【问题标题】:Parallel execution of localhost tasks in Ansible在 Ansible 中并行执行 localhost 任务
【发布时间】:2022-10-22 22:26:12
【问题描述】:

我正在使用 community.vmware.vmware_guest_powerstate 集合让 Ansible 启动 VM。

问题是 1 个 VM 所需的时间可能是 2-5 秒,这使得当我想启动 50 个 VM 时效率非常低...

有没有办法让它并行?

剧本:

- hosts: localhost
  gather_facts: false
  collections:
    - community.vmware
  vars:
    certvalidate: "no"
    server_url: "vc01.x.com"
    username: "{{ lookup('ansible.builtin.env', 'API_USER', default=Undefined) }}"
    password: "{{ lookup('ansible.builtin.env', 'API_PASS', default=Undefined) }}"
  tasks:
    - name: "setting state={{ requested_state }} in vcenter"
      community.vmware.vmware_guest_powerstate:
        username: "{{ lookup('ansible.builtin.env', 'API_USER', default=Undefined) }}"
        password: "{{ lookup('ansible.builtin.env', 'API_PASS', default=Undefined) }}"
        hostname: "{{ server_url }}"
        datacenter: "DC1"
        validate_certs: no
        name: "{{ item }}"
        state: "powered-on"
      loop: "{{ hostlist }}"

这是 Ansible 的输出:(每行可能需要 2-5 秒 ...)

TASK [setting state=powered-on in vcenter] ************************************************************************************************************
Monday 19 September 2022  11:17:59 +0000 (0:00:00.029)       0:00:08.157 ****** 
changed: [localhost] => (item=x1.com)
changed: [localhost] => (item=x2.com)
changed: [localhost] => (item=x3.com)
changed: [localhost] => (item=x4.com)
changed: [localhost] => (item=x5.com)
changed: [localhost] => (item=x6.com)
changed: [localhost] => (item=x7.com)

【问题讨论】:

  • 试试async
  • @VladimirBotka async 将保持 ansible 运行而无需等待,但该过程仍将一个接一个地启动它们......(所以最后一个 vm 在一个巨大的列表中 - 仍然受到......)

标签: performance ansible performance-testing


【解决方案1】:

... 1 个 VM 所需的时间可能是 2-5 秒,这使得当我想启动 50 个 VM 时效率非常低...

对,这是通常的行为。

有没有办法让它并行?

正如 Vladimir Botka 在 cmets 中已经提到的那样,asynchronous actions and polling 值得一试,因为

默认情况下,Ansible 同步运行任务,保持与远程节点的连接处于打开状态,直到操作完成。这意味着在剧本中,每个任务默认阻止下一个任务,这意味着后续任务将在当前任务完成之前不会运行。这种行为会带来挑战。

您可以在任务和循环中看到它。

大概是最佳实践解决用例并消除原因是增强module code

根据文档vmware_guest_powerstate module – Manages power states of virtual machines in vCenter 和源代码ansible-collections/community.vmware/blob/main/plugins/modules/vmware_guest_powerstate.py,参数name: 只为一个VM 取一个名称。如果可以直接向模块提供 VM 名称列表"{{ hostlist }}",则只有一次连接尝试,并且循环发生在远程节点而不是控制器节点(...即使它正在运行 @ 987654332@ 两种情况)。

为此,需要从name=dict(type='list') 而不是str 开始,并实现所有其他逻辑、错误处理和响应。

更多文档

由于社区vmware_guest_powerstate 模块正在导入和使用其他库


同时并基于

进一步的问答和测试

我已经设置了另一个简短的性能测试来模拟您正在观察的行为

---
- hosts: localhost
  become: false
  gather_facts: false

  tasks:

  - name: Gather subdirectories
    shell:
      cmd: "ls -d /home/{{ ansible_user }}/*/"
      warn: false
    register: subdirs

  - name: Gather stats (loop) async
    shell: "stat {{ item }}"
    loop: "{{ subdirs.stdout_lines }}"
    loop_control:
      label: "{{ item }}"
    async: 5
    poll: 0

  - name: Gather stats (loop) serial
    shell: "stat {{ item }}"
    loop: "{{ subdirs.stdout_lines }}"
    loop_control:
      label: "{{ item }}"

  - name: Gather stats (list)
    shell: "stat {% raw %}{{% endraw %}{{ subdirs.stdout_lines | join(',') }}{% raw %}}{% endraw %}"
    register: result

  - name: Show result
    debug:
      var: result.stdout

并发现添加async 会增加一些额外的开销,从而导致执行时间更长。

Gather subdirectories ------------------------ 0.57s
Gather stats (loop) async -------------------- 3.99s
Gather stats (loop) serial ------------------- 3.79s
Gather stats (list) -------------------------- 0.45s
Show result ---------------------------------- 0.07s

这是因为与建立连接的“长”时间相比,执行任务的“短”运行时间。正如文件指出的那样

例如,某项任务可能需要比 SSH 会话允许的时间更长的时间才能完成,从而导致超时。或者,您可能希望在同时执行其他任务的同时在后台执行一个长时间运行的进程。异步模式可让您控制长时间运行的任务的执行方式。

在长时间运行的进程和任务的情况下,可以利用async

【讨论】:

    【解决方案2】:

    试试这个...

    - hosts: all
      gather_facts: false
      collections:
        - community.vmware
      vars:
        certvalidate: "no"
        server_url: "vc01.x.com"
        username: "{{ lookup('ansible.builtin.env', 'API_USER', default=Undefined) }}"
        password: "{{ lookup('ansible.builtin.env', 'API_PASS', default=Undefined) }}"
      tasks:
        - name: "setting state={{ requested_state }} in vcenter"
          community.vmware.vmware_guest_powerstate:
            username: "{{ lookup('ansible.builtin.env', 'API_USER', default=Undefined) }}"
            password: "{{ lookup('ansible.builtin.env', 'API_PASS', default=Undefined) }}"
            hostname: "{{ server_url }}"
            datacenter: "DC1"
            validate_certs: no
            name: "{{ inventory_hostname }}"
            state: "powered-on"
    

    然后使用您的主机列表作为清单运行它并使用分叉:

    ansible-playbook -i x1.com,x2.com,x3.com,... --forks 10 play.yml

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-08
      • 2016-07-19
      • 2016-07-03
      • 2012-01-04
      • 2017-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多