使用常用模块编写幂等 Playbook

AnsibleBeginner
立即练习

介绍

幂等性(Idempotence)意味着 Playbook 可以被重复执行,且仅在目标状态缺失或不一致时才会对系统进行更改。

在本实验中,你将使用常用的 Ansible 模块来创建目录和主机别名的配置文件,然后运行两次 Playbook,以证明第二次运行是稳定的。

创建幂等性练习项目

在此步骤中,你将创建一个包含两个本地受管主机别名的小型 Ansible 项目。每个别名都会写入其各自的目录,这样你既可以在单个 RHEL 10 虚拟机内操作,又能观察到针对不同主机的结果。

从默认的 LabEx 工作区开始。

cd /home/labex/project

-p 选项告诉 mkdir 在需要时创建父目录,并且如果目录已存在则直接成功。

mkdir -p rhce-ansible/{inventory/group_vars,playbooks,managed,reports}
cd rhce-ansible

创建项目默认配置,将 Ansible 指向你的清单文件并禁用重试文件(retry files)。

cat > ansible.cfg <<'EOF'
[defaults]
inventory = ./inventory/hosts
host_key_checking = False
retry_files_enabled = False
EOF

managed 目录将存放 Playbook 生成的文件,而 reports 将存放保存的 Playbook 输出。将它们分开存放可以更方便地对比预期内容与 Ansible 的运行记录。

定义本地受管主机和变量

在此步骤中,你将创建清单文件和组变量。这些别名使用 ansible_connection=local,这意味着 Ansible 在针对命名主机执行任务时,实际上是在当前虚拟机上安全地运行。 在执行此步骤的命令之前,请返回到 Ansible 项目目录。这样即使 LabEx 分步运行,命令也能保持稳定。

cd /home/labex/project/rhce-ansible

在同一个组中创建两个应用主机别名。

cat > inventory/hosts <<'EOF'
[app]
app1 ansible_connection=local
app2 ansible_connection=local
EOF

组变量描述了该组中所有主机共享的预期状态。

cat > inventory/group_vars/app.yml <<'EOF'
app_owner: labex
app_environment: training
app_message: Managed by Ansible common modules
EOF

确认 Ansible 可以识别这两个主机。

ansible app --list-hosts

输出应列出 app1 和 app2。在编写 Playbook 之前进行此检查非常有用,因为针对 app 组的 Play 只能影响清单中解析到该组的主机。

编写预期状态 Playbook

在此步骤中,你将编写一个使用 file、copy 和 lineinfile 的 Playbook。这些模块描述的是最终状态,而不是手动运行 shell 命令。 在执行此步骤的命令之前,请返回到 Ansible 项目目录。

cd /home/labex/project/rhce-ansible

创建 Playbook。路径中包含了 {{ inventory_hostname }},以便每个别名都能获得各自的输出目录。

cat > playbooks/common-modules.yml <<'EOF'
---
- name: Configure app host directories with common modules
  hosts: app
  gather_facts: false
  tasks:
    - name: Ensure host directory exists
      ansible.builtin.file:
        path: "/home/labex/project/rhce-ansible/managed/{{ inventory_hostname }}"
        state: directory
        mode: '0755'

    - name: Install base application configuration
      ansible.builtin.copy:
        dest: "/home/labex/project/rhce-ansible/managed/{{ inventory_hostname }}/app.conf"
        content: |
          owner={{ app_owner }}
          environment={{ app_environment }}
          message={{ app_message }}
        mode: '0644'

    - name: Ensure managed message is present
      ansible.builtin.lineinfile:
        path: "/home/labex/project/rhce-ansible/managed/{{ inventory_hostname }}/app.conf"
        line: "message={{ app_message }}"
        create: true
        mode: '0644'
EOF

file 任务用于创建目录,copy 任务用于写入完整的配置文件,而 lineinfile 任务展示了如何强制确保某一行内容存在。这些模块会将当前状态与预期状态进行比较,这就是它们能够实现幂等性的原因。

在运行新的 Playbook 之前,请先进行语法检查。

ansible-playbook playbooks/common-modules.yml --syntax-check

运行 Playbook 并检查文件

在此步骤中,你将首次运行预期状态 Playbook。由于目标文件尚不存在,第一次运行应该会报告更改。 在执行此步骤的命令之前,请返回到 Ansible 项目目录。

cd /home/labex/project/rhce-ansible

运行 Playbook 并保存输出以供后续对比。

ansible-playbook playbooks/common-modules.yml | tee reports/first-run.txt

第一次运行应该会报告更改,因为主机目录和 app.conf 文件都是新创建的。tee 命令让你可以在查看运行过程的同时,将输出保存下来用于幂等性检查。

检查 Ansible 创建的主机特定文件。

cat managed/app1/app.conf managed/app2/app.conf

两个文件应该包含相同的 owner、environment 和 message 值,但它们位于不同的主机别名目录下。这表明 Playbook 已将相同的预期状态应用到了每个清单主机上。

再次运行 Playbook 以验证幂等性

在此步骤中,你将再次运行同一个 Playbook。由于文件已经符合预期状态,Ansible 应该报告两个主机均无更改。 在执行此步骤的命令之前,请返回到 Ansible 项目目录。

cd /home/labex/project/rhce-ansible

第二次运行 Playbook 并保存输出。

ansible-playbook playbooks/common-modules.yml | tee reports/second-run.txt

在汇总行中查找 changed=0。

grep -E 'app[12].*changed=0' reports/second-run.txt

第二次运行出现 changed=0 是幂等性的关键信号。这意味着模块检查了现有文件,并发现无需进行任何修复。

总结

你构建了一个 Ansible 项目,使用常用模块描述了预期状态,运行了 Playbook,并通过第二次运行(报告无更改)验证了其幂等性。