Ansible 如何配置 fact_caching 减少收集主机信息的时间?

文章导读
启用 fact_caching 并选择合适的后端(如 jsonfile 或 redis),能让 Ansible 在缓存有效期内直接读取主机信息,避免重复执行 setup 模块,适合主机数量多或网络延迟高的场景。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 参考来源
A A

启用 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 如何配置 fact_caching 减少收集主机信息的时间?

在 ansible.cfg 的 [defaults] 段落中添加配置。如果使用 redis,需安装 ansible 的 redis 依赖库并设置连接地址:

fact_caching = redis
fact_caching_connection = localhost:6379:0
fact_caching_prefix = ansible_facts
fact_caching_timeout = 7200

3. 管理缓存生命周期

缓存不是永久的,需要设置 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)下是否生成了以主机名命名的文件。

Ansible 如何配置 fact_caching 减少收集主机信息的时间?

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. 权限问题

Ansible 如何配置 fact_caching 减少收集主机信息的时间?

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