Ansible Fact Caching 配置的全面指南
Ansible 收集托管节点事实信息(facts)的能力对于动态清单、条件执行和详细报告至关重要。然而,在每次 playbook 执行时都运行 gather_facts: true 会显著增加整体 playbook 的运行时间,尤其是在拥有数百或数千台主机的环境中。这种性能瓶颈可以通过 Ansible Fact Caching 有效解决。
事实缓存允许 Ansible 存储前一次运行中收集到的事实信息,并立即在后续运行中重用它们,从而避免了耗时的 SSH 连接和数据收集过程。本指南将详细介绍如何使用两种主要方法配置和利用事实缓存:JSON 文件和 Redis,从而在您的自动化工作流程中实现显著的性能提升。
理解 Ansible Facts 与性能影响
Ansible 使用 setup 模块(或通过 gather_facts: true 隐式地)收集事实信息。这些事实信息包括操作系统详细信息、网络接口、已安装的软件包等。尽管这些信息非常有价值,但通过 SSH 收集它们可能会很慢,尤其是在高延迟连接或管理大量机器时。
关键性能优势: 通过启用缓存,后续的 playbook 运行将从本地缓存(JSON 文件)或快速的内存存储(Redis)中读取事实信息,而不是在远程主机上执行 setup 模块。
事实缓存的配置方法
Ansible 支持通过 ansible.cfg 文件配置多种缓存机制。最常见和最可靠的两种方法是 JSON 文件缓存和 Redis 缓存。
1. JSON 文件缓存(本地存储)
JSON 缓存是最简单的方法,它将事实数据作为序列化文件存储在控制机上。它不需要任何外部服务。
在 ansible.cfg 中配置 JSON 缓存
要启用 JSON 缓存,您必须定义缓存插件并指定文件存储的位置。
[defaults]
# 指定要使用的缓存插件
fact_caching = json
# 指定事实文件将存储的目录
fact_caching_connection = /path/to/ansible_facts_cache
# 设置缓存过期时间(秒)。0 表示永不过期。
fact_caching_timeout = 600
参数解释:
fact_caching = json: 激活内置的 JSON 缓存插件。fact_caching_connection: 此目录必须存在,并且执行 Ansible 的用户必须有写入权限。fact_caching_timeout: 在此示例中,事实信息在 600 秒(10 分钟)后被视为过期,将重新收集。
最佳实践: 确保缓存目录位于快速的本地存储(如 NVMe 驱动器)上,以获得最佳的读/写性能。
2. Redis 缓存(共享、高性能存储)
Redis 是一种常被用作高性能缓存或消息代理的内存数据结构存储。将 Redis 用于事实缓存非常适合团队环境,在这种环境中,多个用户或 CI/CD 流水线需要快速、一致地访问同一缓存。
Redis 缓存的先决条件
- 一个可从 Ansible 控制机访问的运行中的 Redis 服务器。
- 控制机上必须安装 Python
redis库:pip install redis。
在 ansible.cfg 中配置 Redis 缓存
使用 Redis 时,fact_caching_connection 用于定义 Redis 连接参数(主机和端口)。
[defaults]
# 指定要使用的缓存插件
fact_caching = redis
# 连接字符串格式:<host>[:<port>][/<db_number>]
# 如果在同一机器上使用默认端口运行:
fact_caching_connection = 127.0.0.1:6379/0
# 设置缓存过期时间(秒)。强烈推荐用于 Redis。
fact_caching_timeout = 3600
关于 Redis 数据库的说明: 最后的数字(例如 /0)指定要使用的 Redis 数据库索引。确保此索引专用于 Ansible 事实,以防止在 Redis 用于其他目的时发生冲突。
将缓存集成到 Playbooks 中
配置 ansible.cfg 设置的是默认行为。要有效利用缓存,您必须确保 playbook 中有两点:
- 通过运行收集事实的 play 来填充缓存。
- 后续的 play 依赖于缓存而不是重新收集事实。
强制收集事实以进行初始填充
当您第一次运行 playbook,或者在超时后运行 playbook 时,Ansible 将执行事实收集过程。
- name: Play 1 - 收集事实并执行任务
hosts: webservers
gather_facts: true # 这将首先填充缓存
tasks:
- name: 使用收集到的事实
debug:
msg: "OS 家族是 {{ ansible_os_family }}"
在后续运行中利用缓存
如果配置了 fact_caching,并且 gather_facts 设置为 true 且事实信息在超时期限内,后续运行将自动使用缓存的数据。
然而,如果您想保证 Ansible 完全跳过事实收集并仅依赖缓存(如果缓存丢失则失败),在初始填充后,您可以将 gather_facts 设置为 false,前提是事实信息仍然有效。
如果明确设置 gather_facts: false 并且启用了缓存,Ansible 将首先检查缓存。如果存在有效数据,则使用它。如果不存在,它将继续执行而没有事实信息,这可能会破坏依赖于事实的任务。
关键行为: 如果使用 gather_facts: true,只有在缓存的事实信息已过期或丢失时,Ansible 才会执行远程事实收集。
管理事实缓存
有时需要手动清除缓存,强制 Ansible 从所有主机收集最新数据。
清除 JSON 缓存
如果使用 JSON 缓存,只需删除 fact_caching_connection 中指定的目录的内容。
# 使用前面定义的路径进行示例
rm -rf /path/to/ansible_facts_cache/*
清除 Redis 缓存
如果使用 Redis,您可以选择性地清除与 Ansible 相关的键,或清除 Ansible 使用的整个数据库。
要清除与默认 Ansible 前缀相关的所有键(通常与清单源相关):
# 连接到 redis-cli 并刷新整个数据库(此示例中为 DB 0)
redis-cli -n 0 FLUSHDB
警告: 必须非常谨慎地使用 Redis 中的
FLUSHDB或FLUSHALL,因为它会删除指定数据库或整个 Redis 实例中的所有数据。
最佳实践总结
- 明智选择: 对于简单的单用户设置或受外部依赖限制的情况,请使用 JSON 缓存。对于协作环境或大规模 CI/CD 集成,请使用 Redis。
- 设置合理的超时时间: 配置
fact_caching_timeout以平衡性能提升和数据新鲜度。对于配置变化不频繁的环境,1 到 24 小时的超时时间很常见。 - 验证配置: 始终运行
ansible --version或检查首次缓存运行的输出,以确认缓存插件已激活并正常工作。 - 清单依赖: 事实缓存最适用于静态或动态生成的清单。如果使用频繁更改的动态清单脚本,缓存的好处可能会被过期或错误所抵消。
通过正确实施事实缓存,您可以将 Ansible 从一个完全迭代的配置工具转变为一个高度优化的系统,该系统能够以最小的每次运行延迟来管理大规模的基础设施。