ansible fact caching 通过本地或远程缓存已收集的 ansible_facts,避免重复ssh连接和远程执行setup模块,显著降低大规模部署时的开销。

Ansible fact caching 为什么能加速大规模执行
默认情况下,Ansible 每次运行 setup 模块(或任何触发 fact 收集的任务)都会重新 SSH 登录目标主机、执行 /usr/bin/python(或 python3)脚本、解析系统信息——这在几百台机器上重复做一遍,光建立连接和序列化开销就非常可观。启用 fact caching 后,Ansible 会把收集到的 facts 存到本地(或远程)缓存后端,后续运行只要缓存未过期,就直接读取,跳过整个远程收集流程。
注意:它只缓存 ansible_facts(即 setup 输出),不缓存自定义变量、register 结果或任务执行状态。
如何配置 fact caching(以 jsonfile 为例)
jsonfile 是最轻量、无需额外服务、适合中小规模集群的首选后端。它把每个主机的 facts 存为独立 JSON 文件,路径可预测,便于调试和清理。
- 在
ansible.cfg中启用:[defaults] fact_caching = jsonfile fact_caching_connection = /tmp/ansible_facts
- 确保
/tmp/ansible_facts目录存在且当前用户有读写权限(Ansible 不会自动创建父目录) - 首次运行 play 时仍会收集 facts 并写入缓存;第二次起,只要缓存未过期(默认 24 小时),
setup任务耗时会从秒级降到毫秒级 - 缓存文件命名规则为
/tmp/ansible_facts/<inventory_hostname></inventory_hostname>,例如/tmp/ansible_facts/web01.example.com
缓存过期与手动刷新的关键控制点
默认缓存有效期是 24 小时(86400 秒),但生产中常需更精细控制——比如你刚升级内核,需要立刻刷新 facts;或某些主机长期离线,缓存已失效却还在用。
- 修改过期时间:在
ansible.cfg加fact_caching_timeout = 3600(单位秒) - 强制跳过缓存、重新收集:加
-e ansible_fact_cache=False参数,或在 task 中显式调用setup并设gather_facts: yes+cacheable: false - 清空某台主机缓存:直接
rm /tmp/ansible_facts/<hostname></hostname>;清空全部:rm -f /tmp/ansible_facts/* - 注意:
gather_facts: no的 play 完全不触发缓存读写,和 fact caching 无关
大规模场景下 redis 缓存的实际表现与坑
当主机数超 500、并发数 > 50 时,jsonfile 的文件锁和磁盘 I/O 可能成为瓶颈;此时 redis 是更可靠的选择——它支持原子操作、TTL 自动清理、多进程安全读写。
- 安装依赖:
pip install redis - 配置示例:
[defaults] fact_caching = redis fact_caching_connection = localhost:6379:0
-
fact_caching_connection格式为host:port:db,不支持密码认证(需提前配好 Redis ACL 或网络隔离) - Redis key 命名为
ansible_facts_<inventory_hostname></inventory_hostname>,可用redis-cli keys "ansible_facts_*"查看 - 容易被忽略的点:Redis 默认不持久化,重启后缓存全丢——若依赖缓存稳定性,需开启
RDB或AOF;另外,Ansible 不会自动清理过期 key,全靠 Redis 自身 TTL 管理,务必确认redis.conf中maxmemory-policy设置合理(推荐allkeys-lru)
缓存不是银弹:它只对重复收集相同主机 facts 有效;如果 inventory 动态生成、hostname 频繁变化,或者你每轮都用不同 group 过滤,缓存命中率会断崖下跌。上线前务必用 --debug 和 ANSIBLE_DEBUG=1 观察 Using fact cache 日志行是否真实出现。










