多应用多环境Ansible Inventory合并异常:主机归属错误求助
问题背景
我正在开发支持多应用多环境的Ansible项目,目录结构如下:
/ansible/inventory/ └── ${APPLICATION}/ └── ${ENVIRONMENT}/ └── tomcat_windows_hosts.yml
希望将每个应用的全局变量存在/ansible/inventory/${APPLICATION}目录下避免重复定义,但执行命令:
ansible-inventory -i /ansible/inventory/sampleapp --list --yaml
后出现组归属异常:dev环境的tomcat_windows_hosts组同时包含dev_server和test_server,而test环境的同名组为空。
库存文件内容
dev环境(/ansible/inventory/sampleapp/dev/tomcat_windows_hosts.yml):
all: children: sampleapp: children: dev: children: tomcat_windows_hosts: hosts: dev_server: ansible_host: 192.168.127.19
test环境(/ansible/inventory/sampleapp/test/tomcat_windows_hosts.yml):
all: children: sampleapp: children: test: children: tomcat_windows_hosts: hosts: test_server: ansible_host: 192.168.127.17
预期vs实际输出
预期输出:
all: children: sampleapp: children: dev: children: tomcat_windows_hosts: hosts: dev_server: ansible_host: 192.168.127.19 test: children: tomcat_windows_hosts: hosts: test_server: ansible_host: 192.168.127.17
实际输出:
all: children: sampleapp: children: dev: children: tomcat_windows_hosts: hosts: dev_server: ansible_host: 192.168.127.19 test_server: ansible_host: 192.168.127.17 test: children: tomcat_windows_hosts: {}
原因分析
Ansible加载多个inventory文件时,会按组名全局合并,而非按父组层级区分。两个文件中都定义了tomcat_windows_hosts组,Ansible会将该组的所有主机合并到第一个被加载的实例(dev环境下的同名组),后续出现的同名组因已存在,会被置为空。
解决方案
方案1:给环境专属组添加唯一标识
修改两个inventory文件,给tomcat_windows_hosts组加上环境前缀,确保组名唯一:
dev环境文件修改后:
all: children: sampleapp: children: dev: children: dev_tomcat_windows_hosts: hosts: dev_server: ansible_host: 192.168.127.19
test环境文件修改后:
all: children: sampleapp: children: test: children: test_tomcat_windows_hosts: hosts: test_server: ansible_host: 192.168.127.17
方案2:重构inventory目录结构(推荐)
采用Ansible推荐的目录式inventory组织方式,分离组层级定义与主机列表,同时更方便管理全局变量:
新目录结构
/ansible/inventory/sampleapp/ ├── group_vars/ # 应用级全局变量存放处 │ └── sampleapp.yml ├── dev/ │ ├── hosts.yml │ └── group_vars/ # dev环境专属变量 │ └── dev.yml ├── test/ │ ├── hosts.yml │ └── group_vars/ # test环境专属变量 │ └── test.yml └── inventory.yml # 统一定义组层级
各文件内容
inventory.yml(定义完整组层级):
all: children: sampleapp: children: dev: children: dev_tomcat_windows_hosts test: children: test_tomcat_windows_hosts
dev/hosts.yml(仅定义dev环境主机):
dev_tomcat_windows_hosts: hosts: dev_server: ansible_host: 192.168.127.19
test/hosts.yml(仅定义test环境主机):
test_tomcat_windows_hosts: hosts: test_server: ansible_host: 192.168.127.17
全局变量复用实现
将应用级全局变量(如通用配置、版本号等)写入/ansible/inventory/sampleapp/group_vars/sampleapp.yml,所有属于sampleapp组的主机(包括dev和test环境)都会自动继承这些变量。
环境专属变量则放在对应环境的group_vars目录下(如dev/group_vars/dev.yml),仅对dev环境生效。
验证
执行原命令验证结果:
ansible-inventory -i /ansible/inventory/sampleapp --list --yaml
此时会得到符合预期的组结构,各环境主机正确归属对应组。
内容的提问来源于stack exchange,提问作者Crazy

