Playbook 详解 之 变量与引用
前言
Ansible 支持利用变量来存储值,并在Ansible 项目的所有文件中重复使用这些值。这可以大大简化项目的创建和维护,并减少错误的数量
提示:本篇文章所使用的环境为centos-8.2基于ansible-2.8.0 搭建
具体环境搭建,请参考:ansible-2.8.0 搭建链接
Ansible 中的变量
通过变量,我们可以轻松地在Ansible 项目中管理给定环境的动态值。例如,变量可能包含这些值:
- 要创建的用户
- 要安装的软件包
- 要重新启动的服务
- 要删除的文件
- 要从互联网检索的存档
变量的命名
变量的命令必须以字母开头,并且只能含有数字、字母、下划线。
在Ansible 中定义变量
一、通过 Inventory 文件定义主机以及主机组变量
- 基于主机定义变量
#编辑Playbook
[root@ansible-server ansible]# vim var1.yml
---
- hosts: all
tasks:
- name: Show var
debug:
msg: The {{ inventory_hostname }} Vaule is {{ key }}
#检查语法
[root@ansible-server ansible]# ansible-playbook var1.yml --syntax-check
playbook: var1.yml
#执行Playbook
[root@ansible-server ansible]# ansible-playbook var1.yml
PLAY [all] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [node04]
ok: [node02]
ok: [node03]
ok: [node01]
TASK [Show var] ****************************************************************************************************
ok: [node01] => {
"msg": "The node01 Vaule is 1"
}
ok: [node04] => {
"msg": "The node04 Vaule is 4"
}
ok: [node02] => {
"msg": "The node02 Vaule is 2"
}
ok: [node03] => {
"msg": "The node03 Vaule is 3"
}
PLAY RECAP *********************************************************************************************************
node01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- 基于主机组定义变量
#定义变量
[root@ansible-server ansible]# vim inventory
#node01 key=1
#node02 key=2
#node03 key=3
#node04 key=4
[dev]
node02
[test]
node03
[prod]
node01
node04
[webservers:children]
dev
test
[webservers:vars]
key=web
#编辑Playbook 文件
---
- hosts: webservers
tasks:
- name: Show var
debug:
msg: The {{ inventory_hostname }} Vaule is {{ key }}
#检查语法
[root@ansible-server ansible]# ansible-playbook var2.yml --syntax-check
playbook: var2.yml
#执行Playbook
[root@ansible-server ansible]# ansible-playbook var2.yml
PLAY [webservers] *********************************************************************************************
TASK [Gathering Facts] ****************************************************************************************
ok: [node02]
ok: [node03]
TASK [Show var] ***********************************************************************************************
ok: [node02] => {
"msg": "The node02 Vaule is web"
}
ok: [node03] => {
"msg": "The node03 Vaule is web"
}
PLAY RECAP ****************************************************************************************************
node02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignore
注意:在主机清单定义变量,主机变量的优先级高于主机组的优先级
二、通过 /etc/ansible/ 下的文件定义主机以及主机组变量
- 基于主机定义变量
#定义变量
[root@ansible-server ansible]# mkdir host_vars
[root@ansible-server ansible]# cd host_vars/
[root@ansible-server host_vars]# echo "key: node01" > node01
[root@ansible-server host_vars]# echo "key: node02" > node02
[root@ansible-server host_vars]# echo "key: node03" > node03
[root@ansible-server host_vars]# echo "key: node04" > node04
#查看定义的变量
[root@ansible-server ~]# cd /ansible/
[root@ansible-server ansible]# head host_vars/*
==> host_vars/node01 <==
key: node01
==> host_vars/node02 <==
key: node02
==> host_vars/node03 <==
key: node03
==> host_vars/node04 <==
key: node04
#执行Playbook
[root@ansible-server ansible]# ansible-playbook var1.yml
PLAY [all] ****************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************
ok: [node03]
ok: [node02]
ok: [node04]
ok: [node01]
TASK [Show var] ***********************************************************************************************
ok: [node01] => {
"msg": "The node01 Vaule is node01"
}
ok: [node04] => {
"msg": "The node04 Vaule is node04"
}
ok: [node02] => {
"msg": "The node02 Vaule is node02"
}
ok: [node03] => {
"msg": "The node03 Vaule is node03"
}
PLAY RECAP ****************************************************************************************************
node01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignore
- 基于主机组定义变量
#定义变量
[root@ansible-server ansible]# mkdir group_vars
[root@ansible-server ansible]# cd group_vars/
[root@ansible-server group_vars]# echo "key: https" > prod
#删除主机变量文件--主机优先生效于主机组
[root@ansible-server group_vars]# cd ..
[root@ansible-server ansible]# rm -fr host_vars/
#执行Playbook
[root@ansible-server ansible]# ansible-playbook var1.yml
PLAY [all] ****************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************
ok: [node01]
ok: [node04]
ok: [node02]
ok: [node03]
TASK [Show var] ***********************************************************************************************
ok: [node01] => {
"msg": "The node01 Vaule is https"
}
ok: [node04] => {
"msg": "The node04 Vaule is https"
}
ok: [node02] => {
"msg": "The node02 Vaule is web"
}
ok: [node03] => {
"msg": "The node03 Vaule is web"
}
PLAY RECAP ****************************************************************************************************
node01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
三、通过 ansible-playbook 命令行传入变量
#直接传入变量的值
[root@ansible-server ansible]# ansible-playbook var1.yml -e 'key=webservers'
PLAY [all] ****************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************
ok: [node03]
ok: [node04]
ok: [node02]
ok: [node01]
TASK [Show var] ***********************************************************************************************
ok: [node01] => {
"msg": "The node01 Vaule is webservers"
}
ok: [node04] => {
"msg": "The node04 Vaule is webservers"
}
ok: [node02] => {
"msg": "The node02 Vaule is webservers"
}
ok: [node03] => {
"msg": "The node03 Vaule is webservers"
}
PLAY RECAP ****************************************************************************************************
node01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignore
#通过文件传入变量
[root@ansible-server ansible]# echo '{"key": "test"}' > var.test
[root@ansible-server ansible]# more var.test
{"key": "test"}
[root@ansible-server ansible]# ansible-playbook var1.yml -e '@var.test'
PLAY [all] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [node03]
ok: [node01]
ok: [node04]
ok: [node02]
TASK [Show var] ****************************************************************************************************
ok: [node01] => {
"msg": "The node01 Vaule is test"
}
ok: [node04] => {
"msg": "The node04 Vaule is test"
}
ok: [node02] => {
"msg": "The node02 Vaule is test"
}
ok: [node03] => {
"msg": "The node03 Vaule is test"
}
PLAY RECAP *********************************************************************************************************
node01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
四、在 playbook 文件内使用 vars
[root@ansible-server ansible]# vim var1.yml
---
- hosts: all
vars:
key: tests
tasks:
- name: Show var
debug:
msg: The {{ inventory_hostname }} Vaule is {{ key }}
#执行Playbook
[root@ansible-server ansible]# ansible-playbook var1.yml
PLAY [all] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [node03]
ok: [node04]
ok: [node01]
ok: [node02]
TASK [Show var] ****************************************************************************************************
ok: [node01] => {
"msg": "The node01 Vaule is tests"
}
ok: [node04] => {
"msg": "The node04 Vaule is tests"
}
ok: [node02] => {
"msg": "The node02 Vaule is tests"
}
ok: [node03] => {
"msg": "The node03 Vaule is tests"
}
PLAY RECAP *********************************************************************************************************
node01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
五、在 playbook 文件内使用 vars_files
[root@ansible-server ansible]# vim var3.yml
---
- hosts: all
vars_files:
- var.test
tasks:
- name: Show var
debug:
msg: The {{ inventory_hostname }} Vaule is {{ key }}
#执行Playbook
[root@ansible-server ansible]# ansible-playbook var3.yml
PLAY [all] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [node01]
ok: [node03]
ok: [node04]
ok: [node02]
TASK [Show var] ****************************************************************************************************
ok: [node01] => {
"msg": "The node01 Vaule is test"
}
ok: [node04] => {
"msg": "The node04 Vaule is test"
}
ok: [node02] => {
"msg": "The node02 Vaule is test"
}
ok: [node03] => {
"msg": "The node03 Vaule is test"
}
PLAY RECAP *********************************************************************************************************
node01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
六、使用 register 内的变量
[root@ansible-server ansible]# vim var4.yml
---
- hosts: all
tasks:
- name: register variable
shell: hostname
register: smm
- name: show register
debug:
msg: hostname is {{ smm }}
#执行Playbook
[root@ansible-server ansible]# ansible-playbook var4.yml
PLAY [all] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [node02]
ok: [node01]
ok: [node03]
ok: [node04]
TASK [register variable] *******************************************************************************************
changed: [node04]
changed: [node02]
changed: [node03]
changed: [node01]
TASK [show register] ***********************************************************************************************
ok: [node01] => {
"msg": "hostname is {'cmd': 'hostname', 'stdout': 'node01', 'stderr': '', 'rc': 0, 'start': '2020-10-01 21:30:16.886943', 'end': '2020-10-01 21:30:16.891430', 'delta': '0:00:00.004487', 'changed': True, 'stdout_lines': ['node01'], 'stderr_lines': [], 'failed': False}"
}
ok: [node04] => {
"msg": "hostname is {'cmd': 'hostname', 'stdout': 'node04', 'stderr': '', 'rc': 0, 'start': '2020-10-01 21:29:45.990403', 'end': '2020-10-01 21:29:45.995018', 'delta': '0:00:00.004615', 'changed': True, 'stdout_lines': ['node04'], 'stderr_lines': [], 'failed': False}"
}
ok: [node02] => {
"msg": "hostname is {'cmd': 'hostname', 'stdout': 'node02', 'stderr': '', 'rc': 0, 'start': '2020-10-01 21:29:43.287218', 'end': '2020-10-01 21:29:43.292358', 'delta': '0:00:00.005140', 'changed': True, 'stdout_lines': ['node02'], 'stderr_lines': [], 'failed': False}"
}
ok: [node03] => {
"msg": "hostname is {'cmd': 'hostname', 'stdout': 'node03', 'stderr': '', 'rc': 0, 'start': '2020-10-01 21:30:01.085457', 'end': '2020-10-01 21:30:01.090727', 'delta': '0:00:00.005270', 'changed': True, 'stdout_lines': ['node03'], 'stderr_lines': [], 'failed': False}"
}
PLAY RECAP *********************************************************************************************************
node01 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
可以看到 info 的结果是一段 Python 字典数据, 里面存储着很多信息包括执行时间状态变化输岀等信
息。 register 的输岀数据结果都是 Python 字典, 我们可以很容易地挑选出我们想要的信息, 比如下
面想标准输出 stdout 的信息时, 只需要指定 stdout这个 key 即可
[root@ansible-server ansible]# vim var4.yml
---
- hosts: all
tasks:
- name: register variable
shell: hostname
register: smm
- name: show register
debug:
msg: hostname is {{ smm['stdout'] }}
#执行Playbook
[root@ansible-server ansible]# ansible-playbook var4.yml
PLAY [all] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [node03]
ok: [node01]
ok: [node02]
ok: [node04]
TASK [register variable] *******************************************************************************************
changed: [node01]
changed: [node02]
changed: [node04]
changed: [node03]
TASK [show register] ***********************************************************************************************
ok: [node01] => {
"msg": "hostname is node01"
}
ok: [node04] => {
"msg": "hostname is node04"
}
ok: [node02] => {
"msg": "hostname is node02"
}
ok: [node03] => {
"msg": "hostname is node03"
}
PLAY RECAP *********************************************************************************************************
node01 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
注意:python 字典 可以使用 smm[‘stdout’] 或者 smm.stdout 去其中的值
七、使用 vars_prompt 传入
[root@ansible-server ansible]# vim var5.yml
---
- hosts: all
vars_prompt:
- name: one
prompt: please input first value
private: no
- name: two
prompt: please input second value
private: yes
default: two
tasks:
- name: show first value
debug:
msg: one value is {{ one }}
- name: show second value
debug:
var: two
#执行Playbook,并分别键入1 、2
[root@ansible-server ansible]# ansible-playbook var5.yml
please input first value: 1
please input second value [two]:
PLAY [all] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [node04]
ok: [node01]
ok: [node03]
ok: [node02]
TASK [show first value] ********************************************************************************************
ok: [node01] => {
"msg": "one value is 1"
}
ok: [node04] => {
"msg": "one value is 1"
}
ok: [node02] => {
"msg": "one value is 1"
}
ok: [node03] => {
"msg": "one value is 1"
}
TASK [show second value] *******************************************************************************************
ok: [node01] => {
"two": "2"
}
ok: [node04] => {
"two": "2"
}
ok: [node02] => {
"two": "2"
}
ok: [node03] => {
"two": "2"
}
PLAY RECAP *********************************************************************************************************
node01 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node02 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node03 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node04 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
八、使用数组方式定义变量
#定义用户数组文件
[root@ansible-server ansible]# vim users.yml
users:
bob:
user_name: bob
home_dir: /home/bob
user_shell: /sbin/nologin
#编辑Playbook
[root@ansible-server ansible]# vim create_user.yml
---
- hosts: dev
vars_files:
- users.yml
tasks:
- name: create user
user:
name: '{{ users.bob.user_name }}'
shell: '{{ users.bob.user_shell }}'
home: '{{ users.bob.home_dir}}'
#检查语法
[root@ansible-server ansible]# ansible-playbook create_user.yml --syntax-check
playbook: create_user.yml
#执行Playbook
[root@ansible-server ansible]# ansible-playbook create_user.yml
PLAY [dev] *********************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************
ok: [node02]
TASK [create user] *************************************************************************************************
ok: [node02]
PLAY RECAP *********************************************************************************************************
node02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#查看执行结果
[root@node02 ~]# tail -1 /etc/passwd
bob:x:1001:1001::/home/bob:/sbin/nologin