Ansible playbook 执行慢通常是因为每次运行都重新通过 SSH 收集主机事实(facts),开启 fact 缓存可以避免重复收集。适用场景是多主机、频繁执行的 playbook,风险是缓存过期可能导致事实信息不准确。
先说结论:开启 fact 缓存是解决 Ansible 重复收集事实导致慢的最有效配置项,能显著减少 SSH 连接和模块执行开销。
- 先定位:确认 playbook 是否包含 gather_facts 任务且执行频率高
- 先做:在 ansible.cfg 中配置 fact_caching 和 backend 连接信息
- 再验证:对比开启缓存前后的执行时间并检查缓存文件生成
命令速用版
直接在 ansible.cfg 配置文件中添加以下段落即可启用本地文件缓存:
[defaults]
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 86400若使用 Redis 缓存,需安装 redis 插件并配置连接地址:
[defaults]
fact_caching = redis
fact_caching_connection = 127.0.0.1:6379
fact_caching_timeout = 86400为什么会这样
Ansible 默认在 playbook 开始时对每个主机执行 setup 模块收集事实信息。
每次运行 playbook 都会建立 SSH 连接并执行 Python 脚本收集系统信息,主机数量越多耗时越长。开启缓存后,Ansible 会读取本地或远程存储的旧事实,跳过网络收集步骤,从而减少执行时间。公开资料中没有看到可靠的量化数据,但减少网络 IO 通常能明显降低总耗时。
分步处理
第一步:确认当前执行耗时。
使用 ansible-playbook 命令添加 `--start-at-task` 或直接在输出中观察 Gathering facts 阶段的时间占比。
第二步:编辑 ansible.cfg 配置文件。
在项目根目录或/etc/ansible/ansible.cfg 的 [defaults] 段落中添加 fact_caching 配置。确保 fact_caching_connection 指定的目录存在且 Ansible 用户有写入权限。
第三步:设置缓存超时时间。
通过 fact_caching_timeout 设置缓存有效期(秒),默认 86400 秒(24 小时)。过期后 Ansible 会重新收集事实。
第四步:清除旧缓存(可选)。
如果主机信息变更,手动删除缓存目录中的文件或执行 redis flush 命令,避免使用旧事实。
怎么验证是否生效
查看缓存目录是否有文件生成。
对于 jsonfile 后端,检查 /tmp/ansible_facts 目录下是否有以主机名命名的 JSON 文件。对于 redis 后端,使用 redis-cli keys 查看键值。
观察 playbook 输出中是否跳过 facts 收集。
使用 -vvv 参数运行 playbook,如果看到 ok 而不是 changed 且没有 setup 模块的详细执行日志,说明命中缓存。
对比两次运行时间。
首次运行后,第二次运行相同 playbook,总耗时应明显减少,尤其是 Gathering facts 阶段。
常见坑
缓存过期导致事实不准。
如果主机 IP 变更或软件版本更新,缓存未过期会导致 playbook 基于旧信息执行,可能引发错误。
权限问题导致缓存写入失败。
确保运行 Ansible 的用户对 fact_caching_connection 指定的路径有读写权限,否则会回退到默认行为。
动态 Inventory 环境需谨慎。
在主机频繁变动的环境中,缓存键可能冲突或失效,建议缩短 timeout 或禁用缓存。
常见问题
如何强制刷新事实缓存?
手动删除缓存文件或设置 fact_caching_timeout 为 0。
删除 jsonfile 缓存目录下的主机文件,或在配置中将 timeout 设为 0 迫使每次重新收集。
gather_facts: no 会影响缓存吗?
不会影响,因为该设置直接禁用事实收集。
如果在 playbook 中设置了 gather_facts: no,Ansible 根本不会尝试收集事实,因此也不会读写缓存。
Redis 缓存比 jsonfile 快吗?
取决于网络环境和并发量,公开资料中没有看到可靠的量化数据。
单机小规模 jsonfile 足够,大规模并发或多控制节点场景 Redis 更适合作为共享缓存。
参考来源
Ansible Documentation - Fact Caching: https://docs.ansible.com/ansible/latest/playbook_guide/playbook_cache.html
Ansible Documentation - Configuration Settings: https://docs.ansible.com/ansible/latest/reference_appendices/config.html