我想充分利用ansible的变量优先级。
让我们来看看这个简化的项目:
├── group_vars
│ └── all
│ └── web
├── hosts
│ └── local
└── site.yml
库存文件hosts/local
:
[local_web]
192.168.1.20
[local_db]
192.168.1.20
[web:children]
local_web
[db:children]
local_db
group_vars/all
文件:
test: ALL
group_vars/web
文件:
test: WEB
site.yml
文件:
---
- name: Test
hosts: db
tasks:
- debug: var=test
好的,这只是为了测试变量的优先级。当我在db
组中运行ansible时,test
变量应该显示"ALL",因为ansible只会查看group_vars/all
,对吧?错误:
TASK: [debug var=test] ********************************************************
ok: [192.168.1.20] => {
"var": {
"test": "WEB"
}
}
实际上,如果local_web
和local_db
主机不同,那么它是有效的。
当主机相同时,为什么ansible仍然会查看不相关的配置文件?那是虫子还是我?
您声明192.168.1.20
是您定义的所有4个组的成员,这与您在剧本中引用主机的方式无关。无论你在剧本中如何引用主机,Ansible都会评估主机所在的所有组,并基于这些组导入变量。
这里有一个方便的测试来证明这一点:
- name: Test
hosts: db
tasks:
- debug: msg="{{ inventory_hostname }} is in group {{ item }}"
when: inventory_hostname in groups[item]
with_items: group_names
其输出为:
TASK: [debug msg="host is in group {{ item }}"] *******************************
ok: [192.168.1.20] => (item=db) => {
"item": "db",
"msg": "192.168.1.20 is in group db"
}
ok: [192.168.1.20] => (item=local_db) => {
"item": "local_db",
"msg": "192.168.1.20 is in group local_db"
}
ok: [192.168.1.20] => (item=local_web) => {
"item": "local_web",
"msg": "192.168.1.20 is in group local_web"
}
ok: [192.168.1.20] => (item=web) => {
"item": "web",
"msg": "192.168.1.20 is in group web"
}
由于主机在web
组中,因此包含了web
group_vars文件。
@Bruce p的答案是正确的。
然而,这种易解释的行为对我来说并不令人满意,因为它会根据主机更改变量的优先级。我使用的不是group_vars
,而是vars_files
字典。
我将group_vars
移到一个名为vars
的目录中。
更新后的site.yml
:
---
- name: Test
hosts: db
tasks:
- debug: var=test
vars_files:
- vars/all
- vars/db
现在,test
显示"ALL",正如我所希望的。它首先读取vars/all
,然后读取vars/db
(为空)。
(注意:变量优先级目前似乎有点问题-v1.9.2-。这意味着如果您使用变量作为var文件名,ansible将不会按预期顺序加载文件。)
另一个可以将变量保留在group_vars中的解决方案是将库存文件hosts/local替换为两个文件:hosts/inv_db和hosts/inv_web,并使用-i选项指定要使用的库存文件。