如何使用ansible中的include将循环并行化

时间:2018-11-12 14:22:44

标签: asynchronous ansible

最近,我遇到了我们烦人的剧本代码中的瓶颈。我们正在按顺序部署群集(例如mongoDB Replica Set),即一个虚拟机接一个虚拟机,每个虚拟机都等待上一个虚拟机启动并运行。

这使整个集群的部署时间减慢了一个成员的速度。

为解决这个问题,我开始研究ansible's async actions and pooling,并发现了一些类似我们的方案的并行循环和“ 即弃即用”策略的示例。

特别的是,我们定义了我们自己的“定制VM并生成它” ansible任务(create_instance.yml),该任务被包括在内并从剧本中接收不同的定制变量,并通过运行不同的程序来抽象整个过程KVM / shell命令。

使用"Parallel task execution in Ansible"作为参考,我最终得到了类似的内容:

- name: Generate VMs for DB
  hosts: hypervisor_fe
  tags: platform,mongodb
  tasks:
    - include: tasks/create_instance.yml
      vars:
        vm: "{{ item }}"
      with_items: "{{ mongodb.vms }}"
      register: mongo_instances
      async: 7200
      poll: 0

    - name: Wait for instance creation to complete
      async_status: jid={{ item.ansible_job_id }}
      register: mongo_jobs
      until: mongo_jobs.finished
      retries: 300
      with_items: "{{ mongo_instances.results }}"

但是,此设置似乎确实忽略了所有新的异步代码,并保留了旧的顺序行为。我猜想这与否有关。以及导入任务中的游戏粒度。如果我改为将include替换为单个,明确的长期运行的任务-例如,

- name: Test async operation
  shell: ping -c1 {{ item.hostname }} && sleep 20

这似乎确实可以正常工作,对每个item执行一次ping操作,然后继续执行下一个操作。

这个假设正确吗?有人对include有经验,并且在ansible中进行了异步循环吗?我是否需要将异步声明移到导入代码中的单个播放中?

1 个答案:

答案 0 :(得分:1)

我建议您通过以下方式重新考虑您的剧本设计:

- hosts: localhost
  tasks:
    - add_host:
        name: "{{ item.name }}"
        groups: new_vms
        vm: "{{ item }}"
      with_items: "{{ mongodb.vms }}"

- hosts: new_vms
  tasks:
    - include: create_instance.yml

create_instance.yml内部使用delegate_to: hypervisor_fe

这为您提供了每个虚拟机的本机Ansible主机循环,同时执行每个任务。