启用 fact_caching 并选择合适的后端(如 jsonfile 或 redis),能让 Ansible 在缓存有效期内直接读取主机信息,避免重复执行 setup 模块,适合主机数量多或网络延迟高的场景。
先说结论:通过配置缓存插件,Ansible 可以将收集到的主机事实存储起来,后续执行时若缓存未过期则直接读取,从而减少 SSH 连接和模块执行开销。
- 先定位:确认当前 playbook 执行中 fact 收集是否占用了较多时间(通常在使用 gather_facts 默认开启时)。
- 先做:在 ansible.cfg 中设置 fact_caching 插件及连接参数,并设定合理的超时时间。
- 再验证:运行 playbook 观察执行日志,确认事实是从缓存加载而非重新收集。
命令速用版
最直接的配置方式是修改项目目录下的 ansible.cfg 文件,添加以下配置片段:
[defaults]
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 86400如果希望临时通过环境变量启用(无需修改配置文件):
export ANSIBLE_FACT_CACHING=jsonfile
export ANSIBLE_FACT_CACHING_CONNECTION=/tmp/ansible_facts
ansible-playbook site.yml为什么会这样
Ansible 默认会在 playbook 执行前对目标主机运行 setup 模块收集事实信息(如 IP 地址、操作系统版本等)。当主机数量较多或网络延迟较高时,这一步骤会消耗大量时间。开启 fact_caching 后,Ansible 会将收集到的事实存储到指定后端(本地文件、Redis 等)。在缓存有效期内,Ansible 会优先读取缓存数据,避免重复通过 SSH 执行 Python 脚本收集信息。
分步处理
1. 选择缓存后端
对于单机或简单场景,jsonfile 最简单,无需额外服务;对于多控制节点或并发场景,建议使用 redis 或 memcached。
2. 修改配置文件
在 ansible.cfg 的 [defaults] 段落中添加配置。如果使用 redis,需安装 ansible 的 redis 依赖库并设置连接地址:
fact_caching = redis
fact_caching_connection = localhost:6379:0
fact_caching_prefix = ansible_facts
fact_caching_timeout = 72003. 管理缓存生命周期
缓存不是永久的,需要设置 timeout(单位秒)。如果需要手动清除缓存,不同后端处理方式不同:
- jsonfile 后端:直接删除缓存目录下的文件。
rm -rf /tmp/ansible_facts/* - redis 后端:使用 redis-cli 清除对应数据库。
redis-cli FLUSHDB
4. 调整 Playbook 策略
确保 playbook 中没有强制设置 gather_facts: no,否则 Ansible 不会尝试收集或使用缓存事实。如果某些任务确实不需要事实,可在特定 play 中关闭,但全局缓存配置仍建议保留。
怎么验证是否生效
1. 检查缓存文件
如果使用 jsonfile,查看配置的连接目录(如 /tmp/ansible_facts)下是否生成了以主机名命名的文件。
2. 观察执行输出(关键)
使用 -vvv 参数运行 playbook,对比首次运行和二次运行的日志输出差异:
- 缓存未命中(首次):日志中会显示完整的 facts 收集过程。
TASK [Gathering Facts] ********************************************************* ok: [target_host] - 缓存命中(二次):在 verbose 模式下,可能观察到 facts 加载行为,且任务执行时间显著缩短(接近 0 秒)。
TASK [Gathering Facts] ********************************************************* ok: [target_host] (Loading facts)
3. 验证事实准确性
在 playbook 中打印某个事实变量(如 ansible_hostname),修改主机名后清除缓存再运行,确认变量值是否更新,以验证缓存刷新机制是否正常。
常见坑
1. 事实信息过期
如果主机 IP 变更或安装了新软件,缓存中的事实可能不准确。务必根据实际变更频率设置合理的 timeout,不要设置过长。
2. 权限问题
jsonfile 后端需要 Ansible 运行用户对缓存目录有写入权限。如果在 CI/CD 环境中运行,注意临时目录的清理和权限隔离。
3. 安全性风险
避免使用 pickle 后端,因为它存在反序列化漏洞风险。官方文档也建议优先使用 json 或 redis 等安全后端。
4. 与 gather_facts 的混淆
启用缓存不代表可以随意关闭 gather_facts。如果 playbook 中显式设置了 gather_facts: no,Ansible 将不会收集事实,也就不会更新或使用缓存中的事实数据,可能导致后续任务因缺少变量而失败。
5. 清除缓存命令失效
旧版文档中提到的 ansible all -m setup -a "clear_facts=yes" 在现代版本中可能无法清除持久化缓存文件,建议直接操作文件系统或 Redis 数据库。
参考来源
- Ansible 官方文档 - Configuration Settings: https://docs.ansible.com/ansible/latest/reference_appendices/config.html
- Ansible 官方文档 - Setup Module: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/setup_module.html