如何提取Ansible inventory其他主机IP供Jinja2模板使用
Ansible角色Jinja2模板引用其他主机组IP的实现方法
核心靠Ansible自带的两个内置魔法变量实现,不需要额外开发插件:
groups:按主机组名返回组内所有主机名的列表hostvars:存储所有主机的变量信息,通过主机名索引就能拿到对应主机的IP等配置
具体操作步骤
- 第一步:规范Inventory主机清单配置
你原来的清单格式可以调整为标准的YAML嵌套结构,如果主机名不能直接解析,加上ansible_host参数指定节点实际IP即可:
all: children: web: hosts: web01: # 这里也可以直接写实际IP,比如192.168.1.10 ansible_host: 192.168.1.10 # 节点实际SSH连接/业务通信IP vars: ansible_user: root ansible_ssh_private_key_file: /path/to/web_ssh_key lb: hosts: lb01: ansible_host: 192.168.1.20 vars: ansible_user: root ansible_ssh_private_key_file: /path/to/lb_ssh_key
- 第二步:在lb组对应的Jinja2模板中编写取值逻辑
注意Ansible的Jinja2模板变量标准格式是{{ 变量名 }},不要加额外的$前缀。- 场景1:web组只有1台节点,直接取单节点IP即可,模板示例:
upstream web { server {{ hostvars[groups['web'][0]]['ansible_host'] | default(groups['web'][0]) }}; }
逻辑说明:groups['web'][0]取web组下第一台主机的主机名,优先从hostvars里读该主机配置的ansible_host作为IP,如果你直接把IP写在清单的主机名位置、没配ansible_host,default过滤器会直接取主机名本身作为IP,兼容两种写法。
- 场景2:web组有多台节点需要批量加入upstream,用for循环遍历即可,模板示例:
upstream web { {% for web_node in groups['web'] %} server {{ hostvars[web_node]['ansible_host'] | default(web_node) }}; {% endfor %} }
渲染后会自动为每台web节点生成一行server配置,直接适配Nginx、HAProxy等负载均衡配置格式。
- 第三步:Playbook正常调用template模块渲染即可
不需要传额外参数,模板里可以直接访问内置变量,参考示例:
- name: 部署LB节点负载均衡配置 hosts: lb tasks: - name: 渲染LB配置文件 template: src: lb_config.conf.j2 dest: /etc/nginx/conf.d/web_lb.conf mode: '0644' notify: reload nginx handlers: - name: reload nginx systemd: name: nginx state: reloaded
注意事项
- 如果执行playbook时加了
--limit lb参数只跑lb组,需要提前执行一次全量主机的setup模块采集事实,或者开启Ansible事实缓存,否则hostvars中缺失web组的变量信息会报取值错误。- 跨主机取IP优先用清单里配置的
ansible_host,不要用ansible_default_ipv4.address这类自动采集的网卡IP,避免因为网卡路由、多网卡配置导致取到错误IP。- 如果web组自定义了业务IP变量(比如
web_biz_ip),直接把模板里的ansible_host替换成你的自定义变量名即可。
内容的提问来源于stack exchange,提问作者Brad Filipchyk
相关产品推荐
相关产品推荐

