playbook变量与引用,playbook变量引用


在介绍playbook变量与引用的时候我们先来了解下Ansible的变量来源。

注:笔者的实验环境如下:
192.168.116.128 ansiblecontrol 部署ansible的server环境 负责下发指令给另外两台节点
192.168.116.129 web1应用着一个nginx服务
192.168.116.130 此节点上部署有一个用devstack部署的openstack环境

三个节点都是跑在vmware上的虚拟机,使用NAT模式与宿主机链接。

变量来源

1.inventory file中定义的变量
2.playbook中定义的变量
3.include文件和角色中定义的变量
4.系统facts变量,可以通过 ansible hostname -m setup来获取。当然你也可以通过安装拓展包来获取更多的系统变量信息。例如拓展facter和ohai。
5.local facts

通过Inventory文件定义主机以及主机组变量

首先我们来看下对应的Inventory文件,Ansible默认的Inventory文件是INI格式,比如之前用到的Inventory文件,然后分别针对每台主机设置一个变量名称叫作key,接着使用debug模块来查看变量的值,最后通过对Nginx组定义一个变量同样使用debug模块查看。可以配置一个inventory文件如下:

192.168.116.129 key=129

[nginx]
192.168.116.129

[nginx:vars]
ansible_python_interpreter=/usr/lib64/python2.7

编写一个playbook文件(文件名为nginx-116.yaml)来验证变量的引用是否正确:

---
  - hosts: nginx
    gather_facts: False
    tasks:
          - name: diplay Host Variable from hostfile
            debug: msg="The {{ inventory_hostname }} Vaule is {{ key }}"

运行的结果如下所示:

发现每台主机都引用了自己定义的变量,接下来我们注释每台主机的变量定义,直接给nginx组定义一个变量,变量名称还是key且值为nginx。

[nginx]
192.168.116.129

[nginx:vars]
ansible_python_interpreter=/usr/lib64/python2.7
key=nginx

注意这种方式是直接给组内进行变量定义。再来运行一下nginx-116.yaml的文件,结果如下:

因为所有主机都处于nginx组内,所以该组定义的变量针对组内所有主机都生效。如果nginx组定义了变量,然后每台主机也定义了变量,只要定义的变量key名称不同,会发生什么样的结果呢?

这里我们该写下inventory文件,定义如下:

192.168.116.129 key=129

[nginx]
192.168.116.129
192.168.116.130

[nginx:vars]
ansible_python_interpreter=/usr/bin/python2.7
key=devstack

然后我们执行下看下结果:

从这里我们可以看到,我们都可以直接引用这些变量,但是如果主机和主机组都定义了变量而且key还都相同,这个时候你会发现单台主机定义的变量会生效。

通过/etc/ansible/下的文件定义主机以及主机组变量

默认使用yum安装ansible的配置文件是在/etc/ansible/目录下,我们还可以使用在该目录下新建host_vars和group_vars目录来针对主机和主机组定义变量,如果是采取其他方式安装的Ansible只需在playbook文件当前目录下新建这两个目录即可。笔者这里是用git安装的ansible,所以我只需要在我指定的playbook路径下创建这两个目录即可。

# head host_vars/*

==> host_vars/192.168.116.129 <==
---
key: 192.168.116.129


==> host_vars/192.168.116.130 <==
---
key: 192.168.116.130

将hosts指定为all然后再执行,结果如下:

我们可以看到每台主机的变量已经生效,这里我们定义一下group_vars下的变量然后我们通过删掉host_vars下每台主机变量定义文件,然后来验证group_vars/下ansible组的变量定义。
group_vars/ansible的定义如下:

# head group_vars/ansible 
---
key: nginx

执行的结果如下:

在这里我们可以知道在inventory file中定义的变量应用优先级是比playbook中通过主机及主机组变量的优先级低的,因为之前可以看到我在inventory file中定义的 key: devstack已经被覆盖了。

通过ansible-playbook命令行传入

前面我们已经介绍了两种主机以及主机组变量的定义方式,这两种方式也是日常使用过程中最常用的两种变量定义方式。这次介绍ansible-playbook命令行传参的方式定义变量,但是默认传进去的变量都是全局变量:

# ansible-playbook /root/playbook/nginx-116.yaml -e "key=Key"

PLAY [all] ************************************************************************************************************************************

TASK [Display Host Variable from hostfile] ****************************************************************************************************
ok: [192.168.116.129] => {
    "msg": "The 192.168.116.129 Vaule is Key"
}
ok: [192.168.116.130] => {
    "msg": "The 192.168.116.130 Vaule is Key"
}

PLAY RECAP ************************************************************************************************************************************
192.168.116.129            : ok=1    changed=0    unreachable=0    failed=0   
192.168.116.130            : ok=1    changed=0    unreachable=0    failed=0

当然也支持同时传多个变量,目前ansible-playbook还支持指定文件的方式传入变量,变量文件的内容支持YAML和JSON两种格式:

# cat var.yaml
---
key: YAML
# cat var.json
{"key": "JSON"}

# ansible-playbook /root/playbook/nginx-116.yaml -e "@var.json"

PLAY [all] ************************************************************************************************************************************

TASK [Display Host Variable from hostfile] ****************************************************************************************************
ok: [192.168.116.129] => {
    "msg": "The 192.168.116.129 Vaule is JSON"
}
ok: [192.168.116.130] => {
    "msg": "The 192.168.116.130 Vaule is JSON"
}

PLAY RECAP ************************************************************************************************************************************
192.168.116.129            : ok=1    changed=0    unreachable=0    failed=0   
192.168.116.130            : ok=1    changed=0    unreachable=0    failed=0   

# ansible-playbook /root/playbook/nginx-116.yaml -e "@var.yaml"

PLAY [all] ************************************************************************************************************************************

TASK [Display Host Variable from hostfile] ****************************************************************************************************
ok: [192.168.116.129] => {
    "msg": "The 192.168.116.129 Vaule is YAML"
}
ok: [192.168.116.130] => {
    "msg": "The 192.168.116.130 Vaule is YAML"
}

PLAY RECAP ************************************************************************************************************************************
192.168.116.129            : ok=1    changed=0    unreachable=0    failed=0   
192.168.116.130            : ok=1    changed=0    unreachable=0    failed=0   

可见这种定义变量的优先级会比之前两个都要高。

在playbook文件内使用vars

我们可以在playbook文件内通过vars字段定义变量。

---
  - hosts: all
    gather_facts: False
    vars:
        key: Ansible
    tasks:
          - name: Display Host Variable from hostfile
            debug: msg="The {{ inventory_hostname }} Vaule is {{ key }}"

执行的结果如下:

在playbook文件内使用vars_files

我们还可以在playbook文件内通过vars_files字段引用变量,首先把所有的变量定义到某个文件内,然后在playbook文件内使用vars_files参数引用这个变量文件,我们再回到之前的variabled.yaml文件:

---
  - hosts: all
    gather_facts: False
    vars_files:
        - var.yaml
    tasks:
          - name: Display Host Variable from hostfile
            debug: msg="The {{ inventory_hostname }} Vaule is {{ key }}"

因为这个var.yaml文件在之前的时候我们已经定义好了,所以直接使用。var.yaml文件就是变量定义存放的文件,这个时候直接运行这个playbook:

使用register内的变量

Ansible playbook内task之间还可以互相传递数据,比如我们总共有两个tasks,其中第2个task是否执行是需要判断第1个task运行后的结果,这个时候我们就得在task之间传递数据,需要把第1个task执行的结果传递给第2个task。Ansible task之间传递数据使用register方式。

---
  - hosts: all
    gather_facts: False
    #vars_files:
    #    - var.yaml
    tasks:
          #- name: Display Host Variable from hostfile
          #  debug: msg="The {{ inventory_hostname }} Vaule is {{ key }}"
          - name: register variable
            shell: hostname
            register: info
          - name: display variable
            debug: msg="The varibale is {{ info }}"

这里我们把第一个task执行hostname的结果register给info这个变量,然后在第二个task把这个结果使用debug模块打印出来,执行结果如下:


这里info返回的信息是一组字典,里面包含了许多信息,例如有时间状态变化的信息,同时包含有执行指令的信息。作为字典我们想要找到我们只想显示的信息则只需要指定key就行:

# cat nginx-116.yaml
---
  - hosts: all
    gather_facts: False
    #vars_files:
    #    - var.yaml
    tasks:
          #- name: Display Host Variable from hostfile
          #  debug: msg="The {{ inventory_hostname }} Vaule is {{ key }}"
          - name: register variable
            shell: hostname
            register: info
          - name: display variable
            debug: msg="The varibale is {{ info['stdout'] }}"

执行的结果如下:

使用vars_prompt传值

Ansible还支持在运行playbook的时候通过交互式地方式给定义好的参数传入变量值,只需在playbook中定义vars_prompt的变量名和交互式提示内容即可。当然Ansible还可以对输入的变量值进行加密处理,比如采用SHA512和MD5算法加密。需要注意的是,如果要对变量值进行加密的话,Ansible机器上需要安装passlib python库。

---
-
 hosts: all
 gather_facts: False
 vars_prompt:
    -
     name: "one"
     prompt: "Please input one value"
     private: no
    -
     name: "two"
     prompt: "Please input two value"
     default: 'good'
     private: yes

 tasks:
    -
     name: display one value
     debug: msg= "one value is {{ one }}"
    -
     name: display two value
     debug: msg= "two value is {{ two }}"

在例子中通过vars_prompt参数进行交互传入两个变量的值,变量名分别是one和two,one变量定义为非私有变量,two变量定义为私有变量并且还提供一个默认值。如果不给变量two传入值的话,two变量的值将会为默认值。private:yes和private:no的作用是显示交互模式下输入的变量值。

相关内容

    暂无相关文章