介绍
清单(Inventory)描述了 Ansible 可以管理的主机以及这些主机所属的组。良好的清单结构可以让你清晰地定位主机,并在合适的范围内附加变量。
在本实验中,你将构建一个包含主机别名、组、子组、组变量、主机变量的静态清单,并编写一个简短的剧本(Playbook)来验证变量是否按预期解析。
创建清单项目
在此步骤中,你将创建用于清单练习的项目目录。本实验使用本地主机别名,以便你可以在一台 RHEL 10 虚拟机中安全地学习清单的行为。
创建并进入项目目录。
cd /home/labex/project
mkdir -p rhce-ansible/{inventory/group_vars,inventory/host_vars,playbooks,reports}
cd rhce-ansible
创建 ansible.cfg,以便 Ansible 默认使用你的清单。
cat > ansible.cfg <<'EOF'
[defaults]
inventory = ./inventory/hosts
retry_files_enabled = False
interpreter_python = auto_silent
EOF
本实验将变量文件放置在 inventory/group_vars 和 inventory/host_vars 下。这种布局将清单数据集中在一起,并明确了这些变量属于 inventory/hosts 中定义的主机。
定义主机、组和子组
在此步骤中,你将创建一个静态清单。每个主机别名都使用 ansible_connection=local,因此这些别名表现得就像受管主机一样,但命令实际上是在当前虚拟机上运行的。子组允许一个组包含其他组。
在执行此步骤的命令之前,请返回 Ansible 项目目录。这样即使 LabEx 分步运行,命令也能保持稳定。
cd /home/labex/project/rhce-ansible
创建 inventory/hosts。
cat > inventory/hosts <<'EOF'
[web]
web1 ansible_connection=local
web2 ansible_connection=local
[db]
db1 ansible_connection=local
[prod:children]
web
db
EOF
检查组关系图。
ansible-inventory --graph
web 和 db 部分定义了普通组。[prod:children] 部分定义了一个父组,因此关系图应该显示 prod 包含了这两个组以及所有三个主机别名。
添加组变量和主机变量
在此步骤中,你将为组和单个主机附加变量。组变量适用于该组中的所有主机。主机变量则会覆盖或补充特定主机的数值。
在执行此步骤的命令之前,请返回 Ansible 项目目录。
cd /home/labex/project/rhce-ansible
为 Web 主机创建变量。
cat > inventory/group_vars/web.yml <<'EOF'
service_role: web
service_port: 8080
EOF
这些值适用于 web 组中的每一台主机。在此清单中,web1 和 web2 都应继承 Web 角色和端口。
为数据库主机创建变量。
cat > inventory/group_vars/db.yml <<'EOF'
service_role: database
service_port: 5432
EOF
数据库组获取了不同的值,因为数据库主机通常需要不同的服务设置。分离组文件可以避免在每个剧本任务中编写条件判断。
为 web2 创建特定于主机的变量。
cat > inventory/host_vars/web2.yml <<'EOF'
rack: rack-b
EOF
主机变量是本实验中使用的最小作用域。只有 web2 拥有 rack 值,这使得区分组级数据和主机级数据变得非常直观。
检查已解析的主机变量
在此步骤中,你将要求 Ansible 显示所选主机的已解析变量。这是在编写剧本之前调试清单的一种安全方法。
在执行此步骤的命令之前,请返回 Ansible 项目目录。
cd /home/labex/project/rhce-ansible
检查 web1。
ansible-inventory --host web1
web1 应该显示 Web 角色和端口,但没有 rack 变量。这种缺失是有用的证据,证明 web2 的主机特定文件没有意外地应用于整个组。
检查 web2 并查找特定于主机的机架(rack)值。
ansible-inventory --host web2 | grep -E 'service_role|service_port|rack'
检查 db1。
ansible-inventory --host db1 | grep -E 'service_role|service_port'
在编写剧本之前比较这三台主机。这是标准的清单调试流程:先确认继承的组值,然后检查是否存在特定于主机的数值。
编写变量报告剧本
在此步骤中,你将创建一个简短的剧本,为每个清单主机写入一个报告文件。该任务使用 inventory_hostname,因此即使所有别名都在本地运行,每个别名也会拥有自己的文件。
在执行此步骤的命令之前,请返回 Ansible 项目目录。
cd /home/labex/project/rhce-ansible
创建剧本。
cat > playbooks/write-inventory-report.yml <<'EOF'
---
- name: Write inventory variable reports
hosts: prod
gather_facts: false
tasks:
- name: Write report for each inventory host
ansible.builtin.copy:
dest: "/home/labex/project/rhce-ansible/reports/{{ inventory_hostname }}.txt"
content: "{{ inventory_hostname }} role={{ service_role }} port={{ service_port }} rack={{ rack | default('none') }}\n"
mode: '0644'
EOF
表达式 {{ inventory_hostname }} 会扩展为当前主机别名,因此一个任务即可为 web1、web2 和 db1 分别创建报告文件。default('none') 过滤器可以防止在未定义 rack 的主机上报错。
运行剧本并检查报告。
ansible-playbook playbooks/write-inventory-report.yml
该剧本的目标是 prod,即包含 Web 和数据库主机的父组。执行摘要应包含所有三个别名,并以 failed=0 结束。
cat reports/*.txt
这些报告文件是清单变量已正确解析的最终证明。web2.txt 应该包含 rack-b,而其他主机应该显示 rack=none。
总结
你构建了一个包含组、子组、组变量和主机变量的静态清单。你还通过 ansible-inventory 和一个小型剧本验证了变量的解析情况。


