0%

ansible变量优先级

ansible提供了灵活多样的变量定义方式,本文整理了ansible变量定义位置以及优先级。

变量名规范

ansible中的变量名可以为字母、数字以及下划线,变量始终应该以字母开头。

变量定义位置

命令行传递

ansible命令行传递变量key=valueYAMLJSON格式,甚至文件。

1
2
# cat /tmp/vars.yml
info: "hello from file"
1
2
3
4
# cat /tmp/vars.json
{
'info': 'hello from file'
}

运行下面命令都会得到期望结果:

1
2
3
4
# ansible-playbook -e @/tmp/vars.yml vars.yml
# ansible-playbook -e @/tmp/vars.json vars.yml
# ansible-playbook -e '{ "info": "hello from command" }' vars.yml
# ansible-playbook -e 'info="hello from command"' vars.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# ansible-playbook -e 'info="hello from command"' vars.yml 

PLAY [test for vars] ***********************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [10.1.1.199]

TASK [show something] **********************************************************************************************
changed: [10.1.1.199]

TASK [debug] *******************************************************************************************************
ok: [10.1.1.199] => {
"info": "hello from command"
}

PLAY RECAP *********************************************************************************************************
10.1.1.199 : ok=3 changed=1 unreachable=0 failed=0

playbook

1
2
3
4
5
6
7
8
- name: test for vars
hosts: test
vars:
info: "Hello world."
tasks:
- name: show something
command: echo {{ info }}
- debug: var=info

运行结果:

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

PLAY [test for vars] ***********************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [10.1.1.199]

TASK [show something] **********************************************************************************************
changed: [10.1.1.199]

TASK [debug] *******************************************************************************************************
ok: [10.1.1.199] => {
"info": "Hello world."
}

PLAY RECAP *********************************************************************************************************
10.1.1.199 : ok=3 changed=1 unreachable=0 failed=0

roles tasks文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# tree roles
roles
└── cron
└── cron-test
├── defaults
│   └── main.yml
├── files
├── tasks
│   └── main.yml
├── templates
└── vars
└── main.yml

7 directories, 3 files

以下为roles/cron/cron-test/tasks/main.yml文件的内容,其他目录下的main.yml为空。

1
2
3
4
5
6
7
8
9
10
11
12
- name: add cron env
cron:
name: PATH
env: yes
value: '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin'

- name: add cron
vars:
cron_name: ntpdate_roles_vars
cron: name={{ item.name }} minute={{ item.minute }} hour={{ item.hour }} day={{ item.day }} job={{ item.job }} state=present
with_items:
- { name: "{{ cron_name }}", minute: "*/10", hour: "*", day: "*", job: "/usr/sbin/ntpdate 10.0.2.165 >/dev/null 2>&1" }

然后我们在roles的同级目录创建test_roles.yml文件来调用roles。

1
2
3
4
- name: test roles
hosts: test
roles:
- cron/cron-test

执行ansible-playbook test_roles.ymlcron_name被顺利替换为ntpdate_roles_vars

roles vars目录

接上例,我们将roles/cron/cron-test/tasks/main.yml中的vars定义注释掉:

1
2
3
4
5
6
7
8
9
10
11
12
- name: add cron env
cron:
name: PATH
env: yes
value: '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin'

- name: add cron
#vars:
# cron_name: ntpdate_roles_vars
cron: name={{ item.name }} minute={{ item.minute }} hour={{ item.hour }} day={{ item.day }} job={{ item.job }} state=present
with_items:
- { name: "{{ cron_name }}", minute: "*/10", hour: "*", day: "*", job: "/usr/sbin/ntpdate 10.0.2.165 >/dev/null 2>&1" }

roles/cron/cron-test/vars/main.yml中添加变量定义

1
cron_name: ntpdate_vars_dir

roles default目录

同roles vars目录,在roles default目录的main.yml也可进行变量定义。但该目录定义的优先级要低,容易被覆盖,一般作为默认值使用。

group_vars目录

在roles的同级目录,新建group_vars目录,子目录以hosts文件中的组命名。group_vars/all目录为系统默认,意为所有组。特定组的变量优先级高于all中定义。

1
2
3
4
5
6
# tree group_vars/
group_vars/
└── test
└── main.yml

1 directory, 1 file

group_vars/test/main.yml的内容:

1
cron_name: "ntpdate_group_vars"

注意:在hosts文件中,某ip隶属于多个分组时,可能会出现不合预期的问题。

例如,hosts文件内容如下:

1
2
3
4
5
[test]
10.1.2.32

[webserver]
10.1.2.32

group_vars定义如下:

1
2
3
4
5
group_vars/all/main.yml中定义:
test_node: false

group_vars/test/main.yml中定义:
test_node: true

此时,即使playbook指定webserver组,test_node的值仍然为true

hosts文件

hosts文件中使用[组名:vars]来为组定义变量。all组名为系统默认,意为所有组。特定组的变量优先级高于all中定义。

1
2
[test:vars]
cron_name=ntpdate_hosts

register注册变量

我们可以在调用模块的时候使用register语句来注册变量。

测试playbook内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
- name: test for vars
hosts: test
tasks:
- name: show something
command: echo hello_world
register: info
- debug: var=info

- name: add cron
cron: name={{ item.name }} minute={{ item.minute }} hour={{ item.hour }} day={{ item.day }} job={{ item.job }} state=present
with_items:
- { name: "{{ info.stdout }}", minute: "*/10", hour: "*", day: "*", job: "/usr/sbin/ntpdate 10.0.2.165 >/dev/null 2>&1" }

运行结果:

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
# ansible-playbook vars.yml

PLAY [test for vars] ***********************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [10.1.1.199]

TASK [show something] **********************************************************************************************
changed: [10.1.1.199]

TASK [debug] *******************************************************************************************************
ok: [10.1.1.199] => {
"info": {
"changed": true,
"cmd": [
"echo",
"hello_world"
],
"delta": "0:00:00.018125",
"end": "2019-03-13 14:25:32.278622",
"failed": false,
"rc": 0,
"start": "2019-03-13 14:25:32.260497",
"stderr": "",
"stderr_lines": [],
"stdout": "hello_world",
"stdout_lines": [
"hello_world"
]
}
}

TASK [add cron] ****************************************************************************************************
changed: [10.1.1.199] => (item={u'hour': u'*', u'job': u'/usr/sbin/ntpdate 10.0.2.165 >/dev/null 2>&1', u'day': u'*', u'minute': u'*/10', u'name': u'hello_world'})

PLAY RECAP *********************************************************************************************************
10.1.1.199 : ok=4 changed=2 unreachable=0 failed=0

ansible变量优先级

ansible中的变量优先级从高到低依次为:

  • 命令行传递
  • roles tasks
  • roles vars
  • playbook
  • group_vars
  • hosts
  • roles default
  • playbook及以上优先级中变量定义,若变量名与fact变量重名,则fact变量将被赋值为自定义值
  • register注册变量相当于在register所在playbook定义的变量,优先级同理。

参考《奔跑吧Ansible》