Ansible PlayBook的中清单变量优先级分析及清单变量如何分离总结

傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。——–王小波

写在前面


  • 嗯,学习Ansible高级特性,整理这部分笔记
  • 博文内容涉及
    • Ansible ploybook 中变量定义的基本原则
    • 不同位置定义变量的优先级 Demo
    • 如何实现变量和清单解耦
  • 食用方式:
    • 大量Demo,所以适合收藏温习查阅变量优先级
    • 需要有ansible基础
    • 了解角色剧本基本结构
    • 能够使用Ansible解决实际问题
  • 理解不足小伙伴帮忙指正

傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。——–王小波


管理清单变量

描述变量的基本原则

在Ansible中,利用变量,可以编写任务、角色和 playbook,使它们可重复使用并且灵活多变。变量可以指定不同系统之间的配置差异ansilbe可以在许多不同的位置设置变量:

  • 在角色的defaultsvars目录中
  • 主机清单文件中,作为主机变量组变量
  • Playbook或清单的 group_varshost_vars子目录下的变量文件中
  • Play角色任务

在项目定义和管理变量时,做好规划以遵循下列原则

  • 保持简单:尽管可以通过许多不同的⽅式定义 Ansible 变量,但尽量仅使用一两种不同方式并且仅在几个地方定义变量。

  • 不要重复:如果⼀组系统具有相同的配置,则将它们组织到⼀个组中,并在 group_vars 目录下的文件中为它们设置清单变量。

  • 在可读的小文件中组织变量:如果有一个包含许多主机组和变量的大型项目,请将变量拆分成多个文件。

变量合并和优先级

当使用多种方式定义相同变量时,Ansible 将使用优先级规则为变量选取值。以下讨论优先级从低到高

  • 配置文件(ansible.cfg)
  • 命令行选项
  • 角色defaults变量
  • host和group变量
  • Play变量
  • Extra变量(全局变量

下面就这几种变量一起简单梳理下:

配置文件

配置文件的变量拥有最低的优先级,通过在ansible.cfg 中提供到的一个KV的键值对,我们看一个Demo

1
2
3
4
5
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat ansible.cfg | grep remote_user
remote_user=root
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

这里的配置文件中的remote_user=root为连接受管机器的远程用户名,对应保存到ansible中的ansible_user变量中

1
2
3
4
5
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible vms82.liruilongs.github.io -m debug -a 'var=ansible_user' -i ./inventorys/hosts
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "root"
}

把配置文件中的变量删除,

1
2
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$sed -i '/remote_user=root/d' ansible.cfg

在次打印变量会提示变量没有定义

1
2
3
4
5
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible vms82.liruilongs.github.io -m debug -a 'var=ansible_user' -i ./inventorys/hosts
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "VARIABLE IS NOT DEFINED!"
}

添加之后也可以正常打印

1
2
3
4
5
6
7
8
9
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$sed '4a remote_user=root' ansible.cfg -i
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible vms82.liruilongs.github.io -m debug -a 'var=ansible_user' -i ./inventorys/hosts
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "root"
}
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

当然这里需要注意的是,当不指定主机清单的时候,默认情况下ansible会忽略带有后缀的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-config dump | grep -i inventory
DEFAULT_HOST_LIST(/root/ansible/ansible.cfg) = [u'/root/ansible/inventory']
DEFAULT_INVENTORY_PLUGIN_PATH(default) = [u'/root/.ansible/plugins/inventory', u'/usr/share/ansible/plugins/inventory']
INVENTORY_ANY_UNPARSED_IS_FAILED(default) = False
INVENTORY_CACHE_ENABLED(default) = False
INVENTORY_CACHE_PLUGIN(default) = None
INVENTORY_CACHE_PLUGIN_CONNECTION(default) = None
INVENTORY_CACHE_PLUGIN_PREFIX(default) = ansible_facts
INVENTORY_CACHE_TIMEOUT(default) = 3600
INVENTORY_ENABLED(default) = ['host_list', 'script', 'auto', 'yaml', 'ini', 'toml']
INVENTORY_EXPORT(default) = False
INVENTORY_IGNORE_EXTS(default) = {{(BLACKLIST_EXTS + ( '.orig', '.ini', '.cfg', '.retry'))}}
INVENTORY_IGNORE_PATTERNS(default) = []
INVENTORY_UNPARSED_IS_FAILED(default) = False
VARIABLE_PRECEDENCE(default) = ['all_inventory', 'groups_inventory', 'all_plugins_inventory', 'all_plugins_play', 'groups_plugins_inventory', 'groups_plugins_play']
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

命令行选项:

可在命令行中传递给ansible-playbook的选项(非 -e )具有最低优先级。这里讲的主要是通过其他参数来定义变量,还是用我们之前定义的ansible_user变量

1
2
3
4
5
6
7
8
9
10
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m debug -a "var=ansible_user"
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "root"
}
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m debug -a "var=ansible_user" -u liruilong
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "liruilong"
}

当然这里需要注意的是通过临时命令的方式执行 debug 模块.默认不会连接受管机,所以这里不会报错,我们的 sanheyiwuyang 用户是一个没有被受管机定义的用户。

1
2
3
4
5
6
7
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m debug -a "var=ansible_user" -u sanheyiwuyang
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "sanheyiwuyang"
}
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

角色default值:

role_name/defaults/ 文件中由角色设置的默认值具有非常低的优先级。相对于角色中的vars目录下的变量,会覆盖defaults变量值。这里我们还是用remote_user这个变量

先来新建一个角色

1
2
3
4
5
6
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-galaxy init vars_demo --init-path=roles
- Role vars_demo was created successfully
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-galaxy list | grep var
- vars_demo, (unknown version)

编写角色中的默认变量,这里我们定义远程用户名是一个没有在受管机定义的sanheyiwuyang

1
2
3
4
5
6
7
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo -e "ansible_user: sanheyiwuyang" > ./roles/vars_demo/defaults/main.yml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat ./roles/vars_demo/defaults/main.yml
ansible_user: sanheyiwuyang
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

编写角色任务

1
2
3
4
5
6
7
8
9
10
11
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$vim ./roles/vars_demo/tasks/main.yml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat ./roles/vars_demo/tasks/main.yml
---
# tasks file for vars_demo
- name: default_vars demo
debug:
var: ansible_user
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

编写执行角色的剧本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$vim vars_demo.yaml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat vars_demo.yaml
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

当前的ansible_user变量定义,我们可以看到,配置文件的优先级最低,其次是 命令行非(-e)的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml -u liruilong

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
fatal: [vms82.liruilongs.github.io]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", "unreachable": true}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

执行调用角色的剧本,报错了,通过 -u 的方式指定liruilong用户,但是角色中使用的并不是liruilong用户,而是没有被受管机定义的sanhewuyang用户,因为命名行非-e的变量优先级小于角色中/roles/var_demo/default/main.yaml定义的变量,所以liruilong用户被覆盖,所以会报错

修改 ./roles/vars_demo/defaults/main.yml中的ansible_user变量,我们也可以发现使用的是root用户,而不是命令行的liruilong

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: root" > ./roles/vars_demo/defaults/main.yml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml -u liruilong

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0


┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

主机变量和组变量:

关于主机变量和组变量这是相对应主机清单文件来讲的,主机清单的定义方式有很多种,我们可以直接通过inventory文件定义,也可以创建
inventory目录中的文件来定义,也可以在项目中指定目录下定义,场景比较多,我们分别看下

以下列表从最低到最高列出了这些变量的确切优先顺序:

  • 直接在清单文件中或通过动态清单脚本设置的al组变量。
  • 直接在清单文件中或通过动态清单脚本设置的其他组变量。
  • 在inventory/group_vars/all文件或子目录中设置的all组的变量。
  • 在项目的group_vars/all文件或子目录中设置的all组的变量。
  • 在inventory/group_vars子目录中设置的其他组变量。
  • 在项目的group_vars子目录中设置的其他组变量。
  • 直接在清单文件中或通过动态清单脚本设置的主机变量。
  • 在inventory/host vars子目录中设置的主机变量。
  • 在项目的host vars子目录中设置的主机变量。
  • 主机facts和缓存的facts。

我们分别来看下:

直接在清单文件中或通过动态清单脚本设置的all组变量

1
2
3
4
5
6
7
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$vim inventory/inventory
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat inventory/inventory
vms82.liruilongs.github.io
[all:vars]
ansible_user=liruilong

当前角色中的默认值为root

1
2
3
4
5
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat ./roles/vars_demo/defaults/main.yml
ansible_user: root
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

通过剧本的执行我们可以看到all中的组变量优先级要大于default目录下的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

直接在清单文件中或通过动态清单脚本设置的其他组变量

在上面的基础上我们新建一个组变量[lb:vars]。定义ansible_user的值为root

1
2
3
4
5
6
7
8
9
10
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$vim inventory/inventory
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat inventory/inventory
[lb]
vms82.liruilongs.github.io
[lb:vars]
ansible_user=root
[all:vars]
ansible_user=liruilong

执行剧本发现,通过ansible_user的值为root,说明覆盖了all组中的定的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$vim inventory/inventory
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0


┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

inventory/group_vars/all文件或子目录中设置的all组的变量

1
2
3
4
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$mkdir -p inventory/group_vars
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: liruilong" > inventory/group_vars/all

会发现inventory/group_vars/all覆盖了上面的inventory/inventory定义的变量,ansible_user的值为liruilong

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

项目group_vars/all文件或子目录中设置的all组的变量

1
2
3
4
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$mkdir group_vars
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: root" > group_vars/all

我们会发现项目group_vars/all下面变量会覆盖主机清单文件inventory/group_vars/all下的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

inventory/group_vars子目录中设置的其他组变量

这里需要说明的是,创建lb组变量inventory/group_vars/lb.yaml文件的前提是,需要在inventory/inventory文件中定义分组

1
2
3
4
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat ./inventory/inventory
[lb]
vms82.liruilongs.github.io

可以看到在inventory/group_vars/lb.yaml文件中定义覆盖了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: liruilong" > inventory/group_vars/lb.yaml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

在项目的group_vars子目录中设置的其他组变量

可以看到项目的./group_vars/lb.yaml的变量优先级要高于inventory/group_vars/lb.yaml下的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: root" > ./group_vars/lb.yaml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

前面我们分析的都是组变量,下面下面我们看看主机变量

直接在清单文件中或通过动态清单脚本设置的主机变量

1
2
3
4
5
6
7
8
9
10
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$sed "s/vms82.liruilongs.github.io/& ansible_user=liruilong/" ./inventory/inventory
[lb]
vms82.liruilongs.github.io ansible_user=liruilong
[lb:vars]
ansible_user=root
[all:vars]
ansible_user=liruilong
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$sed "s/vms82.liruilongs.github.io/& ansible_user=liruilong/" ./inventory/inventory -i

设置主机变量为ansible_user=liruilong优先级大于上面的组变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

inventory/host_vars子目录中设置的主机变量

1
2
3
4
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$mkdir inventory/host_vars
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: root" > inventory/host_vars/vms82.liruilongs.github.io.yaml

inventory/host_vars子目录中设置的主机变量优先级大于./inventory/inventory 中的主机变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0


┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

在项目的host_vars子目录中设置的主机变量

1
2
3
4
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$mkdir host_vars
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: liruilong" > host_vars/vms82.liruilongs.github.io.yaml

项目的host_vars子目录中设置的主机变量优先级大于清单host_vars子目录的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

主机facts和缓存的facts

主机facts,可以看到set_fact设置的变量具有最高的优先级

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat vars_demo.yaml
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
- name: set fact ansible_user
set_fact:
ansible_user: root
- name: show vars
debug:
var: ansible_user
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [set fact ansible_user] ***************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

对于其他的一些通过gather_facts收集的变量,相对于剧本之外具有很高的优先级

相对于清单inventory的group_varshost_vars子目录与相对于 playbook 项目的子目录之间的优先级比较好区分,相同类型,项目下总是比清单里的优先级要高,。

如果在 playbook 的相同目录中有group_vars 和 host_vars子目录,则这些组和主机变量将被自动包含在内。

简单总结一下ansible清单文件变量优先级。在facts优先级最高,其次是主机变量,包含清单变量文件的host_vars目录和inventory清单变量目录和inventory文件,项目下要高于清单目录下,清单目录要高于清单文件,之后是组变量,group_vars目录下的文件,inventory清单变量目录,inventory文件,整体上,inventory文件优先级小于目录下的优先级,同样是inventory目录下要小于项目目录下。

Play 变量:

准备工作,我们还用之前的角色和剧本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat vars_demo.yaml
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
- name: show vars
debug:
var: ansible_user
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Play 的优先级高于主机或组变量、角色默认值,除 -e 以外的命令行选项。以下列表从最低到最高列出了这些变量的优先顺序:

  • play 的 vars 部分进行设置。
  • 通过 play 中的 vars_prompt 部分提示用户来进行设置。
  • 通过 play 的 vars_files 部分从外部文件列表进行设置。
  • 由角色的 rolename/vars/ 子目录中的文件进行设置。
  • 通过这个块的 vars 部分为当前的 block 进行设置。
  • 通过这个任务的 vars 部分为当前的任务进行设置。
  • 通过 include_vars 模块动态加载。
  • 通过使用 set_fact 模块或通过使用 register 记录任务在主机上执行的结果,为特定的主机进行设置。
  • 在 play 的 role 部分加载时或通过使用 include_role 模块 playbook 中为角色设置的参数。
  • 由 vars 部分为通过 include_tasks 模块包含的任务进行设置。

我们分别梳理下:

由 play 的 vars 部分进行设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
---
- name: vars_demo roles demo
hosts: all
vars:
ansible_user: root
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
- name: show vars
debug:
var: ansible_user

play 的 vars 部分进行设置的变量要高于前面设置的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0


通过 play 中的vars_prompt部分提示用户来进行设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---
- name: vars_demo roles demo
hosts: all
vars:
ansible_user: root
vars_prompt:
- name: ansible_user
prompt: "input ansible_user name"
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
- name: show vars
debug:
var: ansible_user

这里默认情况下输入数据是不显示,可以添加参数private: no来显示输入变量值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml
input ansible_user name:

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

通过 play 的 vars_files 部分从外部文件列表进行设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
- name: vars_demo roles demo
hosts: all
vars:
ansible_user: root
vars_files:
- vars_files
vars_prompt:
- name: ansible_user
prompt: "input ansible_user name"
private: no
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
- name: show vars
debug:
var: ansible_user

定义引入的变量文件

1
2
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: liruilong" > vars_files

执行剧本,可以看到我们输入的是root但是打印的是liruilong,即vars_files的优先级高于vars_prompt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml
input ansible_user name: root

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

由角色的rolename/vars/子目录中的文件进行设置

当前剧本执行返回的变量值为 liruilong,我们定义roles/vars_demo/vars/main.yml目录的ansible_user变量为root.执行剧本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: root" > roles/vars_demo/vars/main.yml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

通过这个任务块的 vars 部分为当前的 block 进行设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- block:
- name: show vars in block
debug:
var: ansible_user
vars:
ansible_user: liruilong
- name: show vars
debug:
var: ansible_user

我们可以看到,在block所在的块的内部,通过vars定义的变量具有最高的优先级,打印的ansible_usern的变量的为liruilong,而在剧本的其他位置的打印的变量为root

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook var_demos.yaml

PLAY [vars_demo roles demo] ****************************************************************

TASK [Gathering Facts] *********************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars in block] ******************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************
vms82.liruilongs.github.io : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

show vars任务为角色中的任务,所以依旧使用角色中的vars/main.yml定义root。

通过这个任务的 vars 部分为当前的任务进行设置

即不是写在block块内的vars变量,而是写在对应 任务中的vars的变量中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- block:
- name: show vars in block
debug:
var: ansible_user
vars:
ansible_user: root
- name: show vars in block no vars
debug:
var: ansible_user
vars:
ansible_user: liruilong

执行我们可以看到在block内部,任务内部的变量优先级要高于任务外部的变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************

TASK [Gathering Facts] *********************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars in block] ******************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars in block no vars] *********************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************
vms82.liruilongs.github.io : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

通过 include_vars 模块动态加载

ansible中,我们可以使用include_vars模块来加载外部的变量。加载方式很简单,和通过 play 的 vars_files 部分从外部文件列表进行设置很类似。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- block:
- name: show vars in block
debug:
var: ansible_user
vars:
ansible_user: root
- name: show vars in block no vars
debug:
var: ansible_user
vars:
ansible_user: liruilong
- name: show vars
debug:
var: ansible_user

- name: include_vars vars file
include_vars:
file: vars_files
- name: show vars after include vars files
debug:
var: ansible_user

但是变量的优先级还是有很大的区别的,我们先把include_vars模块放到最后看看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat vars_files
ansible_user: liruilong
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************

TASK [Gathering Facts] *********************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars in block] ******************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars in block no vars] *********************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [include_vars vars file] **************************************************************
ok: [vms82.liruilongs.github.io]

TASK [show vars after include vars files] **************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************
vms82.liruilongs.github.io : ok=7 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

发现模块执行前是没有变化的,只会影响执行后的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- name: include_vars vars file
include_vars:
file: vars_files
- block:
- name: show vars in block
debug:
var: ansible_user
vars:
ansible_user: root
- name: show vars in block no vars
debug:
var: ansible_user
vars:
ansible_user: liruilong
- name: show vars
debug:
var: ansible_user

- name: show vars after include vars files
debug:
var: ansible_user

include_vars模块放到最前面,我们发现剧本中变量全部被替换为liruilong了,除了角色变量,因为剧本中,角色最先执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************

TASK [Gathering Facts] *********************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [include_vars vars file] **************************************************************
ok: [vms82.liruilongs.github.io]

TASK [show vars in block] ******************************************************************
ok: [vms82.liruilongs.github.io] =>
"ansible_user": "liruilong"
}

TASK [show vars in block no vars] *********************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars] ***************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [show vars after include vars files] **************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

