Ansible 变量的使用详解

Playbook 变量


ansible中使用变量,能够让我们的工作变得更加灵活

定义变量

变量名应该由字母、数字、下划线组成,变量名需要字母开头,ansible内置的关键字不能作为变量名使用

 

Playbook 变量定义


使用vars关键字可以在当前playbook中进行变量定义,让我们要使用变量的时候,则需要引用对应变量名,使用{{ 变量名 }}可以引用对应变量。

vars:

变量简单定义

[root@localhost ~]# cat vars.yml 
- hosts: all
  remote_user: root
  vars:                     #定义变量
    file_name: test.txt     #变量名(随意):file_name,变量的内容:test.txt
  tasks:                    #Task定义远程主机上执行的任务列表
    - name: file mode create file vars
      file: path=/tmp/{{file_name}} state=touch 

定义多个变量

- hosts: all
  vars:   
    t1: v1
    t2: v2

除了上述语法,也可用YAML快序列语法定义变量

- hosts: all
  vars:   
    - t1: v1
    - t2: v2
# cat playbook.yml
---
- hosts: example
  vars:
    foo: bar
  tasks:
    # print "Variable 'foo' is set to bar ".
    - debug: msg="Variable 'foo' is set to {{ foo }}"

定义变量时,还可以类似以"属性"的方式定义变量 

- hosts: all
  gather_facts: false
  remote_user: root
  vars:
    nginx:
      proxy_1: /etc/nginx/conf.d/nginx_1.proxy
      proxy_2: /etc/nginx/conf.d/nginx_2.proxy
  tasks:
  - name: task1
    file: path={{nginx.proxy_1}} state=touch
  - name: task2
    file: path={{nginx['proxy_2']}}  state=touch  # 第二种引用变量.属性的方法


[root@www ~]# ansible-playbook var.yml 
................................................................................
192.168.179.99             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

单独变量文件 :

创建nginx_vars.yaml文件,定义变量

nginx:
  proxy_1: /etc/nginx/conf.d/nginx_1.proxy
  proxy_2: /etc/nginx/conf.d/nginx_2.proxy

 在nginx_vars.yaml文件中定义完变量后,即可在playbook中引入包含变量的文件

- hosts: all
  gather_facts: false
  remote_user: root
  vars_files:
  - ~/nginx_vars.yaml
  
  tasks:
  - name: task1
    file: path={{nginx.proxy_1}} state=touch
  - name: task2
    file: path="{{nginx['proxy_2']}}" state=touch


[root@www ~]# ansible-playbook var.yml 
.................................................................................
192.168.179.99             : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

该例中使用vars_files关键字引入对应的变量文件,然后使用文件中的变量,该关键字可以引入一个变量文件,也可以引入多个变量文件,每个被引入的文件都需要以-开头,varsvars_files可以同时使用

注意: 在 vars.yml 文件中,定义变量的代码是顶格写的。这就是当变量被独立出来定义时的一个特殊之处,即当在独立文件中定义变量时,变量可在YAML中顶格进行定义,也不需要vars标识。

 

inventory 文件定义变量


在 Ansible 中,Inventory 文件通常是指 Ansible 的主机和组的定义文件 Hosts(默认路径为/etc/ansible/hosts,简称Hosts文件)。在 Hosts 文件中,变量会被定义在主机名的后面或组名的下方,如下面这个例子所示:

[shanghai]
app1.example.com proxy_state=present 
app2.example.com proxy_state=absent 
#为主机组指定变量,作用范围为整个主机组
[shanghai: vars]
cdn_host=sh.static.example.com api_version=3.0

在 Inventory 文件中直接定义变量方法虽然简单直观,但当所需要定义的变量多,并且在被多台主机同时应用的时候,这种方法就会显得非常麻烦。而且,事实上,Ansible 的官方手册中也并不建议人们把变量直接定义在 Hosts 文件中。
在执行 Ansible 命令时,Ansible 默认会从/etc/ansible/host_vars/ 和 /etc/ansible/group_vars/ 两个目录下读取变量定义,如果/etc/ansible 下面没有这两个目录,可以直接手动创建,并且可以在这两个目录中创建与 Hosts 文件中主机名或组名同名的文件来定义变量。
举例来说,我们现在要给主机 app1.example.com 设置一组变量,那就可以直接在/etc/ansible/host_vars/ 目录下创建一个名为 app1.example.com 的空白文件,然后在文件中以 YAML 语法来定义所需的变量,如以下代码所示:

# cat /etc/ansible/host_vars/app1.example.com
---
foo: bar
baz: qux

 如此一来,变量 foo 和 baz 将自动定义给主机 app1.example.com。

