介绍
在本实验中,你将学习如何在 Ansible 中处理多个清单(inventory)。在复杂的环境中,管理多个清单是一种常见场景,尤其是在涉及不同主机组或独立环境的情况下。你将学习如何定义和组织多个清单,访问来自不同清单的主机,并在多个清单之间执行操作。
创建清单目录和文件
让我们从创建一个目录来存储清单文件开始,然后为开发环境和生产环境创建两个独立的清单文件。
首先,在 /home/labex/project 路径下创建一个名为 inventory 的新目录:
mkdir -p /home/labex/project/inventory
此命令将创建一个名为 inventory 的新目录。-p 选项确保如果父目录不存在,则会自动创建。
接下来,在 inventory 目录中创建两个清单文件:dev_inventory.ini 和 prod_inventory.ini:
touch /home/labex/project/inventory/dev_inventory.ini
touch /home/labex/project/inventory/prod_inventory.ini
touch 命令用于创建空文件(如果文件不存在),或者更新文件的修改时间(如果文件已存在)。
接下来,我们将向这些清单文件中添加内容。使用文本编辑器(例如 nano 或你习惯的其他编辑器)打开 dev_inventory.ini:
nano /home/labex/project/inventory/dev_inventory.ini
添加以下内容:
[dev]
localhost ansible_connection=local
保存文件并退出编辑器(在 nano 中,可以按 Ctrl+X,然后按 Y,最后按 Enter)。
现在,打开 prod_inventory.ini:
nano /home/labex/project/inventory/prod_inventory.ini
添加以下内容:
[prod]
localhost ansible_connection=local
保存并退出编辑器。
在这些清单文件中:
[dev]和[prod]是组名。它们帮助将主机组织到逻辑组中。localhost是主机名。我们使用 localhost 来模拟同一台机器上的不同环境。ansible_connection=local告诉 Ansible 在本地运行命令,而不是尝试通过 SSH 连接到机器。这对于在安装 Ansible 的同一台机器上运行 Ansible 非常有用。
在实际场景中,你通常会为开发和生产服务器使用不同的 IP 地址或主机名,而不是为两者都使用 localhost。
创建适用于多个清单的 Playbook
在这一步中,我们将创建一个可以同时适用于开发和生产清单的 playbook。在 Ansible 中,playbook 是一个 YAML 文件,用于定义在主机上执行的一组任务。
首先,在 /home/labex/project 目录下创建一个名为 multi_env_playbook.yaml 的新文件:
touch /home/labex/project/multi_env_playbook.yaml
现在,使用文本编辑器打开 multi_env_playbook.yaml 文件。我们将使用 nano,这是一个简单的命令行文本编辑器:
nano /home/labex/project/multi_env_playbook.yaml
将以下内容复制并粘贴到文件中:
---
- name: Demonstrate multi-environment playbook
hosts: all
gather_facts: no
tasks:
- name: Print environment type
debug:
msg: "This host belongs to the {{ 'production' if 'prod' in group_names else 'development' }} environment"
- name: Show hostname
command: hostname
register: hostname_output
- name: Display hostname
debug:
msg: "The hostname is: {{ hostname_output.stdout }}"
粘贴完成后,按 Ctrl + X,然后按 Y,最后按 Enter 保存并退出 nano。
让我们分解这个 playbook,以理解每个部分:
- 文件顶部的
---表示 YAML 文档的开始。 name: Demonstrate multi-environment playbook是这个 play 的描述性名称。hosts: all表示这个 playbook 将在清单中的所有主机上运行。gather_facts: no跳过事实收集阶段以加快执行速度。事实收集是 Ansible 收集目标主机信息的过程。tasks:开始列出要执行的任务。- 第一个任务使用
debug模块打印一条消息。它使用条件语句来确定主机是属于生产环境还是开发环境:group_names是一个特殊变量,包含当前主机所属的所有组的列表。- 如果
group_names列表中包含 'prod',则打印 "production",否则打印 "development"。
- 第二个任务运行
hostname命令,并将其输出存储在一个名为hostname_output的变量中。 - 第三个任务使用
debug模块显示主机名。它通过hostname_output.stdout访问存储的输出。
使用开发清单运行 Playbook
现在我们已经设置好了 playbook 和清单,接下来让我们使用开发清单运行 playbook。
在终端中执行以下命令:
ansible-playbook -i /home/labex/project/inventory/dev_inventory.ini /home/labex/project/multi_env_playbook.yaml
让我们分解这个命令:
ansible-playbook是运行 Ansible playbook 的命令。-i /home/labex/project/inventory/dev_inventory.ini指定要使用的清单文件。-i选项代表 "inventory"(清单)。/home/labex/project/multi_env_playbook.yaml是我们的 playbook 文件的路径。
此命令告诉 Ansible 使用 dev_inventory.ini 文件并运行 multi_env_playbook.yaml playbook。
你应该会看到类似以下的输出:
PLAY [Demonstrate multi-environment playbook] *******************************************
TASK [Print environment type] *********************************************************
ok: [localhost] => {
"msg": "This host belongs to the development environment"
}
TASK [Show hostname] ******************************************************************
changed: [localhost]
TASK [Display hostname] ***************************************************************
ok: [localhost] => {
"msg": "The hostname is: 66d80191e483433f91fbdca9"
}
PLAY RECAP ****************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
此输出表明:
- Playbook 在开发环境中成功运行。
- 它正确地识别出主机属于开发环境。
- 它成功获取并显示了主机名。
- "PLAY RECAP" 显示了 playbook 执行的摘要。在这里,"ok=3" 表示三个任务成功执行,"changed=1" 表示一个任务对系统进行了更改(运行了
hostname命令)。
使用生产清单运行 Playbook
现在,让我们使用生产清单运行相同的 playbook,看看它的行为有何不同。
在终端中执行以下命令:
ansible-playbook -i /home/labex/project/inventory/prod_inventory.ini /home/labex/project/multi_env_playbook.yaml
此命令与之前的命令类似,但它使用的是 prod_inventory.ini 文件,而不是 dev_inventory.ini。
你应该会看到类似以下的输出:
PLAY [Demonstrate multi-environment playbook] *********************************
TASK [Print environment type] *************************************************
ok: [localhost] => {
"msg": "This host belongs to the production environment"
}
TASK [Show hostname] **********************************************************
changed: [localhost]
TASK [Display hostname] *******************************************************
ok: [localhost] => {
"msg": "The hostname is: labex-instance"
}
PLAY RECAP ********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
请注意,这次 playbook 正确地识别出它正在生产环境中运行。这是因为我们使用了生产清单文件,该文件将主机定义在 [prod] 组下。
其余的输出与我们在开发清单中看到的内容类似,这是预期的,因为我们仍然在同一台本地机器上运行。
使用两个清单运行 Playbook
最后,让我们同时使用两个清单来运行 playbook。这演示了 Ansible 如何同时处理多个清单。
在你的终端中执行以下命令:
ansible-playbook -i /home/labex/project/inventory/dev_inventory.ini -i /home/labex/project/inventory/prod_inventory.ini /home/labex/project/multi_env_playbook.yaml
此命令使用多个 -i 选项包含两个清单文件。Ansible 在运行 playbook 时会合并这些清单。
你应该会看到类似以下的输出:
PLAY [Demonstrate multi-environment playbook] *******************************************************************************************************************************************************************************************************************************************
TASK [Print environment type] ***********************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "This host belongs to the production environment"
}
TASK [Show hostname] ********************************************************************************************************************************************************************************************************************************************************************
changed: [localhost]
TASK [Display hostname] *****************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "The hostname is: 66d80191e483433f91fbdca9"
}
PLAY RECAP ******************************************************************************************************************************************************************************************************************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
你可能会注意到,尽管我们包含了两个清单,但 playbook 只运行了一次。这是因为两个清单都指向同一个 localhost,并且 Ansible 默认会去重主机。如果每个清单中有不同的主机,Ansible 将为每个唯一的主机运行 playbook。
环境被识别为“production”,因为当同一主机出现在多个清单中并属于不同组时,Ansible 会将该主机添加到它所属的 所有 组中。由于 localhost 在 [dev] 和 [prod] 组中都有定义,因此 group_names 变量同时包含 'dev' 和 'prod'。Playbook 的逻辑检查 group_names 中是否包含 'prod',这在这种情况下总是为真,因此它会显示“production”,而不管清单的顺序如何。
这种使用多个清单的方法在实际场景中非常有用,你可能在不同环境中有通用主机,或者你想针对来自不同清单文件的组合主机运行 playbook。
总结
在本实验中,你学习了如何管理多个 Ansible 清单。你为开发和生产环境创建了单独的清单文件,编写了一个可以适用于两种环境的 playbook,并使用不同的清单配置执行了 playbook。
本实验的关键要点包括:
- 创建和组织多个清单文件:你学习了如何为不同的环境创建单独的清单文件,这有助于组织和管主机。
- 编写能够适应不同环境的 playbook:你创建了一个 playbook,它可以检查当前运行的环境并相应地调整其行为。
- 使用单个或多个清单运行 playbook:你学习了如何在运行 playbook 时指定一个或多个清单文件,从而灵活地选择目标主机。
- 理解 Ansible 如何处理出现在多个清单中的主机:你了解到 Ansible 会去重主机,并在确定组归属时使用主机的第一个匹配项。
这些技能在管理具有不同环境的复杂基础设施时至关重要。通过利用多个清单,你可以更好地组织和控制跨不同主机集或环境的 Ansible 自动化。