PLAY RECAP *********************************************************************************
vms82.liruilongs.github.io : ok=7 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

通过使用 set_fact 模块或通过使用register记录任务在主机上执行的结果,为特定的主机进行设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- name: set facts
set_fact:
ansible_user: root
- name: include_vars vars file
include_vars:
file: vars_files
- block:
- name: show vars in block
debug:
var: ansible_user
vars:
ansible_user: root
- name: show vars in block no vars
debug:
var: ansible_user
vars:
ansible_user: liruilong
- name: show vars
debug:
var: ansible_user

- name: show vars after include vars files
debug:
var: ansible_user

嗯,不多解释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************

TASK [Gathering Facts] *********************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [set facts] ***************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [include_vars vars file] **************************************************************
ok: [vms82.liruilongs.github.io]

TASK [show vars in block] ******************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars in block no vars] *********************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars after include vars files] **************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************
vms82.liruilongs.github.io : ok=8 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

在 play 的 role 部分加载时或通过使用 include_role 模块playbook中为角色设置的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
---
- name: vars_demo roles demo
hosts: all
roles:
- role: vars_demo
ansible_user: liruilong
tasks:
- name: set facts
set_fact:
ansible_user: root
- name: include_vars vars file
include_vars:
file: vars_files
- block:
- name: show vars in block
debug:
var: ansible_user
vars:
ansible_user: root
- name: show vars in block no vars
debug:
var: ansible_user
vars:
ansible_user: liruilong
- name: show vars
debug:
var: ansible_user

- name: show vars after include vars files
debug:
var: ansible_user

剧本设置角色变量后,角色内置的变量被覆盖掉,但是只对当前角色生效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************

TASK [Gathering Facts] *********************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [set facts] ***************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [include_vars vars file] **************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [show vars in block] ******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars in block no vars] *********************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars after include vars files] **************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************************
vms82.liruilongs.github.io : ok=8 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

或者也可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
---
- name: vars_demo roles demo
hosts: all
# roles:
# - role: vars_demo
# ansible_user: liruilong
tasks:
- name: include role
include_role:
name: vars_demo
vars:
ansible_user: liruilong
- name: set facts
set_fact:
ansible_user: root
- name: include_vars vars file
include_vars:
file: vars_files
- block:
- name: show vars in block
debug:
var: ansible_user
vars:
ansible_user: root
- name: show vars in block no vars
debug:
var: ansible_user
vars:
ansible_user: liruilong
- name: show vars
debug:
var: ansible_user

- name: show vars after include vars files
debug:
var: ansible_user
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************

TASK [Gathering Facts] *********************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [include role] ************************************************************************************

TASK [vars_demo : default_vars demo] *******************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

TASK [set facts] ***************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [include_vars vars file] **************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [show vars in block] ******************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars in block no vars] *********************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars] ***************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars after include vars files] **************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

PLAY RECAP *********************************************************************************************
vms82.liruilongs.github.io : ok=8 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

由 vars 部分为通过 include_tasks 模块包含的任务进行设置

1
2
3
4
5
6
7
8
9
10
11
12
13
---
- name: vars_demo roles demo
hosts: all
# roles:
# - role: vars_demo
# ansible_user: liruilong
tasks:
- name: include_tasks demo
include_tasks: task.yaml
vars:
ansible_user: root
- name: include role
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat task.yaml
- name: vars demo 2
debug:
var: ansible_user
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************

TASK [Gathering Facts] *********************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [include_tasks demo] ******************************************************************************
included: /root/ansible/task.yaml for vms82.liruilongs.github.io

TASK [vars demo 2] *************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

....

Extra变量(-e 命令或者–extra-vars)

使用 ansible-playbook 命令的 -e 选项设置的额外变量始终具有最高的优先级。或者--extra-vars也可以以JSON形式定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible vms82.liruilongs.github.io -m debug -a 'var=ansible_user'
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "root"
}
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m debug -a "var=ansible_user" --extra-vars "{'ansible_user':'liruilong'}"
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "liruilong"
}
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m debug -a "var=ansible_user" --e "{'ansible_user':'liruilong'}"
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "liruilong"
}

可以发现当使用 --extra-vars 在命令行定义变量的时候,会覆盖ansible.cfg 的变量配置,使用了liruilong这个受管机用户

将变量与清单分离

随着环境在规模和种类上扩展,清单文件会变得很大且难以阅读。

更好的做法是将变量定义从清单文件转移到单独的变量文件中,每个主机组分别对应一个,每个变量文件都已主机组命令,且包含该主机组的变量定义:

在这里插入图片描述