同理,要想针对整个 shanghai 主机组定义一些变量,则只需在/etc/ansible/group_vars/目录下创建与主机组同名的 YAML 文件来定义变量就可以了:

# cat /etc/ansible/group_vars/group_example
---
admin: layn

也可以在/etc/ansible/group_vars 和/etc/ansible/host_vars 两个目录下定义all文件,来一次性为所有的主机组和主机定义变量 

 

Playbook 变量注册


注册变量,其实就是将操作的结果,包括标准输出和标准错误输出,保存到变量中,然后再根据这个变量的内容来决定下一步的操作,在这个过程中用来保存操作结果的变量就叫注册变量。我们在 Playbook 中使用 register 来声明一个变量为注册变量。 

register关键字可以存储指定命令的输出结果到一个自定义的变量中,它还有一个非常棒的用法,就是我们需要判断对执行了某个操作或某个命令后,如何做出相应的响应处理(执行其它的ansible语句),也会用到它。

register简单实用

- hosts: all
  gather_facts: false
  remote_user: root
  tasks:
  - name: register vars
    shell: hostname
    register: system_status
  - name: display vars
    debug: msg={{system_status.stdout}}

[root@www ~]# ansible-playbook var.yml 
************
changed: [192.168.179.99]
TASK [display vars] ********************************************************************************************************************************
ok: [192.168.179.99] => {
    "msg": "www.lu.com"
}

192.168.179.99             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
  • 第一个shell执行完后,使用register获取数据到system_status
  • system_status是一个key/value字典
  • debug输出System_Status.stdout的具体内容

 

register生产示例


我需要判断sda1是否存在,如果存在则执行文件拷贝

- hosts: all
  gather_facts: no
  remote_user: root

  tasks:
    - name: Create a register to represent the status if the /dev/sda1 exsited
      shell: df -h | grep sda1
      register: dev_sda1_result
      ignore_errors: True

    - name: Copy test.sh to all hosts
      copy: src=/root/test.sh dest=/tmp/test.sh mode=755
      when: dev_sda1_result.rc == 0

 当df -h | grep sda1执行后,会在dev_sda1_result里写入执行结果,然后dev_sda1_result.rc里的rc就是命令的返回状态,非0表示执行失败,ignore_errors关键字一定要设置为True,否则如果命令执行不成功,即echo $?不为0,则在语句后面的ansible语句不会被执行,导致程序中止。

register多条件判断

然后在when中用and或者or来组合判断。比如当两种条件之一成功:

    - name: Copy test.sh to all hosts
      copy: src=/root/test.sh dest=/tmp/test.sh mode=755
      when: ( dev_sda1_result.rc == 0 ) or ( dev_sda2_result.rc == 0  )

在ansible的playbook中task之间的相互传递变量

register.yml

---
- hosts: all
  gather_facts: no
  tasks:
    - name: register vars
      shell: hostname
      register: info
    - name: display vars
      debug: msg="{{info.stdout}}"
  • 第一个shell执行完后,使用register获取数据到info里
  • info是一个key value字典
  • debug输出info.stdout的具体内容

 

内置变量


hostvars
groups
group_names
inventory_hostname
play_hosts
inventory_hostname_short

 

变量优先级


变量优先级由高到低如下:

  1. 在命令行中定义的变量(即用 -e 定义的变量);
  2. 在 Inventory 中定义的连接变量(比如ansible_ssh_user);
  3. 大多数的其他变量(命令行转换、play中的变量、included 的变量、role 中的变量等);
  4. 在 Inventory 定义的其他变量;
  5. 由系统通过 gather_facts 方法发现的 Facts;
  6. “Role 默认变量”, 这个是默认的值,很容易丧失优先权。

 

变量定义建议


  1. Role中的默认变量应设置得尽可能的合理,因为它优先级最低
  2. Playbook 中应尽量少地定义变量,Playbook 中用的变量应尽量定义在专门的变量文件中,通过 vars_files 引用,或定义在 Inventory 文件中
  3. 只有真正与主机或主机组强相关的变量才定义在 Inventory 文件中
  4. 应尽量少地在动态或静态的 Inventory 源文件中定义变量,尤其是不要定义那些很少在 Playbook 中被用到的变量
  5. 应尽量避免在命行中使用 -e 选项来定义变量。只有在我们不用去关心项目的可维护性和任务幂等性的时候,才建议使用这种变量定义方式。比如只是做本地测试,或者运行一个一次性的 Playbook 任务。

你可能感兴趣的:(Ansible,ansible)