ansible 通过 gather_facts 精准采集元数据驱动条件发布,需控制采集范围、防御变量未定义、设计简洁条件逻辑,并可扩展自定义 facts。

在 Linux 中用 Ansible 的 gather_facts 自动采集目标主机元数据,并据此驱动条件分支发布,核心在于“采集要准、变量要稳、判断要简、执行要稳”。这不是单纯开启 facts 就能跑通的事,而是涉及采集范围控制、变量存在性防护、条件逻辑设计和执行上下文一致性的一整套实践。
明确开启并按需精简 facts 采集
默认情况下,Ansible 每个 play 开头都会自动运行 setup 模块收集全量 facts(存入 ansible_facts 字典),但全量采集耗时且常因网络、权限或容器环境失败。生产中应主动收敛:
- 保留
gather_facts: true(不显式关闭),避免后续任务突然缺失变量 - 用
gather_subset锁定必需子集,例如:gather_subset: ["mininal", "hardware"]—— 获取 OS、架构、主机名、CPU、内存等硬信息,跳过易超时的 network/virtual 探测 - 若确定某台主机无网络或为容器(如 Podman rootless),显式排除:
gather_subset: ["!network", "!virtual", "mininal"]
安全引用 facts 变量,避免 undefined 报错
facts 是只读的,且一旦 gather_facts: false 或采集失败,ansible_facts 及其下字段(如 ansible_distribution)将完全不存在。直接引用会报错。必须做防御性处理:
- 用
default过滤器兜底,例如:{{ ansible_facts['distribution'] | default('Unknown') }}{{ ansible_facts['memtotal_mb'] | default(0) }} - 条件判断前先检查键是否存在:
when: ansible_facts is defined and ansible_facts['os_family'] == 'RedHat' - 不依赖
ansible_os_family等旧式扁平变量(Ansible 2.12+ 已统一归入ansible_facts),统一走字典路径
用 facts 驱动清晰的条件分支发布逻辑
元数据不是摆设,要直接映射到部署决策。常见可靠用法:
- 按操作系统分发不同软件包:
when: ansible_facts['os_family'] == 'Debian'→ 用apt模块when: ansible_facts['os_family'] == 'RedHat'→ 用yum或dnf模块 - 按内存容量调整服务配置:
when: ansible_facts['memtotal_mb'] | int > 8192→ 启用高内存 JVM 参数when: ansible_facts['memtotal_mb'] | int → 使用轻量级配置模板 - 按 CPU 核心数设置进程数:
workers: "{{ ansible_facts['processor_vcpus'] | int | default(2) }}",再传给服务配置文件
必要时补充自定义 facts 增强元数据维度
标准 facts 不包含业务侧指标(如应用版本、集群角色、机房区域)。可通过以下方式注入:
- 在目标主机
/etc/ansible/facts.d/下放置 JSON 文件(如app.fact),内容:{"role": "api", "env": "prod", "version": "2.4.1"} - 在 play 中启用加载:
fact_path: /etc/ansible/facts.d
或显式调用:- setup: gather_subset: "!all" # 先跳过默认采集<br>- include_vars: /etc/ansible/facts.d/app.fact
- 之后即可用
{{ ansible_local.app.role }}或{{ ansible_facts['app']['role'] }}参与分支判断











