You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Ansible清单剧本包含不可达服务器的静态数据?

问题背景

我将服务器清单存储为多个YML文件,每个服务器对应一个文件,示例内容如下:

---

server_data:
  - var_hostname: "linuxbox42"
    var_OS: "Linux"
    var_OS_distro: "RHEL"
    var_OS_version: "9.2"
    (...)

我使用Ansible剧本和Jinja模板在服务器linuxbox01上生成清单CSV文件,相关文件内容如下:

主剧本内容

- name: Create inventory
  hosts: mylinuxservers
  ignore_unreachable: true
  become: true
  gather_facts: yes
  roles:

    - role: linux_create_inventory

输出CSV的任务(属于linux_create_inventory角色)

- name: Output to CSV
  template:
    src: inventory.csv.j2
    dest: /root/inventory.csv
  delegate_to: linuxbox01

Jinja2模板(inventory.csv.j2)

hostname,OS,OS_distro,OS_version, (...)
{% for h in ansible_play_hosts_all %}
{{
    h 
}},{{ 
    hostvars[h]['server_data'][0]['var_OS'] | default('unknown') 
}},{{
    hostvars[h]['ansible_distribution'] | default(hostvars[h]['server_data'][0]['var_OS_distro'])
}},{{
    hostvars[h]['ansible_distribution_version'] | default(hostvars[h]['server_data'][0]['var_OS_version'])
}},{{
(...)

该剧本在安装于linuxbox01的Ansible Tower(AWX)上运行。

遇到的问题

我需要CSV中同时包含Ansible无法连接的服务器,且这些服务器应使用YML文件中的静态数据而非Ansible事实。但当前只要存在不可达服务器,剧本就会全部失败,报错信息如下:

fatal: [linuxbox42 -> linuxbox01]: FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'server_data'"}
fatal: [linuxbox99 -> linuxbox01]: FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'server_data'"}

其中linuxbox42可被Ansible连接,linuxbox99不可达。若仅在全部可达的服务器子列表上运行剧本(通过Ansible Tower任务的"Limit:"设置),则CSV可正常生成。

现在需要解决:如何让Ansible同时考虑不可达服务器的YML文件数据?


解决方案

1. 全局预加载所有服务器的静态YML数据

问题核心是不可达主机的server_data变量未被加载到hostvars中——Ansible默认仅在目标主机执行阶段加载对应主机的变量文件。需要在剧本全局阶段提前加载所有服务器的YML文件,确保无论主机是否可达,变量都存在于hostvars内。

假设静态YML文件存储在inventory_vars/目录下,文件名格式为{{ inventory_hostname }}.yml,修改主剧本如下:

- name: Preload all server static data
  hosts: localhost
  tasks:
    - name: Load each server's YML file
      include_vars:
        file: "inventory_vars/{{ item }}.yml"
        name: server_data_{{ item }}
      loop: "{{ groups['mylinuxservers'] }}"

    - name: Assign static data to each host's hostvars
      set_fact:
        server_data: "{{ lookup('vars', 'server_data_' + item)['server_data'] }}"
      delegate_to: "{{ item }}"
      delegate_facts: true
      loop: "{{ groups['mylinuxservers'] }}"

- name: Create inventory
  hosts: mylinuxservers
  ignore_unreachable: true
  become: true
  gather_facts: yes
  roles:
    - role: linux_create_inventory

2. 优化模板的变量引用逻辑

为避免因变量层级不存在导致报错,需在模板中添加更安全的变量引用逻辑,使用default过滤器覆盖整个嵌套路径的缺失场景。修改后的inventory.csv.j2示例:

hostname,OS,OS_distro,OS_version, (...)
{% for h in ansible_play_hosts_all %}
{% set svr_data = hostvars[h].get('server_data', [{}])[0] %}
{{ h }},{{
    svr_data.get('var_OS', 'unknown')
}},{{
    hostvars[h].get('ansible_distribution', svr_data.get('var_OS_distro', 'unknown'))
}},{{
    hostvars[h].get('ansible_distribution_version', svr_data.get('var_OS_version', 'unknown'))
}},{{
(...)

3. 确认任务执行策略(可选)

确保ignore_unreachable: true参数作用于所有任务,若AWX环境支持,可将剧本策略设置为free,但核心解决措施仍是预加载静态变量。


内容的提问来源于stack exchange,提问作者dr_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 04:55:37