Ansible PlayBook的中清单变量优先级分析及清单变量如何分离总结

Posted 山河已无恙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ansible PlayBook的中清单变量优先级分析及清单变量如何分离总结相关的知识,希望对你有一定的参考价值。

写在前面


  • 嗯,学习Ansible高级特性,整理这部分笔记
  • 博文内容涉及
    • Ansible ploybook 中变量定义的基本原则
    • 不同位置定义变量的优先级 Demo
    • 如何实现变量和清单解耦
  • 食用方式:
    • 大量Demo,所以适合收藏温习查阅变量优先级
    • 需要有ansible基础
    • 了解角色剧本基本结构
    • 能够使用Ansible解决实际问题
  • 理解不足小伙伴帮忙指正

傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。--------王小波


管理清单变量

描述变量的基本原则

在Ansible中,利用变量,可以编写任务、角色和 playbook,使它们可重复使用并且灵活多变。变量可以指定不同系统之间的配置差异ansilbe可以在许多不同的位置设置变量:

  • 在角色的defaultsvars目录中
  • 主机清单文件中,作为主机变量组变量
  • Playbook或清单的 group_varshost_vars子目录下的变量文件中
  • Play角色任务

在项目定义和管理变量时,做好规划以遵循下列原则

  • 保持简单:尽管可以通过许多不同的⽅式定义 Ansible 变量,但尽量仅使用一两种不同方式并且仅在几个地方定义变量。

  • 不要重复:如果⼀组系统具有相同的配置,则将它们组织到⼀个组中,并在 group_vars 目录下的文件中为它们设置清单变量。

  • 在可读的小文件中组织变量:如果有一个包含许多主机组和变量的大型项目,请将变量拆分成多个文件。

变量合并和优先级

