浅谈 ansible inventory 的那些坑

一号坑:-i参数只能定义一次。

开始话题之前,先看一个调用案例:

有playbook如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# deploy.yml

- hosts: '{{host_svr}}'
max_fail_percentage: 30
serial: "30%"
remote_user: common
become: true
roles:
- dubbosvr

- hosts: '{{host_web}}'
max_fail_percentage: 30
serial: "30%"
remote_user: common
become: true
roles:
- websvr

调用playbook执行部署:

1
2
3
4
# inventory/web.host 文件里面定义了 web.host 主机组
# inventory/svr.host 文件里面定义了 svr.host 主机组

ansible-playbook -v -i inventory/web.host -i inventory/svr.host deploy.yml -e host_web=web.host -e host_svr=svr.host

执行的时候只执行完svr.host主机组就不再执行了,为什么?

相信有人马上就能看出问题来了,但是对于半路出家的我来说,曾折腾了好久都想不出个所以然。

是的,没错,inventory参数重复定义了!!!

曾经我天真地以为,-i参数和-e参数一样,可以多次定义,全部读取。但我错了,而且没意识到是命令的错,以为是playbook定义有误或者一个playbook不支持定义多主机组导致。

在反复核对和google了半天无果后,我静下心来,开始从官方文档去寻找蛛丝马迹。当我从官方文档的playbook主题中看到一个案例时,我彻底排除了playbook的问题,转而开始研究参数的调用。

官方明确说明playbook支持多主机组

是的,没错,官方明确说了,playbook支持多个主机组定义,而且示例代码和我的playbook差别不大。

当我转而去研究参数时,终于发现了一个问题:

1
2
3
4
5
6
7
8
9
  -i INVENTORY, --inventory-file=INVENTORY
specify inventory host path
(default=/etc/ansible/hosts) or comma separated host
list.

# -i 参数,指定 host 文件,或用逗号分隔 host 列表,默认路径为 /etc/ansible/hosts 。
# 说白了,就是 /etc/ansible/ansible.cfg 配置文件中
# "inventory = /etc/ansible/hosts"
# 的外部定义,而这种定义,一般只能存在一个,以最后的为准。

这下终于能解释为什么web.host不执行了,因为它被svr.host的定义覆盖了,导致playbook找不到web.host主机组的定义,故忽略执行。

(别问我为啥不把web.hostsvr.host都定义到同一个文件,这涉及到group_varsrole的定义,以及一套环境多套web的考量。况且,我只是举个栗子……)

二号坑:使用group_var时需要指定具体主机组。

这个坑跟group_var路径有关,大家都知道,这个路径存放的是跟部署主机组相关的变量,比如在部署主机组web.host的时候,默认会先去加载group_var/web.host文件中的变量,如果web.host文件存在的话。

但是,它并不是按playbook里面定义的主机组来加载的,而是根据inventory参数来加载的,也就是说,你的inventory参数中包含了多少个主机组,它就会去加载多少个对应的变量文件(如果存在的话)。这种方式势必会照成变量冲突,比如定义了两个web环境的变量,而调用的是同一个role的时候,带入role里面的变量,是以最后一次的定义为准。

举个栗子,你想部署web1环境,但是你带入的inventory包含了web1.hostweb2.host,由于使用了同一个role,所以定义了同一个变量tomcat_home(值不一样),这时候,就会出现web2的变量把web1的覆盖,导致web1部署失败的情况。

所以在使用group_var的时候,一定要控制好变量的命名,以及inventory的分类,以免照成不必要的麻烦。

三号坑:role下面的default变量不能继承到meta

role下面的default变量,只能提供给本roleplaybook使用,不能继承到依赖的role,并且不能用相同的变量名给变量赋值,如“{ role: tomcat, tomcat_home: " }"”,所以,如果当前roledependencies里面的role都需要在default里面用到相同的变量,乖乖地把它们设成一致吧。

END

好了,这就是我在使用ansible inventory的过程中遇到的坑,希望我血淋淋的教训能给大家带来一些些帮助。

That’s all.