17 Oct 2016
在ansible中,inventory的组织方式可如下
somedomain [cluster01] domain01 [cluster02] domain02 [tomcat:children] cluster01 cluster02
这样我们可以使用子分组来区分不同分组主机的变量,但是生产环境中,很有可能cluster01和02在同一台主机上
此时,在切换子分组的时候,每个子分组的变量会互相干涉吗?
注意:
文中的转义符”\“,仅为了语法不冲突,无实际意义,实际操作时,需去掉它
tree . . ├── group_vars │ ├── group │ ├── group01 │ └── group02 ├── hosts └── main.yml
# inventory文件 **************************** [group:children] group01 [group01] 192.168.33.102 **************************** # 父group变量文件:group_vars/group **************************** --- test: test_group **************************** # 子group变量文件:group_vars/group **************************** --- test: test_group_01 **************************** # 测试yaml文件:main.yml **************************** --- - hosts: "\{\{ host }}" remote_user: root tasks: - debug: msg="\{\{ test }}" **************************** # 测试结果 ansible-playbook -i hosts main.yml -e '{"host":"group"}' PLAY [group] ******************************************************************* TASK [setup] ******************************************************************* ok: [192.168.33.102] TASK [debug] ******************************************************************* ok: [192.168.33.102] => { "msg": "test_group_01" } PLAY RECAP ********************************************************************* 192.168.33.102 : ok=2 changed=0 unreachable=0 failed=0 # 结论 子分组的变量会覆盖父分组
# 与场景1唯一的改变是在inventory文件中增加host变量 **************************** [group:children] group01 [group01] 192.168.33.102 test=test_host **************************** # 测试结果 ansible-playbook -i hosts main.yml -e '{"host":"group"}' PLAY [group] ******************************************************************* TASK [setup] ******************************************************************* ok: [192.168.33.102] TASK [debug] ******************************************************************* ok: [192.168.33.102] => { "msg": "test_host" } PLAY RECAP ********************************************************************* 192.168.33.102 : ok=2 changed=0 unreachable=0 failed=0 # 结论 host变量会覆盖组变量
# 与场景1(注意是场景1)的区别1是修改了inventory内容 **************************** [group:children] group01 group02 [group01] 192.168.33.102 [group02] 192.168.33.102 **************************** # 与场景1(注意是场景1)的区别2是增加了group_vars/group02的内容 **************************** --- test: test_group_02 **************************** # 测试结果 ansible-playbook -i hosts main.yml -e '{"host":"group"}' PLAY [group] ******************************************************************* TASK [setup] ******************************************************************* ok: [192.168.33.102] TASK [debug] ******************************************************************* ok: [192.168.33.102] => { "msg": "test_group_01" } PLAY RECAP ********************************************************************* 192.168.33.102 : ok=2 changed=0 unreachable=0 failed=0 # 结论 当同层级(group01和group02)同时存在针对同一host的组变量时,不确定哪一个会生效
当然,实验3也是主要的问题所在,因为假设在同一台host上我们部署了两个tomcat,一主一备, 当我们希望去分别指定两个tomcat时,同一变量的情况下,我们无法准确的知道该变量会指定谁。
从上面的实验中,我们得出一个结论,ansible对于变量的层级分为三种,all、group、host(暂不考虑role)
这里思考解决办法:
# inventory内容 **************************** [group:children] group01 group02 [group01] 192.168.33.102 [group02] 192.168.33.102 **************************** # group变量文件:group_vars/group **************************** --- test: - '\{\{ test_01 | d({}) }}' - '\{\{ test_02 | d({}) }}' **************************** # 含义为当test_01变量不存在时,返回{} # test_02亦同 # group01变量文件:group_vars/group01 **************************** --- test_01: test_group_01 **************************** # group02变量文件:group_vars/group02 **************************** --- test_02: test_group_02 **************************** # 测试yaml文件内容 **************************** --- - hosts: "\{\{ host }}" remote_user: root tasks: - debug: msg="\{\{ test }}" **************************** # 测试结果 ansible-playbook -i hosts main.yml -e '{"host":"group"}' PLAY [group] ******************************************************************* TASK [setup] ******************************************************************* ok: [192.168.33.102] TASK [debug] ******************************************************************* ok: [192.168.33.102] => { "msg": [ "test_group_01", "test_group_02" ] } PLAY RECAP ********************************************************************* 192.168.33.102 : ok=2 changed=0 unreachable=0 failed=0 # 此时我们发现返回的结果是一个list,包含了两个变量的值。但我们希望它返回两次,而不是一个list # 因为若返回结果是list,我们在很多模块中调用它会因为类型问题报错 # 我们仅对yaml文件进行修改 **************************** --- - hosts: "\{\{ host }}" remote_user: root tasks: - debug: msg="\{\{ item }}" with_items: "\{\{ test }}" **************************** # 再次测试 ansible-playbook -i hosts main.yml -e '{"host":"group"}' PLAY [group] ******************************************************************* TASK [setup] ******************************************************************* ok: [192.168.33.102] TASK [debug] ******************************************************************* ok: [192.168.33.102] => (item=test_group_01) => { "item": "test_group_01", "msg": "test_group_01" } ok: [192.168.33.102] => (item=test_group_02) => { "item": "test_group_02", "msg": "test_group_02" } PLAY RECAP ********************************************************************* 192.168.33.102 : ok=2 changed=0 unreachable=0 failed=0 # 此时结果完全符合我们的预期
有时候我们并不希望执行时ansible去循环这个变量,而是希望指定一个子分组,ansible就采用我们在子分组中配置的那个变量怎么办?
此时我们可以使用外部传参或inventory中指定别名的方式来隔离分组变量 其中外部传参的方式完全规避了group vars的影响,暴力直接,但是也有其局限性,那就是在inventory中主机特别多时,需要整理的参数很多
这里我们采用inventory别名的方法来测试
inventory文件内容修改
[group:children] group01 group02 [group01] host1 ansible_host=192.168.33.102 [group02] host2 ansible_host=192.168.33.102
变量文件修改
# group01变量文件 --- test_01: test_group_01 test_separate: this is 01 # group02变量文件 --- test_02: test_group_02 test_separate: this is 02 ---
这样我们就在group01和group02中拥有了两个直接冲突的变量
yaml测试文件修改
---
- hosts: "\{\{ host }}"
remote_user: root
tasks:
- debug: msg="\{\{ test }}"
- debug: msg="\{\{ test_separate }}"
增加一个debug信息,让我们来看看区别
测试结果
# 先来指定group01 ansible-playbook -i hosts main.yml -e "host=group01" PLAY [group01] ***************************************************************** TASK [setup] ******************************************************************* ok: [host1] TASK [debug] ******************************************************************* ok: [host1] => { "msg": [ "test_group_01", {} ] } TASK [debug] ******************************************************************* ok: [host1] => { "msg": "this is 01" } PLAY RECAP ********************************************************************* host1 : ok=3 changed=0 unreachable=0 failed=0 # 再来指定group02 ansible-playbook -i hosts main.yml -e "host=group02" PLAY [group02] ***************************************************************** TASK [setup] ******************************************************************* ok: [host2] TASK [debug] ******************************************************************* ok: [host2] => { "msg": [ {}, "test_group_02" ] } TASK [debug] ******************************************************************* ok: [host2] => { "msg": "this is 02" } PLAY RECAP ********************************************************************* host2 : ok=3 changed=0 unreachable=0 failed=0
我们可以看出,当我们指定的不是group而是其分组时,第一个debug信息输出的是一个包含{}的列表 而第二个debug,则由于我们在inventory中的别名配置,隔离了分组之间的变量冲突