慢在哪里
playbook 的执行时间由三部分构成:每次任务的连接与传输开销、模块本身的工作量、以及控制节点等待目标机返回的时间。默认 forks 只有 5,意味着即使有 200 台主机,同时推进的也只有 5 台;再加上每台每任务都重新建立 SSH 连接,时间大半花在握手而不是做事。性能调优的顺序就是先消掉这些固定开销,再考虑减少任务数。
基本信息
| 并发度 | forks,默认 5,可在 ansible.cfg 或命令行调整 |
|---|---|
| 连接复用 | ssh 的 ControlPersist,让多次任务共用一条底层连接 |
| 减少往返 | pipelining,把模块代码与参数一起送去而不是分多次传输 |
| 执行策略 | strategy: linear(默认)与 free(各主机独立推进) |
| 耗时定位 | 启用计时类回调插件,输出每个任务的耗时排行 |
| 采集开销 | gather_facts 与缓存配置,节点多时影响明显 |
典型使用场景
- 清单从几十台涨到几百台,执行时间线性增长:先加大 forks 并确认连接复用
- 每次运行开头采集事实就占掉可观时间:改用事实缓存或按需采集
- 个别任务明显拖慢整体:用计时回调找出它,单独优化或改异步
- 主机之间没有依赖关系,不必等最慢的那台:改用 free 策略让快的先往下走
- 长耗时任务(备份、编译)阻塞整批推进:改成异步加轮询
- 控制节点 CPU 与内存有富余,目标机压力可控时,才有继续加并发的前提
常用配置与开关
常用配置与开关
# ansible.cfg
[defaults]
forks = 50 # 并发主机数,按控制节点与目标机承受力调
strategy = linear # 依赖严格顺序时保留 linear
[ssh_connection]
pipelining = True # 减少一次往返;配合提权时需目标机允许
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
# 关闭不必要的事实采集(yaml 片段)
# - hosts: web
# gather_facts: false
# tasks:
# - name: 只做一件事
# ansible.builtin.service:
# name: app
# state: restarted
# 多台无关主机并行推进
# ansible-playbook site.yml -f 50 --limit web手段与收益对照
| 手段 | 主要收益 | 代价与前提 |
|---|---|---|
| 提高 forks | 并发推进更多主机,总时长明显下降 | 控制节点 CPU/内存与目标机负载上升 |
| ControlPersist 复用 | 省掉每次任务的 SSH 握手 | 需 ssh 插件;连接超时参数要合理 |
| pipelining | 每个任务少一次往返 | 提权场景需目标机 sudoers 不要求 tty |
| 事实缓存或关采集 | 省掉重复探测 | 缓存会带来陈旧值,关掉后依赖事实的条件会失效 |
| strategy: free | 主机各跑各的,不被最慢主机拖住 | 任务间的顺序假设不再成立,日志交错更难读 |
| 异步任务 | 长任务不阻塞整体推进 | 需要轮询与结果检查,失败处理更复杂 |
优化前先量化:打开计时类回调插件跑一次,拿到每个任务的耗时排名。常见结论是少数几个任务占了大部分时间,先处理这几个,比调整全局参数更有效。回调配置项名称在版本间有过变化,以官方文档为准。
把 forks 一次性从 5 提到几百,往往先压垮的是控制节点内存或目标机的 SSH 连接数,甚至触发目标机连接限流导致任务失败。应当分档上调,边调边观察目标机负载与失败率。
优化顺序
先看清单规模与机器的承载能力定 forks;再确保连接复用与减少往返的开关生效;然后砍掉不需要的事实采集;最后才动结构性的东西(free 策略、异步、把多个小任务合并成一次调用)。顺序颠倒的话,结构性改动带来的复杂度先落地,收益反而不确定。