Ansible 配置并行 - 项目管理笔记
概述
在 Ansible 项目管理中,合理配置并行执行策略对提升效率和控制风险至关重要。Ansible 提供了多种方式来控制任务的执行方式,包括并发连接数控制、分批滚动执行和异步任务处理。
Playbook 执行顺序机制
基本执行流程
- Ansible 按照 Playbook 中定义的顺序执行各个 play
- 每个 play 中,所有主机会分批执行第一个任务,直到所有批次完成该任务
- 然后所有主机再分批执行下一个任务,依此类推
- 只有当所有主机完成所有任务后,Ansible 才会释放 shell 控制
潜在问题
- 当 play 目标主机数量很大时(数百台),控制节点负载会显著增加
- 所有主机同时执行可能导致服务中断风险(如同时更新所有 Web 服务器)
配置 forks 控制并发连接
基本概念
forks
参数控制 Ansible 同时建立的最大连接数,默认值为 5
# 查看当前 forks 设置
ansible-config dump | grep FORKS
# 查看配置文件中的设置(默认为 5)
grep forks /etc/ansible/ansible.cfg
配置建议
- Linux 受管主机:大多数任务在受管主机上运行,控制节点负载较小,可将 forks 设置为较高值(接近 100)
- 网络设备:大多数任务在控制节点上运行,负载较大,应保持较低的 forks 值
使用示例
清单内容:
controller
[webs]
node1
node3
[dbs]
node2
node4
剧本内容:
---
- name: connection
hosts: all
tasks:
- name: conneciton 1
shell: sleep 5 # 模拟耗时任务,执行5秒
- name: conneciton 2
debug:
msg: connection 2 # 快速执行的任务
执行命令:
ansible-playbook playbook.yaml -f 2 # 使用2个并行连接执行
执行结果:
- 第一个任务:controller 和 node1 同时完成,然后 node3 和 node2 同时完成,最后 node4 完成
- 第二个任务:由于执行速度快,5台主机几乎同时完成
配置 serial 实现滚动更新
使用场景
当需要对服务进行更新且要求保持服务可用性时,使用 serial
关键字实现分批滚动更新
使用示例
---
- name: Rolling update
hosts: all
serial: 2 # 每次更新2台主机,确保服务连续性
tasks:
- name: latest apache httpd package is installed
yum:
name: httpd
state: latest # 安装最新版本的httpd
notify: restart apache # 触发处理器
handlers:
- name: restart apache
service:
name: httpd
state: restarted # 重启apache服务
百分比配置
serial: "30%" # 按主机总数的百分比设置批次大小,确保至少1台主机
配置 async 实现异步任务
使用场景
适用于执行时间较长的任务(如大文件下载、系统重启等)
参数说明
async
: 任务执行的最大超时时间(秒)poll
: Ansible 检查任务状态的间隔时间(秒),默认 15
使用示例
示例1:任务超时(失败)
---
- name: connection
hosts: node1
tasks:
- name: conneciton
shell: sleep 10 # 任务需要10秒完成
async: 5 # 但只等待5秒,任务会超时失败
poll: 2 # 每2秒检查一次任务状态
示例2:后台下载(不等待)
---
- name: connection
hosts: node1
tasks:
- name: download
get_url:
url: http://192.168.48.100/ISOS/openEuler-24.03-LTS-x86_64-dvd.iso # 大文件下载
dest: /home/laoma
async: 100 # 设置100秒超时
poll: 0 # 不轮询检查,立即继续后续任务(后台执行)
示例3:同步执行(默认行为)
---
- name: connection
hosts: node1
tasks:
- name: conneciton
shell: sleep 10 # 任务需要10秒完成
async: 0 # 设置为0表示使用默认同步行为
poll: 2 # 每2秒检查一次任务状态
使用 wait_for 模块监控条件
文件存在检查
---
- name: test wait for
hosts: node1
tasks:
- shell: sleep 10 && touch /tmp/hello # 后台创建文件
async: 20 # 设置20秒超时(大于sleep时间)
poll: 0 # 不轮询,立即继续
register: out # 注册任务输出
- name: wait for create /tmp/hello
wait_for:
path: /tmp/hello # 等待文件创建
state: present # 检查文件存在
delay: 5 # 开始检查前的延迟时间(秒)
timeout: 30 # 总超时时间
sleep: 2 # 检查间隔
端口可用性检查(系统重启场景)
---
- name: test wait_for
hosts: node1,node2
tasks:
- name: reboot node1
shell: shutdown -r now "Ansible updates triggered" # 重启节点
async: 1 # 短暂超时
poll: 0 # 不等待,立即继续
when: inventory_hostname == "node1" # 只在node1上执行
- name: wait for node1 come back
wait_for:
host: node1 # 等待的主机
port: 22 # 检查的端口(SSH)
state: started # 等待端口可用
delay: 10 # 开始检查前的延迟(给重启留时间)
sleep: 2 # 检查间隔
timeout: 300 # 总超时时间(5分钟)
when: inventory_hostname == "node2" # 在node2上执行等待
使用 async_status 模块跟踪异步任务
基本用法
---
- name: test async_status
hosts: node1
tasks:
- shell: sleep 10 # 后台任务
async: 20 # 设置20秒超时
poll: 0 # 不轮询,立即继续
register: out # 注册任务输出
- name: wait for
async_status:
jid: "{{ out.ansible_job_id }}" # 通过任务的ansible_job_id属性跟踪
register: job_result # 注册检查结果
until: job_result.finished # 直到任务完成
retries: 30 # 最大重试次数
delay: 2 # 重试间隔(秒)
参数说明
retries
: 最大重试次数(默认 3)delay
: 重试间隔时间(默认 5 秒)
执行效果如下图:(共尝试六次,前五次失败,第六次成功)
总结
result.finished # 直到任务完成
retries: 30 # 最大重试次数
delay: 2 # 重试间隔(秒)
### 参数说明
- `retries`: 最大重试次数(默认 3)
- `delay`: 重试间隔时间(默认 5 秒)
执行效果如下图:(共尝试六次,前五次失败,第六次成功)
[外链图片转存中...(img-e1VDi2xZ-1755615838824)]
## 总结
通过合理配置 forks、serial、async 等参数,结合 wait_for 和 async_status 模块,可以在项目执行效率和服务稳定性之间找到最佳平衡点,实现高效的 Ansible 自动化管理。