对于多样化的大型化环境而言,更好的方法是在group_vars目录下为每个主机组创建子目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──[root@vms82.liruilongs.github.io]-[~/inventory-variables]
└─$ls
ansible.cfg deploy_haproxy.yml group_vars roles
deploy_apache.yml deploy_webapp.yml inventory.yml site.yml
┌──[root@vms82.liruilongs.github.io]-[~/inventory-variables]
└─$cd group_vars/
┌──[root@vms82.liruilongs.github.io]-[~/inventory-variables/group_vars]
└─$tree
.
├── lb_servers
│   ├── firewall.yml
│   └── haproxy.yml
└── web_servers

2 directories, 2 files

在这里插入图片描述

group_vars 目录下各目录的文件中存在的所有变量都与其余变量合并在⼀起。通过将变量分隔到按功能分组的文件中,可以使整个 playbook 项目更易于理解和维护。

在这里插入图片描述

特殊清单变量

可以使用多个变量来更改Ansible连接到清单中列出的主机的方式。其中⼀些对于主机特定变量最为有用,但另⼀些可能与组中或清单中的所有主机相关。

ansible_connection:主机的连接类型,用于访问受管主机的连接插件。默认情况下,ssh 用于除 localhost 外的所有主机,后者使用 local。

1
2
3
4
5
6
7
8
9
10
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m debug -a "msg={{ansible_connection}}"
vms82.liruilongs.github.io | SUCCESS => {
"msg": "ssh"
}
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible 127.0.0.1 -m debug -a "msg={{ansible_connection}}"
127.0.0.1 | SUCCESS => {
"msg": "local"
}

ansible_host:要连接的主机名称。实际 IP 地址或完全限定域名,在连接受管主机时使用,而不使来用自清单文件(inventory_hostname) 中的名称。默认情况下,此变量具有与清单主机名相同的值。

1
2
3
4
5
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m debug -a "msg={{ansible_host}}"
vms82.liruilongs.github.io | SUCCESS => {
"msg": "vms82.liruilongs.github.io"
}
  • ansible_port:Ansible 用于连接受管主机的端口。对于(默认)SSH 连接插件,其值默认为 22。
  • ansible_user:Ansible 以此用户身份连接受管主机。作为 Ansible 的默认行为,它会使用与控制节点上运行 Ansible Playbook 的用户相同的用户名来连接受管主机。
  • ansible_become_user:Ansible 连接到受管主机后,它将使用 ansible_become_method(默认情况下为sudo)切换到此用户。
  • ansible_python_interpreter:Ansible 应在受管主机上使用的 Python 可执行文件的路径。

系统变量:通过剧本的gather_facts=yes自动搜集(默认调用setup模块),对任务主机有效,系统指标

1
2
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m setup

使用变量识别当前主机

ansible魔法变量,指的是ansible为管理目的而预设的特殊变量,通过adhoc方式或者playbook方式,都可以调用/或者msg查看

  • inventory_hostname:当前正在处理的受管主机的名称,从清单中获取。
  • ansible_host:用于连接受管主机的实际 IP 地址或主机名。
  • ansible_facts[‘hostname’]:作为事实,从受管主机手机的完全限定域名。
  • ansible_play_hosts:当前 Play 期间尚未失败的所有主机的列表。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    ┌──[root@vms81.liruilongs.github.io]-[~/ansible]
    └─$ansible all -m debug -a "var=hostvars"
    vms82.liruilongs.github.io | SUCCESS => {
    "hostvars": {
    "vms82.liruilongs.github.io": {
    "ansible_check_mode": false,
    "ansible_diff_mode": false,
    "ansible_facts": {},
    "ansible_forks": 5,
    "ansible_inventory_sources": [
    "/root/ansible/inventory"
    ],
    "ansible_playbook_python": "/usr/bin/python2",
    "ansible_user": "liruilong",
    "ansible_verbosity": 0,
    "ansible_version": {
    "full": "2.9.25",
    "major": 2,
    "minor": 9,
    "revision": 25,
    "string": "2.9.25"
    },
    "group_names": [
    "lb"
    ],
    "groups": {
    "all": [
    "vms82.liruilongs.github.io"
    ],
    "lb": [
    "vms82.liruilongs.github.io"
    ],
    "ungrouped": []
    },
    "inventory_dir": "/root/ansible/inventory",
    "inventory_file": "/root/ansible/inventory/hosts",
    "inventory_hostname": "vms82.liruilongs.github.io",
    "inventory_hostname_short": "vms82",
    "omit": "__omit_place_holder__fbd943e37b3564fcd7926f8926da009ae4e9e4ab",
    "playbook_dir": "/root/ansible"
    }
    }
    }

