为什么 Ansible playbook 执行慢如何开启 fact 缓存优化性能

文章导读
Ansible playbook 执行慢通常是因为每次运行都重新通过 SSH 收集主机事实(facts),开启 fact 缓存可以避免重复收集。适用场景是多主机、频繁执行的 playbook,风险是缓存过期可能导致事实信息不准确。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

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 会重新收集事实。

为什么 Ansible playbook 执行慢如何开启 fact 缓存优化性能

第四步:清除旧缓存(可选)。

如果主机信息变更,手动删除缓存目录中的文件或执行 redis flush 命令,避免使用旧事实。

怎么验证是否生效

查看缓存目录是否有文件生成。

对于 jsonfile 后端,检查 /tmp/ansible_facts 目录下是否有以主机名命名的 JSON 文件。对于 redis 后端,使用 redis-cli keys 查看键值。

观察 playbook 输出中是否跳过 facts 收集。

使用 -vvv 参数运行 playbook,如果看到 ok 而不是 changed 且没有 setup 模块的详细执行日志,说明命中缓存。

对比两次运行时间。

首次运行后,第二次运行相同 playbook,总耗时应明显减少,尤其是 Gathering facts 阶段。

常见坑

缓存过期导致事实不准。

如果主机 IP 变更或软件版本更新,缓存未过期会导致 playbook 基于旧信息执行,可能引发错误。

权限问题导致缓存写入失败。

为什么 Ansible playbook 执行慢如何开启 fact 缓存优化性能

确保运行 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