启用 jsonfile 缓存可避免重复 ssh 连接与 facts 收集,零依赖、易调试、原子写入;redis 易因配置或网络问题静默降级,运维复杂且不必要。

Ansible 默认每次执行 play 都会重新 SSH 登录并运行 setup 模块收集 facts,上百台主机时光连接开销就可能拖慢整个流程。启用本地 JSON 文件缓存是最直接、零依赖的提速方式,不需要部署 Redis 或其他服务。
为什么选 jsonfile 而不是 redis
除非你已有高可用 Redis 集群且团队熟悉运维,否则 jsonfile 是更稳妥的选择:它不引入新服务依赖,缓存文件可直接 ls/cat/rm 调试,权限和路径都透明可控。而 redis 后端一旦连接失败(比如网络抖动、密码变更、端口被封),Ansible 会静默 fallback 到无缓存模式,反而掩盖问题。
-
jsonfile缓存写入是原子的,单机多进程并发读写基本无冲突 -
redis需额外维护连接池、超时、认证,fact_caching_connection格式稍错(比如少个冒号)就会完全失效 - 中小规模(jsonfile 已能将
setup耗时从秒级压到毫秒级
配置 jsonfile 缓存的三步实操
只需改 ansible.cfg 并确保目录可写,无需重启任何服务:
- 在
[defaults]段添加:fact_caching = jsonfile<br>fact_caching_connection = /tmp/ansible_facts<br>fact_caching_timeout = 3600
- 手动创建目录并赋权:
mkdir -p /tmp/ansible_facts && chmod 755 /tmp/ansible_facts(Ansible 不自动建父目录) - 确认
gathering行为:默认是smart,即有缓存就用、过期或不存在才重收;如需强制每次都收,才要显式设gathering = explicit
setup 任务耗时没降?检查这几个点
缓存配置正确但没生效,常见于以下情况:
- play 中写了
gather_facts: no—— 这会跳过整个 facts 流程,自然不读也不写缓存 - 用了
delegate_to: localhost或run_once: true的 task 触发了 facts 收集,但缓存只存inventory_hostname对应的主机名,委托目标不会被缓存 - 缓存文件属主是 root,但当前运行 ansible 的用户是普通账号,导致写入失败(
ls -l /tmp/ansible_facts看是否为空或权限不对) - inventory 中主机名含下划线或大写字母(如
WEB-SERVER-01),而缓存文件名严格按inventory_hostname命名,大小写/符号不匹配会导致“找不到缓存”
缓存过期后怎么精准刷新某台机器
别删全量缓存,也别等 24 小时超时——生产中常需秒级响应:
- 清空单台:
rm -f /tmp/ansible_facts/<code>web01.example.com(注意和 inventory 中定义的 hostname 完全一致) - 强制重收单次:
ansible-playbook site.yml -e ansible_fact_cache=False - 在某个 task 里局部禁用缓存:
- name: Refresh facts for kernel check<br> setup:<br> gather_facts: yes<br> vars:<br> cacheable: false
真正容易被忽略的是:缓存只存 ansible_facts,不存 register 结果、hostvars 计算值或自定义变量。如果你在 playbook 里做了大量 set_fact + 条件判断,这部分逻辑依然照常执行,缓存帮不上忙。