一个完整的Demo

嗯,我们来看一个具体的Demo,这Demo是之前的博文用到,看一下如何从现有的ansible项目中抽取变量来实现剧本的可复用,可维护

这是原本的结构目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
┌──[root@vms81.liruilongs.github.io]-[~/ansible/inventory-variables]
└─$tree
.
├── ansible.cfg
├── deploy_apache.yml
├── deploy_haproxy.yml
├── deploy_webapp.yml
├── inventory.yml
├── roles
│   ├── apache
│   │   ├── meta
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── tests
│   │   ├── inventory
│   │   └── test.yml
│   ├── firewall
│   │   ├── defaults
│   │   │   └── main.yml
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── meta
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── tests
│   │   ├── inventory
│   │   └── test.yml
│   ├── haproxy
│   │   ├── defaults
│   │   │   └── main.yml
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── meta
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   ├── templates
│   │   │   └── haproxy.cfg.j2
│   │   └── tests
│   │   ├── inventory
│   │   └── test.yml
│   └── webapp
│   ├── defaults
│   │   └── main.yml
│   ├── meta
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   └── tests
│   ├── inventory
│   └── test.yml
└── site.yml

30 directories, 34 files
┌──[root@vms81.liruilongs.github.io]-[~/ansible/inventory-variables]
└─$

这是我们重新编写过的,会发现多了一个group_vars目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
┌──[root@vms81.liruilongs.github.io]-[~/ansible/inventory-variables]
└─$tree
.
├── ansible.cfg
├── deploy_apache.yml
├── deploy_haproxy.yml
├── deploy_webapp.yml
├── group_vars
│   ├── lb_servers
│   │   ├── firewall.yml
│   │   └── haproxy.yml
│   └── web_servers
├── inventory.yml
├── roles
│   ├── apache
│   │   ├── meta
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── tests
│   │   ├── inventory
│   │   └── test.yml
│   ├── firewall
│   │   ├── defaults
│   │   │   └── main.yml
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── meta
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── tests
│   │   ├── inventory
│   │   └── test.yml
│   ├── haproxy
│   │   ├── defaults
│   │   │   └── main.yml
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── meta
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   ├── templates
│   │   │   └── haproxy.cfg.j2
│   │   └── tests
│   │   ├── inventory
│   │   └── test.yml
│   ├── org_common
│   │   ├── meta
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── tests
│   │   ├── inventory
│   │   └── test.yml
│   └── webapp
│   ├── defaults
│   │   └── main.yml
│   ├── meta
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   └── tests
│   ├── inventory
│   └── test.yml
└── site.yml

30 directories, 34 files

下面来看一个这个Demo, 关于剧本干了什么,小伙伴可以看看我之前的ansible博文

在项目根目新建一个group_vars ,在该目录下为每个主机组创建子目录

1
2
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$mkdir group_vars

创建 lb_servers ⽬录,以存放 lb_servers 组中主机的变量

1
2
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$mkdir group_vars/lb_servers

创建 web_servers ⽬录,以存放 web_servers 组的变量

1
2
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$ mkdir group_vars/web_servers

在每个主机组中为涉及到的角色定义变量文件

1
2
3
4
5
6
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$touch group_vars/lb_servers/firewall.yml
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$touch group_vars/lb_servers/haproxy.yml
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$ls

在执行deploy_haproxy剧本的时候,调用haproxy,会涉及到角色相关的变量加载。firewall_rules,haproxy_appservers这两个角色变量。firewall 角色通过角色依赖的方式执行,而haproxy通过剧本直接执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$cat deploy_haproxy.yml
- name: Ensure HAProxy is deployed
hosts: lb_servers
force_handlers: True

roles:
# The "haproxy" role has a dependency on the "firewall" role.
# The "firewall" role requires a "firewall_rules" variable be defined.
- role: haproxy
firewall_rules:
# Allow 80/tcp connections
- port: 80/tcp

haproxy_appservers:
- name: serverb.lab.example.com
ip: 172.25.250.11
backend_port: 80
- name: serverc.lab.example.com
ip: 172.25.250.12
backend_port: 80

group_vars/lb_servers/firewall.yml定义主机组lb_servers中涉及firewall角色的变量

1
2
3
4
5
6
7
8
9
10
11
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$tee group_vars/lb_servers/firewall.yml <<- EOF
> firewall_rules:
> # Allow 80/tcp connections
> - port: 80/tcp
> EOF
firewall_rules:
# Allow 80/tcp connections
- port: 80/tcp
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$

同时将剧本中的变量删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$cat deploy_haproxy.yml
- name: Ensure HAProxy is deployed
hosts: lb_servers
force_handlers: True

