如何让Ansible并行运行多个服务部署步骤?
问题:如何让Ansible并行执行独立服务的部署步骤块?
我有一个用于部署测试代码的长Ansible Playbook,由多个基本独立的服务部署步骤组成:
# steps for service 1 - file: # setup config dir for service1 - template: # setup config file for service1 - community.docker.docker_image: # get the image1 - community.docker.docker_container: # have the image1 started # steps for service 2 - file: # setup config dir for service2 - template: # setup config file 1 for service2 - template: # setup config file 2 for service2 - community.docker.docker_image: # get the image2 - community.docker.docker_container: # have the image2 started # steps for service 3 - file: # setup config dir for service3 - template: # setup config file 1 for service3 - template: # setup config file 2 for service3 - community.docker.docker_image: # get the image3 - community.docker.docker_container: # have the image3 started
当前该Playbook会按顺序执行所有步骤,耗时较长。我想通过简便方式让Ansible并行运行每个服务对应的步骤块,实现类似Shell中后台执行任务再等待的效果:
block1 & # does service1 stuff block2 & # does service2 stuff block3 & # does service3 stuff wait; wait; wait
我是Ansible新手,可能缺少相关重构知识,请问该如何实现?
解决方案
可以实现,推荐两种简便的方式:
方法一:用async+poll配合block打包服务步骤
把每个服务的部署步骤封装成block,通过异步执行(async)让每个block在后台运行,最后统一等待所有异步任务完成。
示例重构后的Playbook:
# 启动所有服务的异步部署任务 - name: 异步部署服务1 block: - file: # setup config dir for service1 - template: # setup config file for service1 - community.docker.docker_image: # get the image1 - community.docker.docker_container: # have the image1 started async: 300 # 任务超时时间(秒),根据实际部署耗时调整 poll: 0 # 立即返回,不等待任务完成 register: service1_job - name: 异步部署服务2 block: - file: # setup config dir for service2 - template: # setup config file 1 for service2 - template: # setup config file 2 for service2 - community.docker.docker_image: # get the image2 - community.docker.docker_container: # have the image2 started async: 300 poll: 0 register: service2_job - name: 异步部署服务3 block: - file: # setup config dir for service3 - template: # setup config file 1 for service3 - template: # setup config file 2 for service3 - community.docker.docker_image: # get the image3 - community.docker.docker_container: # have the image3 started async: 300 poll: 0 register: service3_job # 等待所有异步任务完成 - name: 等待服务1部署完成 async_status: jid: "{{ service1_job.ansible_job_id }}" register: service1_result until: service1_result.finished retries: 30 # 重试次数,和async时间对应(30*10=300秒) delay: 10 - name: 等待服务2部署完成 async_status: jid: "{{ service2_job.ansible_job_id }}" register: service2_result until: service2_result.finished retries: 30 delay: 10 - name: 等待服务3部署完成 async_status: jid: "{{ service3_job.ansible_job_id }}" register: service3_result until: service3_result.finished retries: 30 delay: 10
方法二:将每个服务封装为Role,异步调用Role
如果后续服务会复用,更推荐把每个服务的部署逻辑拆成独立的Role,然后通过异步方式调用这些Role,实现并行:
- 先创建三个Role:
roles/service1、roles/service2、roles/service3,把对应服务的步骤放到各自Role的tasks/main.yml中。 - 在主Playbook中异步调用Role:
- name: 异步部署服务1 import_role: name: service1 async: 300 poll: 0 register: service1_job - name: 异步部署服务2 import_role: name: service2 async: 300 poll: 0 register: service2_job - name: 异步部署服务3 import_role: name: service3 async: 300 poll: 0 register: service3_job # 等待逻辑和方法一完全一致 - name: 等待服务1部署完成 async_status: jid: "{{ service1_job.ansible_job_id }}" register: service1_result until: service1_result.finished retries: 30 delay: 10 # 省略服务2、3的等待步骤...
注意事项
async的时间要设置足够长,确保服务部署能在超时前完成;retries和delay的乘积建议等于或略大于async时间,避免提前终止等待;- 这种方式是在同一主机上并行执行多个任务块,如果是多主机部署,Ansible本身默认会按主机并行,结合这种方式能进一步提升效率。
内容的提问来源于stack exchange,提问作者Adam Kotwasinski
相关产品推荐
相关产品推荐

