Ansible Playbook中的变量与引用
Ansible是一个系列文章,我会尽量以通俗易懂、诙谐幽默的总结方式给大家呈现这些枯燥的知识点,让学习变的有趣一些。
Ansible系列博文直达链接:Ansible入门系列
前言
前面有说到使用playbook来搞一些复杂的功能,我们使用YAML来写playbook,就像我们用其它语言写代码一样,也是可以定义变量的,能定义变量,那这个功能就不得了了,就有必要好好的讲讲了。变量就好比playbook的翅膀,让ansible playbook的使用场景大大增多。在Ansible中,变量的玩法有下面这几种:
- 通过inventory定义变量
- 通过文件定义变量
- 使用远程主机的系统变量
- 通过ansible-playbook命令行传入变量
- 通过vars定义变量
- 通过vars_files定义变量
- 通过register注册变量
- 使用vars_prompt传入变量
玩法还挺多的,下面就对这些玩法进行一一的总结,争取一次把Ansible中变量的玩法吃透。
通过inventory定义变量
我们可以在inventory文件中定义变量,然后在playbook中使用这些变量。到底怎么玩,下面我通过一段代码来举例说明:
192.168.1.3 key=10086
[server1]
192.168.1.3
[server1:vars]
key=10087
ansible_ssh_user='test1'
上面是我的inventory文件内容,我针对192.168.1.3这个主机定义了一个变量key,然后又针对server1这个主机组定义了变量key和ansible_ssh_user。然后我来写一个测试playbook,看下在inventory文件中定义的变量怎么用。
---
- hosts: server1
tasks:
- name: Display var from inventory file
debug: msg="The {{ inventory_hostname }} value is {{ key }}"
输出内容如下:
[jelly@localhost yaml]$ ansible-playbook inventoryVar.yaml
PLAY [server1] *************************************
TASK [Gathering Facts] *****************************
ok: [192.168.1.3]
TASK [Display var from inventory file] *************
ok: [192.168.1.3] => {
"msg": "The 192.168.1.3 value is 10086"
}
PLAY RECAP *****************************************
192.168.1.3 : ok=2 changed=0 unreachable=0 failed=0
可以看到,我们通过{{}}
来引用变量,同时也看到,主机定义的变量的优先级高于主机组定义的变量。
通过文件定义变量
通过文件定义变量这种玩法就用的更多了,在后面讲到role的时候,还会专门用到这个知识点的。说白了就是我们在playbook的同级目录建立两个名分别为host_vars
和group_vars
的文件夹,分别用来定义主机和主机组的变量。下面是我的文件结构:
[jelly@localhost yaml]$ tree
.
├── fileVar.yaml
├── group_vars
│ └── server1
├── host_vars
│ └── 192.168.1.3
host_vars
文件夹下的文件用被管理主机的IP为文件名,比如此处的192.168.1.3,文件内容按照YAML的语法进行定义,比如此处192.168.1.3的内容如下:
key: 10086
group_vars
文件夹下的文件用inventory下定义的组名来命名,比如此处的server1,文件内容也是按照YAML语法进行定义,比如此处server1的内容如下:
foo:
field1: one
field2: two
在来看我的测试playbook,它是这样的:
---
- hosts: server1
tasks:
- name: Display var from file
debug: msg="The {{ inventory_hostname }} value is {{ key }} and {{ foo.field1 }}"
重点是我们可以通过foo.field1
这种方式来引用复杂的变量,运行结果如下:
[jelly@localhost yaml]$ ansible-playbook fileVar.yaml
PLAY [server1] *************************************
TASK [Gathering Facts] *****************************
ok: [192.168.1.3]
TASK [Display var from file] ***********************
ok: [192.168.1.3] => {
"msg": "The 192.168.1.3 value is 10086 and one"
}
PLAY RECAP *****************************************
192.168.1.3 : ok=2 changed=0 unreachable=0 failed=0
使用远程主机的系统变量
不知道大家有没有看过上篇说过的Ansible Facts,我们通过setup
模块获取的远程主机的信息可以直接作为变量在playbook中引用。是的,这样就大大方便了我们的工作。下面牛通过一个简单的playbook来看看怎么玩。
---
- hosts: server1
tasks:
- name: Echo System
debug: msg="{{ ansible_os_family }}"
ansible_os_family
是ansible_facts
节点下的一个值,我们可以直接在playbook中直接应用。就是这么简单!
通过ansible-playbook命令行传入变量
上面的三种方式在我们日常工作中用的比较多,接下来说说怎么通过ansible-playbook命令行传参的方式定义变量。先来看下我们的测试YAML脚本:
---
- hosts: server1
tasks:
- name: ansible-playbook command var
debug: msg="var1 is {{ var1 }}; var2 is {{ var2 }}"
我们在命令行输入以下命令进行执行:
ansible-playbook commandVar1.yaml -e "var1=1 var2=2"
除了这里说的直接传入变量,目前ansible-playbook还支持指定文件的方式传入变量,变量文件的内容支持YAML和JSON两种格式,来看下怎么玩!!!
我这里准备了两个文件,分别是YAML和JSON格式的。内容如下:
[jelly@localhost yaml]$ cat var.json
{"var1":"10086", "var2":"10087"}
[jelly@localhost yaml]$ cat var.yaml
---
var1: 10086
var2: 10087
接下来,我在命令行指定var.json或者var.yaml文件传入变量:
ansible-playbook commandVar1.yaml -e "@var.json"
玩起来还是蛮简单的!
注意:ansible-playbook命令行传进去的变量都是全局变量
通过vars定义变量
通过vars定义变量,这个就简单了,在之前的文章中也有说过,这里就通过一个简单的YAML脚本来演示。
---
- hosts: server1
vars:
var1: 10086
var2: 10087
tasks:
- name: Display vars
debug: msg="var1 is {{var1}}, var2 is {{var2}}"
这个就是这么简单,自己理解去吧!!!
通过vars_files定义变量
这种玩法就有点意思了,怎么说呢。我们可以把所有的变量定义到某个文件内,然后在playbook文件内使用vars_files
参数引用这个变量文件。比如这样子:
---
- hosts: server1
vars_files:
- var.yaml
tasks:
- name: Display vars
debug: msg="var1 is {{var1}}, var2 is {{var2}}"
通过register注册变量
如果我们有需要在两个task之间传递数据的场景,就可以考虑使用这里的register
注册变量了,比如我们在一个playbook中有两个task,分别是TaskA和TaskB,如果TaskB需要根据TaskA的执行结果做一些判断,这个时候就需要在两个task之间传递数据,把TaskA的执行结果传递给TaskB。怎么搞?看下面的代码。
---
- hosts: server1
tasks:
- name: TaskA
shell: hostname
register: info
- name: TaskB
debug: msg="TaskA's output is {{info}}"
执行上面的YAML脚本,输出结果如下:
[jelly@localhost yaml]$ ansible-playbook registerVar.yaml
PLAY [server1] ******************************************
TASK [Gathering Facts] **********************************
ok: [192.168.1.3]
TASK [TaskA] ********************************************
changed: [192.168.1.3]
TASK [TaskB] ********************************************
ok: [192.168.1.3] => {
"msg": "TaskA's output is {'changed': True, 'end': '2019-10-08 08:34:11.129667', 'stdout': 'localhost.localdomain', 'cmd': 'hostname', 'rc': 0, 'start': '2019-10-08 08:34:11.123739', 'stderr': '', 'delta': '0:00:00.005928', 'stdout_lines': ['localhost.localdomain'], 'stderr_lines': [], 'failed': False}"
}
PLAY RECAP **********************************************
192.168.1.3 : ok=3 changed=1 unreachable=0 failed=0
从上面的YAML脚本,我们可以看到TaskA中执行的hostname
命令,它的输出结果注册到了info中,这样一来,在TaskB中就可以引用info了,完成数据在task之间的传递。
同时也可以看到,info的结果是一段Python字段数据,里面存储着很多信息包含执行时间、状态变化等信息。register的输出数据结果都是Python字典,我们可以很容易地挑选出我们想要的信息,比如这样:
---
- hosts: server1
tasks:
- name: TaskA
shell: hostname
register: info
- name: TaskB
debug: msg="TaskA's output is {{info.stdout}}"
使用vars_prompt传入变量
Ansible还支持在运行playbook的时候通过交互式的方式给定义好的参数传入变量值,只需要在playbook中定义vars_prompt
的变量名和交互式提示内容即可!就像下面这样:
---
- hosts: server1
vars_prompt:
- name: "var1"
prompt: "Please input var1"
private: no
- name: "var2"
prompt: "Please input var2"
default: '10086'
private: yes
tasks:
- name: echo var1
debug: msg="var1 is {{var1}}"
- name: echo var2
debug: msg="var2 is {{var2}}"
在运行上面的YAML脚本的时候,会提示进行变量输入,其中我们定义的var1为非私有变量,var2为私有变量还有一个默认值。当定义为私有变量时,在终端输入变量时,则不会显示对应的值,就像我们ssh登陆主机,输入密码看不见一样。
总结
哦,我的天哪!总结完一看,这么长,这么多内容;但是还好,内容虽多,但是蛮简单的。在上班路上,或者下班路上,看看这么一篇总结,也还是不错的。希望你看完这篇文章后,能感叹一下,Ansible的变量玩法还有这么多啊。玩了Ansible这么久,就是感觉这货一直都在给我带来惊喜,越来越好玩,越来越耐玩!还等什么,搞个测试环境,也玩一玩!
果冻想,认真玩技术的地方。
2019年10月8日,于内蒙古呼和浩特。