当使用多种方式定义相同变量时,Ansible 将使用优先级规则为变量选取值。以下讨论优先级从低到高

  • 配置文件(ansible.cfg)
  • 命令行选项
  • 角色defaults变量
  • host和group变量
  • Play变量
  • Extra变量(全局变量

下面就这几种变量一起简单梳理下:

配置文件

配置文件的变量拥有最低的优先级,通过在ansible.cfg 中提供到的一个KV的键值对,我们看一个Demo

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat ansible.cfg | grep remote_user
remote_user=root
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

这里的配置文件中的remote_user=root为连接受管机器的远程用户名,对应保存到ansible中的ansible_user变量中

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible vms82.liruilongs.github.io -m debug -a 'var=ansible_user' -i ./inventorys/hosts
vms82.liruilongs.github.io | SUCCESS => 
    "ansible_user": "root"

把配置文件中的变量删除,

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$sed -i '/remote_user=root/d' ansible.cfg

在次打印变量会提示变量没有定义

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible vms82.liruilongs.github.io -m debug -a 'var=ansible_user' -i ./inventorys/hosts
vms82.liruilongs.github.io | SUCCESS => 
    "ansible_user": "VARIABLE IS NOT DEFINED!"

添加之后也可以正常打印

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$sed '4a remote_user=root' ansible.cfg -i
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible vms82.liruilongs.github.io -m debug -a 'var=ansible_user' -i ./inventorys/hosts
vms82.liruilongs.github.io | SUCCESS => 
    "ansible_user": "root"

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

当然这里需要注意的是,当不指定主机清单的时候,默认情况下ansible会忽略带有后缀的文件

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-config  dump | grep -i inventory
DEFAULT_HOST_LIST(/root/ansible/ansible.cfg) = [u'/root/ansible/inventory']
DEFAULT_INVENTORY_PLUGIN_PATH(default) = [u'/root/.ansible/plugins/inventory', u'/usr/share/ansible/plugins/inventory']
INVENTORY_ANY_UNPARSED_IS_FAILED(default) = False
INVENTORY_CACHE_ENABLED(default) = False
INVENTORY_CACHE_PLUGIN(default) = None
INVENTORY_CACHE_PLUGIN_CONNECTION(default) = None
INVENTORY_CACHE_PLUGIN_PREFIX(default) = ansible_facts
INVENTORY_CACHE_TIMEOUT(default) = 3600
INVENTORY_ENABLED(default) = ['host_list', 'script', 'auto', 'yaml', 'ini', 'toml']
INVENTORY_EXPORT(default) = False
INVENTORY_IGNORE_EXTS(default) = (BLACKLIST_EXTS + ( '.orig', '.ini', '.cfg', '.retry'))
INVENTORY_IGNORE_PATTERNS(default) = []
INVENTORY_UNPARSED_IS_FAILED(default) = False
VARIABLE_PRECEDENCE(default) = ['all_inventory', 'groups_inventory', 'all_plugins_inventory', 'all_plugins_play', 'groups_plugins_inventory', 'groups_plugins_play']
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

命令行选项:

可在命令行中传递给ansible-playbook的选项(非 -e )具有最低优先级。这里讲的主要是通过其他参数来定义变量,还是用我们之前定义的ansible_user变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m debug -a "var=ansible_user"
vms82.liruilongs.github.io | SUCCESS => 
    "ansible_user": "root"

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m debug -a "var=ansible_user" -u liruilong
vms82.liruilongs.github.io | SUCCESS => 
    "ansible_user": "liruilong"

当然这里需要注意的是通过临时命令的方式执行 debug 模块.默认不会连接受管机,所以这里不会报错,我们的 sanheyiwuyang 用户是一个没有被受管机定义的用户。

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible all -m debug -a "var=ansible_user" -u sanheyiwuyang
vms82.liruilongs.github.io | SUCCESS => 
    "ansible_user": "sanheyiwuyang"

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

角色default值:

role_name/defaults/ 文件中由角色设置的默认值具有非常低的优先级。相对于角色中的vars目录下的变量,会覆盖defaults变量值。这里我们还是用remote_user这个变量

先来新建一个角色

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-galaxy init vars_demo --init-path=roles
- Role vars_demo was created successfully
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-galaxy list | grep var
- vars_demo, (unknown version)

编写角色中的默认变量,这里我们定义远程用户名是一个没有在受管机定义的sanheyiwuyang

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo -e "ansible_user: sanheyiwuyang" > ./roles/vars_demo/defaults/main.yml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat ./roles/vars_demo/defaults/main.yml
ansible_user: sanheyiwuyang
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

编写角色任务

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$vim ./roles/vars_demo/tasks/main.yml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat ./roles/vars_demo/tasks/main.yml
---
# tasks file for vars_demo
- name: default_vars demo
  debug:
    var: ansible_user
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

编写执行角色的剧本

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$vim  vars_demo.yaml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat vars_demo.yaml
---
- name: vars_demo roles demo
  hosts: all
  roles:
    - vars_demo
  tasks:
    - name: show vars
      debug:
        var: ansible_user
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

当前的ansible_user变量定义,我们可以看到,配置文件的优先级最低,其次是 命令行非(-e)的方式

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml  -u liruilong

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
fatal: [vms82.liruilongs.github.io]: UNREACHABLE! => "changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", "unreachable": true

PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0  

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

执行调用角色的剧本,报错了,通过 -u 的方式指定liruilong用户,但是角色中使用的并不是liruilong用户,而是没有被受管机定义的sanhewuyang用户,因为命名行非-e的变量优先级小于角色中/roles/var_demo/default/main.yaml定义的变量,所以liruilong用户被覆盖,所以会报错

修改 ./roles/vars_demo/defaults/main.yml中的ansible_user变量,我们也可以发现使用的是root用户,而不是命令行的liruilong

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: root" >  ./roles/vars_demo/defaults/main.yml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml  -u liruilong

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "root"


TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "root"


PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

主机变量和组变量:

关于主机变量和组变量这是相对应主机清单文件来讲的,主机清单的定义方式有很多种,我们可以直接通过inventory文件定义,也可以创建
inventory目录中的文件来定义,也可以在项目中指定目录下定义,场景比较多,我们分别看下

以下列表从最低到最高列出了这些变量的确切优先顺序:

  • 直接在清单文件中或通过动态清单脚本设置的al组变量。
  • 直接在清单文件中或通过动态清单脚本设置的其他组变量。
  • 在inventory/group_vars/all文件或子目录中设置的all组的变量。
  • 在项目的group_vars/all文件或子目录中设置的all组的变量。
  • 在inventory/group_vars子目录中设置的其他组变量。
  • 在项目的group_vars子目录中设置的其他组变量。
  • 直接在清单文件中或通过动态清单脚本设置的主机变量。
  • 在inventory/host vars子目录中设置的主机变量。
  • 在项目的host vars子目录中设置的主机变量。
  • 主机facts和缓存的facts。

我们分别来看下:

直接在清单文件中或通过动态清单脚本设置的all组变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$vim inventory/inventory
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat inventory/inventory
vms82.liruilongs.github.io
[all:vars]
ansible_user=liruilong

当前角色中的默认值为root

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat ./roles/vars_demo/defaults/main.yml
ansible_user: root
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

通过剧本的执行我们可以看到all中的组变量优先级要大于default目录下的变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "liruilong"


TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "liruilong"


PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

直接在清单文件中或通过动态清单脚本设置的其他组变量

在上面的基础上我们新建一个组变量[lb:vars]。定义ansible_user的值为root

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$vim inventory/inventory
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat inventory/inventory
[lb]
vms82.liruilongs.github.io
[lb:vars]
ansible_user=root
[all:vars]
ansible_user=liruilong

执行剧本发现,通过ansible_user的值为root,说明覆盖了all组中的定的变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$vim inventory/inventory
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "root"


TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "root"


PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

inventory/group_vars/all文件或子目录中设置的all组的变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$mkdir -p inventory/group_vars
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: liruilong" > inventory/group_vars/all

会发现inventory/group_vars/all覆盖了上面的inventory/inventory定义的变量,ansible_user的值为liruilong

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "liruilong"


TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "liruilong"


PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

项目group_vars/all文件或子目录中设置的all组的变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$mkdir group_vars
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: root" >  group_vars/all

我们会发现项目group_vars/all下面变量会覆盖主机清单文件inventory/group_vars/all下的变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "root"


TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "root"


PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

inventory/group_vars子目录中设置的其他组变量

这里需要说明的是,创建lb组变量inventory/group_vars/lb.yaml文件的前提是,需要在inventory/inventory文件中定义分组

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$cat ./inventory/inventory
[lb]
vms82.liruilongs.github.io

可以看到在inventory/group_vars/lb.yaml文件中定义覆盖了

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: liruilong" >  inventory/group_vars/lb.yaml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "liruilong"


TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "liruilong"


PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

在项目的group_vars子目录中设置的其他组变量

可以看到项目的./group_vars/lb.yaml的变量优先级要高于inventory/group_vars/lb.yaml下的

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: root" > ./group_vars/lb.yaml
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "root"


TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "root"


PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

前面我们分析的都是组变量,下面下面我们看看主机变量

直接在清单文件中或通过动态清单脚本设置的主机变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$sed  "s/vms82.liruilongs.github.io/& ansible_user=liruilong/" ./inventory/inventory
[lb]
vms82.liruilongs.github.io ansible_user=liruilong
[lb:vars]
ansible_user=root
[all:vars]
ansible_user=liruilong
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$sed  "s/vms82.liruilongs.github.io/& ansible_user=liruilong/" ./inventory/inventory -i

设置主机变量为ansible_user=liruilong优先级大于上面的组变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "liruilong"


TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "liruilong"


PLAY RECAP *********************************************************************************************************
vms82.liruilongs.github.io : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

inventory/host_vars子目录中设置的主机变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$mkdir inventory/host_vars
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$echo "ansible_user: root" > inventory/host_vars/vms82.liruilongs.github.io.yaml

inventory/host_vars子目录中设置的主机变量优先级大于./inventory/inventory 中的主机变量

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$ansible-playbook vars_demo.yaml

PLAY [vars_demo roles demo] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************
ok: [vms82.liruilongs.github.io]

TASK [vars_demo : default_vars demo] *******************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": "root"


TASK [show vars] ***************************************************************************************************
ok: [vms82.liruilongs.github.io] => 
    "ansible_user": ansible 流程控制

ansible 流程控制

Ansible之主机清单及playbook剧本

Ansible之主机清单及playbook剧本

Ansible-playbook 针对不在清单文件中并包含组变量的任意主机运行

ansible-playbook 额外变量的顺序和优先级