6

Ansible最佳实践之如何管理playbook的中清单变量(多种方式的清单变量定义)

 2 years ago
source link: https://liruilongs.github.io/2022/05/13/rhca/DO447/Ansible%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5%E4%B9%8B%E5%A6%82%E4%BD%95%E7%AE%A1%E7%90%86playbook%E7%9A%84%E4%B8%AD%E6%B8%85%E5%8D%95%E5%8F%98%E9%87%8F/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Ansible最佳实践之如何管理playbook的中清单变量(多种方式的清单变量定义)

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


  • 理解不足小伙伴帮忙指正

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


管理清单变量

描述变量的基本原则

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

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

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

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

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

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

变量合并和优先级

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

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

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

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

┌──[[email protected]]-[~/ansible]
└─$cat ansible.cfg | grep remote_user
remote_user=root
┌──[[email protected]]-[~/ansible]
└─$

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

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

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

┌──[[email protected]]-[~/ansible]
└─$sed -i '/remote_user=root/d' ansible.cfg

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

┌──[[email protected]]-[~/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!"
}

添加之后也可以正常打印

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

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

┌──[[email protected]]-[~/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']
┌──[[email protected]]-[~/ansible]
└─$

命令行选项:

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

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

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

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

角色default值:

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

先来新建一个角色

┌──[[email protected]]-[~/ansible]
└─$ansible-galaxy init vars_demo --init-path=roles
- Role vars_demo was created successfully
┌──[[email protected]]-[~/ansible]
└─$ansible-galaxy list | grep var
- vars_demo, (unknown version)

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

┌──[[email protected]]-[~/ansible]
└─$echo -e "ansible_user: sanheyiwuyang" > ./roles/vars_demo/defaults/main.yml
┌──[[email protected]]-[~/ansible]
└─$cat ./roles/vars_demo/defaults/main.yml
ansible_user: sanheyiwuyang
┌──[[email protected]]-[~/ansible]
└─$

编写角色任务

┌──[[email protected]]-[~/ansible]
└─$vim ./roles/vars_demo/tasks/main.yml
┌──[[email protected]]-[~/ansible]
└─$cat ./roles/vars_demo/tasks/main.yml
---
# tasks file for vars_demo
- name: default_vars demo
debug:
var: ansible_user
┌──[[email protected]]-[~/ansible]
└─$

编写执行角色的剧本

┌──[[email protected]]-[~/ansible]
└─$vim vars_demo.yaml
┌──[[email protected]]-[~/ansible]
└─$cat vars_demo.yaml
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
┌──[[email protected]]-[~/ansible]
└─$

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

┌──[[email protected]]-[~/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

┌──[[email protected]]-[~/ansible]
└─$

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

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

┌──[[email protected]]-[~/ansible]
└─$echo "ansible_user: root" > ./roles/vars_demo/defaults/main.yml
┌──[[email protected]]-[~/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


┌──[[email protected]]-[~/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组变量

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

当前角色中的默认值为root

┌──[[email protected]]-[~/ansible]
└─$cat ./roles/vars_demo/defaults/main.yml
ansible_user: root
┌──[[email protected]]-[~/ansible]
└─$

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

┌──[[email protected]]-[~/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

┌──[[email protected]]-[~/ansible]
└─$

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

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

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

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

┌──[[email protected]]-[~/ansible]
└─$vim inventory/inventory
┌──[[email protected]]-[~/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


┌──[[email protected]]-[~/ansible]
└─$

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

┌──[[email protected]]-[~/ansible]
└─$mkdir -p inventory/group_vars
┌──[[email protected]]-[~/ansible]
└─$echo "ansible_user: liruilong" > inventory/group_vars/all

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

┌──[[email protected]]-[~/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

┌──[[email protected]]-[~/ansible]
└─$

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

┌──[[email protected]]-[~/ansible]
└─$mkdir group_vars
┌──[[email protected]]-[~/ansible]
└─$echo "ansible_user: root" > group_vars/all

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

┌──[[email protected]]-[~/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

┌──[[email protected]]-[~/ansible]
└─$

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

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

┌──[[email protected]]-[~/ansible]
└─$cat ./inventory/inventory
[lb]
vms82.liruilongs.github.io

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

┌──[[email protected]]-[~/ansible]
└─$echo "ansible_user: liruilong" > inventory/group_vars/lb.yaml
┌──[[email protected]]-[~/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

┌──[[email protected]]-[~/ansible]
└─$

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

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

┌──[[email protected]]-[~/ansible]
└─$echo "ansible_user: root" > ./group_vars/lb.yaml
┌──[[email protected]]-[~/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

┌──[[email protected]]-[~/ansible]
└─$

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

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

┌──[[email protected]]-[~/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
┌──[[email protected]]-[~/ansible]
└─$sed "s/vms82.liruilongs.github.io/& ansible_user=liruilong/" ./inventory/inventory -i

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

┌──[[email protected]]-[~/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

┌──[[email protected]]-[~/ansible]
└─$

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

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

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

┌──[[email protected]]-[~/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


┌──[[email protected]]-[~/ansible]
└─$

在项目的host_vars子目录中设置的主机变量

┌──[[email protected]]-[~/ansible]
└─$mkdir host_vars
┌──[[email protected]]-[~/ansible]
└─$echo "ansible_user: liruilong" > host_vars/vms82.liruilongs.github.io.yaml

项目的host_vars子目录中设置的主机变量优先级大于清单host_vars子目录的变量

┌──[[email protected]]-[~/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

┌──[[email protected]]-[~/ansible]
└─$

主机facts和缓存的facts

主机facts,可以看到set_fact设置的变量具有最高的优先级

┌──[[email protected]]-[~/ansible]
└─$cat vars_demo.yaml
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
- name: set fact ansible_user
set_fact:
ansible_user: root
- name: show vars
debug:
var: ansible_user
┌──[[email protected]]-[~/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"
}

TASK [set fact ansible_user] ***************************************************************************************
ok: [vms82.liruilongs.github.io]

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

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

对于其他的一些通过gather_facts收集的变量,相对于剧本之外具有很高的优先级

相对于清单inventory的group_varshost_vars子目录与相对于 playbook 项目的子目录之间的优先级比较好区分,相同类型,项目下总是比清单里的优先级要高,。

如果在 playbook 的相同目录中有group_vars 和 host_vars子目录,则这些组和主机变量将被自动包含在内。

简单总结一下ansible清单文件变量优先级。在facts优先级最高,其次是主机变量,包含清单变量文件的host_vars目录和inventory清单变量目录和inventory文件,项目下要高于清单目录下,清单目录要高于清单文件,之后是组变量,group_vars目录下的文件,inventory清单变量目录,inventory文件,整体上,inventory文件优先级小于目录下的优先级,同样是inventory目录下要小于项目目录下。

Play 变量:

准备工作,我们还用之前的角色和剧本

┌──[[email protected]]-[~/ansible]
└─$cat vars_demo.yaml
---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
- name: show vars
debug:
var: ansible_user
┌──[[email protected]]-[~/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"
}

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

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

Play 的优先级高于主机或组变量、角色默认值,除 -e 以外的命令行选项。以下列表从最低到最高列出了这些变量的优先顺序:

  • 由 play 的 vars 部分进行设置。
  • 通过 play 中的 vars_prompt 部分提示用户来进行设置。
  • 通过 play 的 vars_files 部分从外部文件列表进行设置。
  • 由角色的 rolename/vars/ 子目录中的文件进行设置。
  • 通过这个块的 vars 部分为当前的 block 进行设置。
  • 通过这个任务的 vars 部分为当前的任务进行设置。
  • 通过 include_vars 模块动态加载。
  • 通过使用 set_fact 模块或通过使用 register 记录任务在主机上执行的结果,为特定的主机进行设置。
  • 在 play 的 role 部分加载时或通过使用 include_role 模块 playbook 中为角色设置的参数。
  • 由 vars 部分为通过 include_tasks 模块包含的任务进行设置。

我们分别梳理下:

由 play 的 vars 部分进行设置。

---
- name: vars_demo roles demo
hosts: all
vars:
ansible_user: root
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
- name: show vars
debug:
var: ansible_user

play 的 vars 部分进行设置的变量要高于前面设置的变量

┌──[[email protected]]-[~/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"
}

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

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


通过 play 中的vars_prompt部分提示用户来进行设置

---
- name: vars_demo roles demo
hosts: all
vars:
ansible_user: root
vars_prompt:
- name: ansible_user
prompt: "input ansible_user name"
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
- name: show vars
debug:
var: ansible_user

这里默认情况下输入数据是不显示,可以添加参数private: no来显示输入变量值

┌──[[email protected]]-[~/ansible]
└─$ansible-playbook vars_demo.yaml
input ansible_user name:

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"
}

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

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

通过 play 的 vars_files 部分从外部文件列表进行设置

---
- name: vars_demo roles demo
hosts: all
vars:
ansible_user: root
vars_files:
- vars_files
vars_prompt:
- name: ansible_user
prompt: "input ansible_user name"
private: no
roles:
- vars_demo
tasks:
- name: show vars
debug:
var: ansible_user
- name: show vars
debug:
var: ansible_user

定义引入的变量文件

┌──[[email protected]]-[~/ansible]
└─$echo "ansible_user: liruilong" > vars_files

执行剧本,可以看到我们输入的是root但是打印的是liruilong,即vars_files的优先级高于vars_prompt

┌──[[email protected]]-[~/ansible]
└─$ansible-playbook vars_demo.yaml
input ansible_user name: root

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"
}

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

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

由角色的rolename/vars/子目录中的文件进行设置

当前剧本执行返回的变量值为 liruilong,我们定义roles/vars_demo/vars/main.yml目录的ansible_user变量为root.执行剧本

┌──[[email protected]]-[~/ansible]
└─$echo "ansible_user: root" > roles/vars_demo/vars/main.yml
┌──[[email protected]]-[~/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"
}

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

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

通过这个任务块的 vars 部分为当前的 block 进行设置。

┌──[[email protected]]-[~/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"
}

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

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

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

┌──[[email protected]]-[~/ansible]
└─$

我们可以看到,在block所在的块的内部,通过vars定义的变量具有最高的优先级,打印的ansible_usern的变量的为liruilong,而在剧本的其他位置的打印的变量为root

通过这个任务的 vars 部分为当前的任务进行设置

即不是写在block块内的vars变量,而是写在对应 任务中的vars的变量中

---
- name: vars_demo roles demo
hosts: all
roles:
- vars_demo
tasks:
- block:
- name: show vars in block
debug:
var: ansible_user
vars:
ansible_user: root
- name: show vars in block no vars
debug:
var: ansible_user
vars:
ansible_user: liruilong

执行我们可以看到,当前角色和block的任务使用的是root用户,而定义了任务内部vars的剧本使用的是liruilong,所以在block内部,任务内部的变量优先级要高于任务外部的变量。

┌──[[email protected]]-[~/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 in block] **********************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "root"
}

TASK [show vars in block no vars] *************************************************************************************
ok: [vms82.liruilongs.github.io] => {
"ansible_user": "liruilong"
}

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

通过 include_vars 模块动态加载

通过使用 set_fact 模块或通过使用 register 记录任务在主机上执行的结果,为特定的主机进行设置。

在 play 的 role 部分加载时或通过使用 include_role 模块 playbook 中为角色设置的参数。

由 vars 部分为通过 include_tasks 模块包含的任务进行设置

使用vars_prompt可能不是最佳实践,它需要在执行 ansible-playbook 时进行交互,且不兼容红帽 Tower。

Extra变量(-e 命令或者–extra-vars)

使用 ansible-playbook 命令的 -e 选项设置的额外变量始终具有最高的优先级。
也可以以JSON形式定义

┌──[[email protected]]-[~/ansible]
└─$ansible vms82.liruilongs.github.io -m debug -a 'var=ansible_user'
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "root"
}
┌──[[email protected]]-[~/ansible]
└─$ansible all -m debug -a "var=ansible_user" --extra-vars "{'ansible_user':'liruilong'}"
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "liruilong"
}
┌──[[email protected]]-[~/ansible]
└─$ansible all -m debug -a "var=ansible_user"
vms82.liruilongs.github.io | SUCCESS => {
"ansible_user": "root"
}
┌──[[email protected]]-[~/ansible]
└─$

可以发现当使用 --extra-vars 在命令行定义变量的时候,会覆盖ansible.cfg 的变量配置,使用了liruilong这个受管机用户

将变量与清单分离

随着环境在规模和种类上扩展,清单文件会变得很大且难以阅读。

更好的做法是将变量定义从清单文件转移到单独的变量文件中,每个主机组分别对应一个,每个变量文件都已主
机组命令,且包含该主机组的变量定义:

对于多样化的大型化环境而言,更好的方法是在 group_vars 目录下为每个主机组创建子目录:

group_vars 目录下各目录的文件中存在的所有变量都与其余变量合并在⼀起。通过将变量分隔到按功能分组的文
件中,可以使整个 playbook 项目更易于理解和维护。

特殊清单变量

可以使用多个变量来更改Ansible连接到清单中列出的主机的方式。其中⼀些对于主机特定变量最为有用,但另
⼀些可能与组中或清单中的所有主机相关。

ansible_connection:用于访问受管主机的连接插件。默认情况下,ssh 用于除 localhost 外的所有主机,后者
使用 local。

  • ansible_host:实际 IP 地址或完全限定域名,在连接受管主机时使用,而不使来用自清单文件(inventory_hostname) 中的名称。默认情况下,此变量具有与清单主机名相同的值。
  • ansible_port:Ansible 用于连接受管主机的端口。对于(默认)SSH 连接插件,其值默认为 22。
  • ansible_user:Ansible 以此用户身份连接受管主机。作为 Ansible 的默认行为,它会使用与控制节点上运行 Ansible Playbook 的用户相同的用户名来连接受管主机。
  • ansible_become_user:Ansible 连接到受管主机后,它将使用 ansible_become_method(默认情况下为sudo)切换到此用户。
  • ansible_python_interpreter:Ansible 应在受管主机上使用的 Python 可执行文件的路径。

人类可读的清单主机名

当 Ansible 在远程主机上执行任务时,输出中会包含清单主机名。由于可以使用上述特殊清单变量来指定替代的
连接属性,因此可以为清单主机名分配任意名称。使用有意义的名称分配清单主机时,可以更好地理解 playbook
输出并诊断 playbook 错误。
请考虑使用以下 YAML 清单文件的 Playbook:

使用变量识别当前主机

  • inventory_hostname:当前正在处理的受管主机的名称,从清单中获取。
  • ansible_host:用于连接受管主机的实际 IP 地址或主机名。
  • ansible_facts[‘hostname’]:作为事实,从受管主机手机的完全限定域名。
  • ansible_play_hosts:当前 Play 期间尚未失败的所有主机的列表。

一个完整的Demo

┌──[[email protected]]-[/home/student/git-repos]
└─$ls
inventory-variables
┌──[[email protected]]-[/home/student/git-repos]
└─$cd inventory-variables
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$mkdir group_vars
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$mkdir group_vars/lb_servers
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$ mkdir group_vars/web_servers
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$touch group_vars/lb_servers/firewall.yml
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$touch group_vars/lb_server/haproxy.yml
touch: cannot touch 'group_vars/lb_server/haproxy.yml': No such file or directory
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$touch group_vars/lb_servers/haproxy.yml
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$ls

deploy_haproxy

┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$cat deploy_haproxy.yml
- name: Ensure HAProxy is deployed
hosts: lb_servers
force_handlers: True

roles:
# The "haproxy" role has a dependency on the "firewall" role.
# The "firewall" role requires a "firewall_rules" variable be defined.
- role: haproxy
firewall_rules:
# Allow 80/tcp connections
- port: 80/tcp

haproxy_appservers:
- name: serverb.lab.example.com
ip: 172.25.250.11
backend_port: 80
- name: serverc.lab.example.com
ip: 172.25.250.12
backend_port: 80


┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$tee group_vars/lb_servers/firewall.yml <<- EOF
> firewall_rules:
> # Allow 80/tcp connections
> - port: 80/tcp
> EOF
firewall_rules:
# Allow 80/tcp connections
- port: 80/tcp
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$cat deploy_haproxy.yml
- name: Ensure HAProxy is deployed
hosts: lb_servers
force_handlers: True

roles:
# The "haproxy" role has a dependency on the "firewall" role.
# The "firewall" role requires a "firewall_rules" variable be defined.
- role: haproxy
firewall_rules:
# Allow 80/tcp connections
- port: 80/tcp

haproxy_appservers:
- name: serverb.lab.example.com
ip: 172.25.250.11
backend_port: 80
- name: serverc.lab.example.com
ip: 172.25.250.12
backend_port: 80


┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$tee group_vars/lb_servers/haproxy.yml <<- EOF
> haproxy_appservers:
> - name: serverb.lab.example.com
> ip: 172.25.250.11
> backend_port: 80
> - name: serverc.lab.example.com
> ip: 172.25.250.12
> backend_port: 80
> EOF
haproxy_appservers:
- name: serverb.lab.example.com
ip: 172.25.250.11
backend_port: 80
- name: serverc.lab.example.com
ip: 172.25.250.12
backend_port: 80
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$cat deploy_haproxy.yml
- name: Ensure HAProxy is deployed
hosts: lb_servers
force_handlers: True

roles:
# The "haproxy" role has a dependency on the "firewall" role.
# The "firewall" role requires a "firewall_rules" variable be defined.
- role: haproxy

deploy_apache

┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$ cat deploy_apache.yml
- name: Ensure Apache is deployed
hosts: web_servers
force_handlers: True

roles:
# The "apache" role has a dependency on the "firewall" role.
# The "firewall" role requires a "firewall_rules" variable be defined.
- role: apache
firewall_rules:
# Allow http requests from the load_balancer.
- zone: internal
service: http
source: "172.25.250.10"
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$tee group_vars/web_servers/firewall.yml <<- EOF
> firewall_rules:
> # Allow http requests from the load_balancer.
> - zone: internal
> service: http
> source: "172.25.250.10"
> EOF
firewall_rules:
# Allow http requests from the load_balancer.
- zone: internal
service: http
source: "172.25.250.10"
┌──[[email protected]]-[/home/student/git-repos/inventory-variables]
└─$
- name: Ensure Apache is deployed
hosts: web_servers
force_handlers: True

roles:
# The "apache" role has a dependency on the "firewall" role.
# The "firewall" role requires a "firewall_rules" variable be defined.
- role: apache
┌──[[email protected]]-[/home/student/git-repos/inventory-variables/group_vars]
└─$tree
.
├── lb_servers
│   ├── firewall.yml
│   └── haproxy.yml
└── web_servers
└── firewall.yml

2 directories, 3 files

该 playbook 将清单主机 load_balancer 作为负载平衡器来部署,并将组 web_servers
中的主机作为后端 Web 服务器来部署。
编辑 inventory.yml 静态清单⽂件,以便 playbook 中引⽤ load_balancer 主机时使
Ansible 连接到 servera.lab.example.com。 清单主机 serverb.lab.example.com
和 serverc.lab.example.com 应当位于组 web_servers 中。

lb_servers:
hosts:
load_balancer:
servera.lab.example.com:

web_servers:
hosts:
server[b:c].lab.example.com:

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK