如何在Ansible Playbook单任务中并行执行命令后再执行下一任务
如何让Ansible任务中针对多主机的命令并行执行,全部完成后再进入下一个任务
现有Playbook与配置文件
原始Ansible Playbook
--- - name: ReadJsonfile hosts: localhost vars: input: "{{ lookup('file','hostinfo.json_pb') | from_json }}" tasks: - name: Image Server(s) command: python3 image.pyc {{item.key}} {{item.value.version}} with_dict: "{{input}}" - name: configure-firstnet on a server command: python3 configure_firstnet.pyc {{item.key}} {{item.value.version}} {{item.value.netconf}} with_dict: "{{input}}"
对应的hostinfo.json配置
{ "hosts": { "abc": { "username": "root", "password": "welcome1", "password2": "WElcome1", "version": "19.17", "toversion" : "19.18.0.0.0", "netconf": "bonding", "baseversion": "18.8.0.0" }, "xyz": { "username": "root", "password": "welcome1", "password2": "WElcome1", "version": "19.18", "toversion" : "19.18.0.0.0", "netconf": "bonding", "baseversion": "18.8.0.0" } } }
需求说明
需要在两台机器上并发执行以下命令,待这两条命令全部执行完成后,再进入下一个configure-firstnet on a server任务:
python3 image.pyc abc 19.17 python3 image.pyc xyz 19.18
尝试过的配置及问题
- 配置1(
poll:10)
--- - name: ReadJsonfile hosts: localhost vars: input: "{{ lookup('file','hostinfo.json_pb') | from_json }}" tasks: - name: Updating the captured data in the default payload file command: python3 updatejson.py - name: Image Server(s) command: python3 image.pyc {{item.key}} {{item.value.version}} register: async_out async: 7200 poll: 10 with_dict: "{{input}}"
问题:Playbook会先等待abc上的image.pyc执行完成,再执行xyz的,无法实现并行。
- 配置2(
poll:0)
- name: Image Server(s) command: python3 image.pyc {{item.key}} {{item.value.version}} register: async_out async: 7200 poll: 0 with_dict: "{{input}}"
问题:任务会立即在两台服务器上启动命令,然后直接进入下一个configure-firstnet on a server任务,不符合“第二个任务依赖前一个任务全部完成”的要求。
解决方案
通过先启动所有异步任务(poll:0),再单独添加任务等待所有异步任务完成的方式实现需求,完整Playbook如下:
--- - name: ReadJsonfile hosts: localhost vars: input: "{{ lookup('file','hostinfo.json_pb') | from_json }}" tasks: - name: Updating the captured data in the default payload file command: python3 updatejson.py - name: 启动异步镜像任务(后台并行执行) command: python3 image.pyc {{item.key}} {{item.value.version}} register: async_out async: 7200 poll: 0 with_dict: "{{ input.hosts }}" # 注意取json中的hosts字段,原input是整个json对象 - name: 等待所有异步镜像任务完成 async_status: jid: "{{ item.ansible_job_id }}" register: async_results until: async_results.finished retries: 720 # 对应async的7200秒,每10秒重试一次,720*10=7200 delay: 10 loop: "{{ async_out.results }}" - name: configure-firstnet on a server command: python3 configure_firstnet.pyc {{item.key}} {{item.value.version}} {{item.value.netconf}} with_dict: "{{ input.hosts }}"
关键说明
- 第一个任务用
poll:0启动所有异步任务,不会等待任务执行,立即返回每个任务的ansible_job_id并注册到async_out中,此时所有任务在后台并行执行。 - 第二个任务通过
async_status模块,遍历所有任务ID轮询状态,until: async_results.finished确保只有当任务完成时才停止轮询,retries和delay控制轮询的次数和间隔,确保覆盖异步任务的超时时间。 - 注意修正
with_dict的取值:原json中的主机信息在hosts字段下,所以应该用{{ input.hosts }}而非{{ input }},否则会遍历整个json的顶级键(如hosts),导致执行错误。
内容的提问来源于stack exchange,提问作者Akash-BLR
相关产品推荐
相关产品推荐