roles:
# The "haproxy" role has a dependency on the "firewall" role.
# The "firewall" role requires a "firewall_rules" variable be defined.
- role: haproxy
haproxy_appservers:
- name: serverb.lab.example.com
ip: 172.25.250.11
backend_port: 80
- name: serverc.lab.example.com
ip: 172.25.250.12
backend_port: 80

同样的在lb_servers主机组目录下haproxy角色变量文件中定义haproxy角色涉及的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$tee group_vars/lb_servers/haproxy.yml <<- EOF
> haproxy_appservers:
> - name: serverb.lab.example.com
> ip: 172.25.250.11
> backend_port: 80
> - name: serverc.lab.example.com
> ip: 172.25.250.12
> backend_port: 80
> EOF
haproxy_appservers:
- name: serverb.lab.example.com
ip: 172.25.250.11
backend_port: 80
- name: serverc.lab.example.com
ip: 172.25.250.12
backend_port: 80
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$
1
2
3
4
5
6
7
8
9
10
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$cat deploy_haproxy.yml
- name: Ensure HAProxy is deployed
hosts: lb_servers
force_handlers: True

roles:
# The "haproxy" role has a dependency on the "firewall" role.
# The "firewall" role requires a "firewall_rules" variable be defined.
- role: haproxy

通过上面的改造,我们把变量从执行角色的剧本中解耦出来,类似代码中将静态可变的数据抽离出来的通过加载配置文件的方式。如果调用角色的剧本很复杂的话,那通过把变量抽离,每次需要维护或者移植直接修改变量文件就可以啦。

同样的deploy_apache剧本的变量我们以同样的方式替换一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$ cat deploy_apache.yml
- name: Ensure Apache is deployed
hosts: web_servers
force_handlers: True

roles:
# The "apache" role has a dependency on the "firewall" role.
# The "firewall" role requires a "firewall_rules" variable be defined.
- role: apache
firewall_rules:
# Allow http requests from the load_balancer.
- zone: internal
service: http
source: "172.25.250.10"
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$tee group_vars/web_servers/firewall.yml <<- EOF
> firewall_rules:
> # Allow http requests from the load_balancer.
> - zone: internal
> service: http
> source: "172.25.250.10"
> EOF
firewall_rules:
# Allow http requests from the load_balancer.
- zone: internal
service: http
source: "172.25.250.10"
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables]
└─$
1
2
3
4
5
6
7
8
- name: Ensure Apache is deployed
hosts: web_servers
force_handlers: True

roles:
# The "apache" role has a dependency on the "firewall" role.
# The "firewall" role requires a "firewall_rules" variable be defined.
- role: apache

改造后的目录多出来的

1
2
3
4
5
6
7
8
9
10
┌──[root@workstation.lab.example.com]-[/home/student/git-repos/inventory-variables/group_vars]
└─$tree
.
├── lb_servers
│   ├── firewall.yml
│   └── haproxy.yml
└── web_servers
└── firewall.yml

2 directories, 3 files

同时我们对主机清单文件进行改写

该 playbook 将清单主机 load_balancer 作为负载平衡器来部署,并将组 web_servers 中的主机作为后端 Web 服务器来部署。
编辑 inventory.yml 静态清单⽂件,以便 playbook 中引⽤ load_balancer 主机时使Ansible 连接到 servera.lab.example.com。 清单主机 serverb.lab.example.com和 serverc.lab.example.com 应当位于组 web_servers 中。

1
2
3
4
5
6
7
lb_servers:
hosts:
servera.lab.example.com:

web_servers:
hosts:
server[b:c].lab.example.com:
1
2
3
4
5
6
7
8
lb_servers:
hosts:
load_balancer:
ansible_host: servera.lab.example.com

web_servers:
hosts:
server[b:c].lab.example.com:

上面的为原来的清单文件,下面为我们改写过的清单文件,这里通过ansible_host清单变量指定了执行时的机器,并且定义了一个别名load_balancer,也就是说,在主机清单为lb_servers所在组执行剧本时,在连接受管主机时,使用当前定义的别名。通过DNS的方式来映射到对应的机器,而不使来用自清单文件(inventory_hostname) 中的名称。

整理参考书籍

《RED HAT 447 Advanced Automation:Ansible Best Practices Edition》

Ansible PlayBook的中清单变量优先级分析及清单变量如何分离总结

https://liruilongs.github.io/2022/05/13/rhca/DO447/Ansible最佳实践之如何管理playbook的中清单变量/

发布于

2022-05-13

更新于

2023-06-21

许可协议

评论
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×