如何通过多Play(线程化)对同一服务器组运行单个Ansible Playbook
高效在2000台同组服务器运行Ansible Playbook的方案
可行方案:多进程并行执行分组Play
你可以通过启动多个独立的ansible-playbook进程来并行处理不同的服务器子集,比手动分两次执行更高效。比如写个简单的bash脚本拆分更多分组(比如5组,每组400台):
#!/bin/bash # 拆分5组并行执行,每组处理400台服务器 for subset in "20%" "other 20%" "other 20%" "other 20%" "other 20%"; do # 后台执行并将日志输出到独立文件,方便排查问题 ansible-playbook -i prod.ini -l "my_group[$subset]" x.yml > "play_${subset// /_}.log" 2>&1 & done # 等待所有后台进程执行完成 wait echo "所有Play执行完成"
这种方式利用操作系统的进程并行能力,绕过了Ansible单进程内Play串行执行的限制。
为什么调大forks到500-1000没效果?
调大forks后性能无提升,大概率是遇到了以下瓶颈:
- 控制机资源耗尽:同时启动上千个SSH连接会吃满控制机的CPU、内存或网络带宽,导致任务排队等待,反而拖慢整体速度。你可以用
top、iftop实时监控控制机状态,确认是否有资源跑满的情况。 - 目标机SSH连接限制:默认的sshd配置(
MaxStartups、MaxSessions)会限制同时连接数,太多并发连接会被目标机拒绝,触发Ansible重试,反而增加耗时。 - 未开启SSH连接复用:如果没配置SSH长连接复用,每个fork都要新建SSH连接,这部分开销在大数量主机场景下会被放大,调大forks也无法抵消连接建立的成本。
关键优化措施
1. 开启SSH连接复用
这是提升大集群执行效率的核心,在ansible.cfg中添加以下配置:
[ssh_connection] ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ControlPath=/tmp/ansible-ssh-%h-%p-%r scp_if_ssh = True
复用连接能把每个主机的SSH连接建立开销从秒级降到毫秒级,配合100-200的forks值,性能会有质的提升。
2. 调整目标机SSH配置
在所有目标机的/etc/ssh/sshd_config中修改连接限制:
MaxStartups 100:30:200 # 允许最多200个初始连接,超过30%概率拒绝新连接 MaxSessions 100 # 每个用户最多允许100个并发会话
修改后重启sshd服务,避免因连接数超限被目标机拒绝。
3. 优化Playbook本身
- 如果不需要收集系统facts,在Play开头加上
gather_facts: no,跳过facts收集步骤。 - 尽量用
command/shell模块替代高开销模块(比如简单文件传输可以用scp结合command,场景允许的话)。 - 启用fact缓存,避免重复收集:
[defaults] gathering = smart fact_caching = jsonfile fact_caching_connection = /tmp/ansible_facts_cache fact_caching_timeout = 86400 # 缓存有效期设为1天
4. 合理控制并行度
不要盲目开太多进程或调大forks,建议根据控制机性能调整:
- 控制机CPU核心数8核以上:分成4-6组,每组300-500台,forks设为150-200。
- 控制机资源一般:分成8组,每组250台,forks设为100左右。
内容的提问来源于stack exchange,提问作者Seedtefan
相关产品推荐
相关产品推荐

