如何在Ansible中并行执行localhost的VMware虚拟机启动任务?
问题描述
我正在使用Ansible的community.vmware.vmware_guest_powerstate模块启动虚拟机,但单台虚拟机启动耗时2-5秒,启动50台时效率极低。请问有没有办法实现并行执行?
我的Playbook:
- 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: "设置虚拟机状态为{{ requested_state }}(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 [设置虚拟机状态为powered-on(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)
解决方案
可以通过以下几种方式实现并行启动虚拟机,大幅提升效率:
1. 使用异步任务(Async)
通过async和poll参数将每个虚拟机的启动任务设为异步执行,让Ansible同时处理多个任务,而非串行等待每个任务完成。
修改后的Playbook示例:
- 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: "异步启动虚拟机" community.vmware.vmware_guest_powerstate: username: "{{ username }}" password: "{{ password }}" hostname: "{{ server_url }}" datacenter: "DC1" validate_certs: no name: "{{ item }}" state: "powered-on" loop: "{{ hostlist }}" async: 300 # 设置异步任务超时时间(秒),可根据虚拟机实际启动耗时调整 poll: 0 # 提交任务后立即返回,不等待当前任务完成 register: vm_start_tasks - name: "等待所有虚拟机启动完成" ansible.builtin.async_status: jid: "{{ item.ansible_job_id }}" loop: "{{ vm_start_tasks.results }}" register: vm_results until: vm_results.finished retries: 30 # 重试次数,配合delay参数控制等待逻辑 delay: 10 # 每次重试间隔(秒)
说明:
async: 300确保每个异步任务有足够时间完成(覆盖单台2-5秒的启动耗时)poll: 0让Ansible同时提交所有启动任务,无需等待单台完成- 第二个任务通过
async_status轮询所有异步任务状态,直到全部完成
2. 调整Ansible并发数(Forks)
Ansible默认并发数(forks)为5,意味着同时最多执行5个任务。可通过以下方式增大并发数:
方法一:命令行参数指定
执行Playbook时通过-f参数设置并发数:
ansible-playbook -f 50 your_playbook.yml
方法二:在Playbook中配置
在Playbook开头添加forks参数:
- hosts: localhost forks: 50 # 设置并发数为50 gather_facts: false # 其余配置保持不变
方法三:修改全局配置(ansible.cfg)
在ansible.cfg中修改默认forks值:
[defaults] forks = 50
3. 可选优化细节
- 避免重复调用
lookup:原Playbook中任务重复使用lookup('ansible.builtin.env'),直接引用vars里的username和password即可,减少不必要的计算 - 确认vCenter API限制:vCenter本身有API请求并发上限,需确保设置的并发数不超过vCenter的限制(默认上限通常足够处理50台虚拟机的启动请求)
内容的提问来源于stack exchange,提问作者chenchuk
相关产品推荐
相关产品推荐

