在上一篇文章中,我们讨论了什么 Ansible 剧本 是以及如何通过剧本创建和运行任务。 在本文中,我们将更进一步,学习如何在 Ansible playbooks 中使用变量。
内容
什么是 Ansible 变量?
变量 是所有编程语言中的基本概念,用于存储数据,然后在代码中使用。 同样,ansible 有存储一些值的变量,它们稍后会在 playbook 中用于不同的处理。
Ansible 支持在多个位置声明变量,例如 playbook、host_vars 和 group_vars 文件以及命令行参数。
在接下来的部分中,我们将讨论如何在不同的地方定义变量并了解变量优先级。
变量 – 键、值映射
变量可以在播放级别和任务级别使用“vars
” 关键字。关键字 vars 之后,给出了带有 key 和 value 的变量。这些变量可以被 play 中的所有任务访问。
我创建了一项任务,该任务使用调试模块通过变量值打印消息。 变量应该用双花括号括起来 {{ 多变的 }}.
如何在 Ansible Playbook 中使用调试模块
- name: Print vars hosts: m1 gather_facts: false vars: os_name: "PoP!_OS Desktop" version: "21.10" tasks: - name: Task1 - Substitute variables debug: msg: "My current desktop OS is {{ os_name }} - {{ version }}" Key-value variable Mapping
现在要运行 playbook,请在终端中运行以下命令。
$ ansible-playbook playbook_name.yml
从下图中,您可以看到我的两个变量都被替换为它们的值 味精 打印到标准输出。
变量 – 元素列表
您可以在变量中创建元素列表。 如果您看一下下面的定义,我已经通过两种方式创建了一个列表变量。
- 定义项目/元素列表的标准 YAML 方式。 在这里,我将变量名称指定为 “top_linux_desktops”.
- 用于创建项目/元素列表的 Python 语法。 在这里,我将变量名称指定为 “top_desktops”.
vars: top_linux_desktops: - MXlinux - pop-os - Linux Mint - Manjaro - Fedora top_desktops: [MXLinux, pop-os, Linux Mint, Manjaro, Fedora]
您可以使用变量名称打印列表中的所有元素。 我创建了两个任务。 第一个任务将打印来自 top_linux_desktops 变量和第二个任务将打印元素 top_desktops 多变的。
tasks: - name: Task1 - List of elements debug: msg: "My fav linux desktops are {{ top_linux_desktops }}" - name: Task2 - List of elements using Python syntax debug: msg: "My fav linux desktops are {{ top_desktops }}"
在列表中,您还可以使用其索引位置访问单个元素,类似于从 python 列表中访问元素的方式。 有两种方法可以做到这一点。
- 使用点表示法(variable.index)
- Python 表示法(变量[index])
我创建了两个任务。 第一个任务使用点表示法,第二个任务使用 python 表示法从第一个和第二个位置打印元素。
tasks: - name: Task3 - Accessing List element using dot notation debug: msg: "My fav linux desktops are {{ top_linux_desktops.1 }} and {{ top_desktops[2] }}" - name: Task4 - Accessing List element using python notation(list[i]) debug: msg: "My fav linux desktops are {{ top_linux_desktops[1] }} and {{ top_desktops[2] }}"
变量 – 字典
您可以创建一个字典对象并将其分配给变量。 这类似于 python 字典。 可以通过两种方式创建字典。
- 定义字典的标准 YAML 语法
- Python 字典符号
如果您可以看到下面的剧本片段,我已经创建了两个字典变量。 第一个变量 “发布信息” 遵循 YAML 语法方法和第二个变量 “new_release_info” 遵循python字典语法。
vars: release_info: name: PoP!_OS Desktop version: 22.04 release_month: April, 2022 new_release_info: { name: PoP!_OS Desktop, version: 22.04, release_month: "April, 2022"}
您可以使用其键从变量或特定字典元素中获取所有值。 与列表类似,字典也遵循点和 python 表示法来打印键的值。
我创建了两个任务,第一个任务将使用 点符号 从字典中获取元素,第二个任务将使用 蟒蛇符号 抓住元素。
tasks: - name: Task1 - Accessing dictionary values using its key with dot notation(dict.key) debug: msg: "{{ release_info.name }} version {{ release_info.version }} is released on {{ release_info.release_month }}" - name: Task2 - Accessing dictionary values using its key with python notation(dict['key']) debug: msg: "{{ new_release_info['name'] }} version {{ new_release_info['version'] }} is released on {{ new_release_info['release_month'] }}"
播放与任务级别优先级
可以在任务级别和游戏级别定义变量,但在任务级别定义的变量优先于在游戏级别定义的变量。
在下面的示例中,我在播放级别和任务级别创建了具有相同变量名称的变量。 现在,当我运行剧本时,它将使用任务变量名称。
vars: os_name: "PoP!_OS Desktop" version: "21.10" tasks: - name: Task1 - Substitute variables vars: os_name: "Linux Mint" version: "20.03" debug: msg: "My current desktop OS is {{ os_name }} - {{ version }}"
剧本与命令行参数优先级
您可以通过使用覆盖剧本中传递的变量 -e
旗帜。 通过的变量具有更高的优先级 -e
旗帜。
我正在运行上一节中的相同剧本,再次使用 -e
旗帜。
$ ansible-playbook 4_var_precedence.yml -e "os_name=fedora" -e "version=35"
您可以将变量传递给 -e
标志在 Json
, YAML
或者 ini
格式。
# INI FORMAT $ ansible-playbook 4_var_precedence.yml -e "os_name=fedora" -e "version=35" # JSON FORMAT $ ansible-playbook 4_var_precedence.yml -e '{"os_name": "fedora"}' -e '{"version": 35}' # YAML FORMAT $ ansible-playbook 4_var_precedence.yml -e "{os_name: fedora}" -e "{version: 35}"
您还可以为变量创建一个单独的文件并将其传递 -e
旗帜。 语法如下。 在这里,我创建了一个名为 vars.yml
并将我所有的变量分组。 现在,当文件传递给 -e
标记所有变量都导入到剧本中。
$ ansible-playbook 4_var_precedence.yml -e @vars.yml
变量文件
您可以创建一个文件并在文件中声明所有变量,而不是在 playbook 中定义变量。 我创建了一个名为 vars.yml
并将我们在前几节中讨论过的所有变量分组到这个文件中。
而不是使用关键字 变量,你应该使用 vars_files 在剧本中并传递文件名。 现在,当您运行 playbook 时,ansible 将从文件中选择变量。 该文件可以位于任何路径中。
主机和组变量
您可以在清单文件中定义主机级别和组级别变量。 您可以参考以下文章,其中我们简要讨论了如何创建主机级和组级变量。
Ansible 清单和配置文件
作为最佳实践,您不应该在清单文件中定义变量,而是可以为 host_vars
和 group_vars
ansible 会自动选择目录中的文件。 创建一个名为 host_vars
.
$ mkdir host_vars
里面 host_vars
目录,您可以定义主机级变量,即您可以创建 INI、YAML 或 JSON 格式文件并存储特定主机的变量。 如果您查看下面的清单文件,我有两个名为“ubuntu”和“rocky”的主机,并为每个主机创建了变量文件。
小心:文件的名称应与清单文件中的主机/别名名称相同。
# Inventory file [m1] ubuntu ansible_host=ubuntu.anslab.com [m2] rocky ansible_host=rocky.anslab.com
$ mkdir host_vars/ubuntu.yml $ echo "message: This variable is read from host_vars/ubuntu.yml file" > host_vars/ubuntu.yml" $ mkdir host_vars/rocky.yml $ echo "message: This variable is read from host_vars/rocky.yml file" > host_vars/rocky.yml
我添加了一个名为 “message
“ 在两个变量文件中。 现在,如果我运行我的剧本,将从这两个文件中获取变量。
同样,您也可以为组创建变量文件。 创建目录 “group_vars
“ 并根据清单文件创建一个具有组名的文件。
[m1] ubuntu ansible_host=ubuntu.anslab.com [m2] rocky ansible_host=rocky.anslab.com [servers:children] m1 m2
我创建了一个名为的子组 “服务器”,所以我将文件名创建为 servers.yml
.
$ mkdir group_vars $ mkdir group_vars/servers.yml $ echo "message: This variable is read from group_vars/servers.yml file" > group_vars/servers.yml
现在,如果我运行剧本,它将读取 servers.yml
从 group_vars.
小心: 如果两个都有 host_vars
和 group_vars
ansible 将首先搜索 host_vars
定义,如果找不到,它将转到 group_vars
.
魔术变量
Ansible 提供了一些内部变量,这些变量的状态在您运行 playbook 时定义。 我们可以通过剧本使用这些变量。 要获取可用特殊变量的列表,您可以参考以下链接。
Ansible 特殊变量
例如,有一个变量叫做 inventory_dir
它存储 playbook 使用的清单文件的绝对路径。
- name: Magic Variables - Get inventory directory path debug: msg: "{{ inventory_dir }}"
一个重要的魔法变量是 hostvars
. 该变量将以 json 格式打印一些魔术变量的集合。
- name: Magic Variables - hostvars debug: msg: "{{ hostvars }}"
输出包含 str、list 和字典格式的信息。 假设我想检查我的 ubuntu 主机在哪个组中,那么我可以通过以下方式获取它。 我在这里使用 python 语法符号。
- name: Magic Variables debug: msg: "{{ hostvars['ubuntu']['group_names'] }}"
并非所有魔术变量在日常操作中都有用。 查看所有魔术变量,看看哪个适合您的用例。
变数的事实
当您运行 playbook 时,ansible 将使用 setup 模块并从目标主机收集事实并将输出保存在内存中,以便可以在 playbook 中使用。 事实也称为剧本变量。
首先,了解事实输出,以便获取特定属性。 运行以下命令,该命令将收集事实输出并将其存储在文件中。
$ ansible all -m setup --tree /tmp/facts_result
将为每个主机创建单独的输出文件。 如果你看一下输出,它只是 JSON 格式的输出。
事实输出中的属性将采用 List、Dictionary 和 AnsibleUnsafeText 格式。 下面是几个不同类型的例子。
- name: Facts output - AnsibleUnsafeText debug: msg: "{{ discovered_interpreter_python }}" - name: Facts output - List debug: msg: "{{ ansible_all_ipv4_addresses }}" - name: Facts output - Dictionary debug: msg: "{{ ansible_python }}"
事实收集了大量信息,因此请花点时间查看输出结果,看看什么符合您的要求。
结论
在这篇文章中,我们讨论了什么是ansible变量以及如何在不同的地方声明变量。 声明变量时,变量优先级非常重要,本文将对此进行介绍。 我们还讨论了魔法变量及其用例。 最后,我们介绍了什么是事实以及如何将事实输出用作变量。
AnsibleAnsible 命令Ansible PlaybooksAnsible 系列Ansible 教程Ansible 变量DevOpsLinuxLinux 管理OpensourceSysadmin