ansible 四、playbook(变量与优先级)

大番茄 2020年02月14日 2,913次浏览

https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html

简单区分的话有几种:

  1. 定义变量
  2. 注册变量
  3. facts变量
  4. magic变量
  5. connect变量

其中3,4,5为特殊变量,不能由用户设置, 但可以覆盖。
https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html#special-variables

变量可以使用{{}}调用,playbook与jinjia2模板中都是。

magic与connect变量ansible命令行也可以使用。

1、定义变量

变量可以通过inventory文件、group_vars、host_vars以及命令行传递, 这两种在inventory部分都有介绍。 这里主要是从playbook文件里定义变量。
varsvar_files 关键字

vars:

- hosts: webserver
  gather_facts: False
  vars:
    server_name: www.test.pub
    http_port: 4343
  tasks:
  - name: print vars
    vars:
      test: hello
    debug:
      msg: "server_name: {{ server_name }}, http_port: {{ http_port }}, test: {{ test }}"
TASK [print vars] *******************************************************************************************************************
ok: [172.100.102.92] => {
    "msg": "server_name: www.test.pub, http_port: 4343, test: hello"
}
ok: [172.100.102.93] => {
    "msg": "server_name: www.test.pub, http_port: 4343, test: hello"
}

vars_files
指定外部变量文件. 外部变量文件需要是yaml格式。不能跟vars一样放到tasks里面。

- hosts: webserver
  gather_facts: False
  vars:
    http_port: 4343
    server_name: www.atest.pub
  vars_files:
    - /vars/vars1.yml

  tasks:
  - name: print vars
    vars:
      test: hello
    debug:
      msg: "server_name: {{ server_name }}, http_port: {{ maxconn }}, test: {{ test }}"

变量文件:

[root@lvs playbook]# cat /vars/vars1.yml
server_name: www.yxingxing.net
maxconn: 2048

执行结果:

TASK [print vars] *******************************************************************************************************************
ok: [172.100.102.92] => {
    "msg": "server_name: www.yxingxing.net, http_port: 2048, test: hello"
}
ok: [172.100.102.93] => {
    "msg": "server_name: www.yxingxing.net, http_port: 2048, test: hello"
}

2、注册变量

获取执行结果为变量内容。
register 关键字

- hosts: 172.100.102.92
  gather_facts: False

  tasks:
  - name: get /root files
    shell: ls /root
    register: root_var

  - name: show root_var
    debug:
      msg: "{{root_var}}"

  - name: show ls /root stdout
    debug: msg={{root_var.stdout}}
TASK [get /root files] **************************************************************************************************************************
changed: [172.100.102.92]

TASK [show root_var] ****************************************************************************************************************************
ok: [172.100.102.92] => {
    "msg": {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": true,
        "cmd": "ls /root",
        "delta": "0:00:00.004385",
        "end": "2020-02-14 12:31:46.147631",
        "failed": false,
        "rc": 0,
        "start": "2020-02-14 12:31:46.143246",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "anaconda-ks.cfg",
        "stdout_lines": [
            "anaconda-ks.cfg"
        ]
    }
}

TASK [show ls /root stdout] *********************************************************************************************************************
ok: [172.100.102.92] => {
    "msg": "anaconda-ks.cfg"
}

命令的返回的结果是一个字典。所以后面获取命令结果需要加上stdout获取字典key的值。 也可以msg={{root_var['stdout']}}

3、facts 变量

facts变量一般用于when条件判断的时候使用,比如目标主机是yum的包管理安装的包名,apt的包管理安装的报名。

由setup模块获取的远程主机的信息。gather_facts 这个关键字就是用来操作是否获取facts变量的。
使用 ansible_facts 变量使用获取到的目标主机变量。

- hosts: 172.100.102.92
  tasks:
  - name: show facts vars
    debug:
      msg: "{{ansible_facts}}"
TASK [show facts vars] **************************************************************************************************************************
ok: [172.100.102.92] => {
    "msg": {
        "_facts_gathered": true,
        "all_ipv4_addresses": [
            "172.100.102.92"
        ],
        "all_ipv6_addresses": [
            "fe80::20c:29ff:fe09:d06a"
        ],
        "ansible_local": {},
        "apparmor": {
            "status": "disabled"
        },
        "architecture": "x86_64",
        "bios_date": "12/12/2018",
        "bios_version": "6.00",
        "cmdline": {
            "BOOT_IMAGE": "/boot/vmlinuz-3.10.0-957.27.2.el7.x86_64",
            "LANG": "en_US.UTF-8",
            "quiet": true,
            "rhgb": true,
            "ro": true,
            "root": "UUID=b57d9d6c-c2c1-4a33-8084-06e22485fde5"
        },
        "date_time": {

.....省略.....

可以看到ansible_facts是一个字典。
使用的时候就是这样:

  tasks:
  - name: show ip
    debug: msg={{ansible_facts['pkg_mgr']}}

也可以使用ansible_local 变量获取本地用户自定义提供的fact变量,这部分暂时用的不多,不多介绍了。

4、magic变量

变量反映了ansible内部信息。在这个网址可以看到所有的特殊变量。
https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html#special-variables

最常用的魔术变量是hostvarsgroupsgroup_names,和inventory_hostname

hostvars 包含inventory中定义的所有主机,与主机对应的变量, 甚至是缓存下来主机对应的facts变量。

debug: msg={{hostvars}}

groups 包含inventory中定义的组, 与组中的主机列表。可以用于枚举组中的所有主机。如:

{% for host in groups['webserver'] %}
   # something that applies to all app servers.
{% endfor %}

group_names 列出当前主机所在的组。一个列表。如:

- hosts: 172.100.102.92
  tasks:
  - name: show ip
    debug: msg={{group_names}}
TASK [show ip] *************************************************************************************************************************************************
ok: [172.100.102.92] => {
    "msg": [
        "dbserver",
        "k8s_master",
        "webserver"
    ]
}

inventory_hostname 现在当前主机在inventory中的名称,在不采集facts变量,不能使用facts变量里的主机名时, 可以用这个代替。

- hosts: webserver
  tasks:
  - name: show ip
    debug: msg={{inventory_hostname}}
TASK [show ip] *************************************************************************************************************************************************
ok: [172.100.102.92] => {
    "msg": "172.100.102.92"
}
ok: [172.100.102.93] => {
    "msg": "172.100.102.93"
}

如果名称很长,也可以使用inventory_hostname_short 短版本的名称。如,变成了这样:

TASK [show ip] *************************************************************************************************************************************************
ok: [172.100.102.92] => {
    "msg": "172"
}
ok: [172.100.102.93] => {
    "msg": "172"
}

5、connect 变量

在之前的inventory里面已经介绍过了, 大致也就这个意思。
https://www.yxingxing.net/articles/2020/02/08/1581145585088.html#b3_solo_h2_23

6、变量优先级

https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

下面是从小到大的优先级。 大的优先级可以覆盖小的优先级。

要注意:
第一个不是命令行-e提供的变量, -e提供的是额外的变量,是最后一个。

  1. command line values (eg “-u user”)
  2. role defaults [1]
  3. inventory file or script group vars [2]
  4. inventory group_vars/all [3]
  5. playbook group_vars/all [3]
  6. inventory group_vars/* [3]
  7. playbook group_vars/* [3]
  8. inventory file or script host vars [2]
  9. inventory host_vars/* [3]
  10. playbook host_vars/* [3]
  11. host facts / cached set_facts [4]
  12. play vars
  13. play vars_prompt
  14. play vars_files
  15. role vars (defined in role/vars/main.yml)
  16. block vars (only for tasks in block)
  17. task vars (only for the task)
  18. include_vars
  19. set_facts / registered vars
  20. role (and include_role) params
  21. include params
  22. extra vars (always win precedence)

其他注意:
在任何部分中,重新定义的变量都将覆盖前一个。如果多个组具有相同的变量,则最后一个加载的覆盖前面的。如果您在play的vars:部分中定义两次变量,则最终结果是第二个变量。

inventory组级别的优先级:
https://www.yxingxing.net/articles/2020/02/08/1581145585088.html#b3_solo_h3_19