在 RHEL 中使用 Ansible 管理变量和事实

AnsibleBeginner
立即练习

介绍

在本实验中,你将学习在 Red Hat Enterprise Linux (RHEL) 系统上使用 Ansible Playbook 管理变量、事实和机密信息的基本技术。你将探索如何通过使用 Playbook 变量、收集内置和自定义的 Ansible 事实(Facts)以及使用 Ansible Vault 保护密码等敏感数据,使你的自动化工作更加灵活和强大。

通过一系列动手操作,你将构建一个用于部署和配置 Apache Web 服务器的 Playbook。你将首先为软件包名称和 Web 内容定义简单的变量,然后利用自定义事实动态更新 Web 服务器的配置。最后,你将使用 Ansible Vault 安全地创建一个带有加密密码的新系统用户,运行完整的 Playbook,并验证所有配置是否已成功应用。

定义并使用 Playbook 变量部署 Apache Web 服务器

在这一步中,你将学习如何在 Ansible Playbook 中使用变量。变量对于提高自动化的灵活性、可重用性以及代码的可读性和可维护性至关重要。与其将软件包名称或文件路径等值硬编码到任务中,不如将它们定义为变量并在整个 Playbook 中引用。我们将创建一个简单的 Playbook,使用变量来安装 Apache Web 服务器 (httpd) 并部署一个基础网页。

  1. 导航至项目目录

    首先,确保你处于正确的工作目录中。本实验的所有工作都将在 ~/project 目录中进行,该目录已为你创建。

    cd ~/project
    

    安装 ansible-core 软件包。

    sudo dnf install -y ansible-core
    
  2. 创建 Ansible Playbook

    现在,让我们创建 Playbook 文件。将其命名为 playbook.yml。你可以使用 nano 等命令行文本编辑器来创建和编辑该文件。

    nano playbook.yml
    

    该命令会在 nano 编辑器中打开一个空文件。现在,添加 Playbook 的初始部分。此部分定义了 Play 的名称、目标主机(由于我们在同一台机器上运行,因此为 localhost)以及一个 vars 部分,我们将在其中定义变量。

    ---
    - name: Deploy Apache using variables
      hosts: localhost
      become: true
      vars:
        web_pkg: httpd
        web_content: "Hello from Ansible Variables"
    

    以下是 Playbook 结构的解析:

    • hosts: localhost:指定 Playbook 应在本地机器上运行。
    • become: true:告诉 Ansible 在执行任务时使用特权提升(相当于 sudo),这对于安装软件是必需的。
    • vars:这是一个字典,我们在其中定义变量的键值对。我们定义了 web_pkg 作为软件包名称,web_content 作为测试网页的内容。
  3. 向 Playbook 添加任务

    接下来,在 vars 部分下方,添加将使用这些变量的 tasks。第一个任务将安装 Apache 软件包,第二个任务将创建一个 index.html 文件。在 nano 编辑器中,将以下 tasks 块添加到你的 playbook.yml 文件中。

    tasks:
      - name: Install the latest version of Apache
        ansible.builtin.dnf:
          name: "{{ web_pkg }}"
          state: latest
    
      - name: Create a basic index.html file
        ansible.builtin.copy:
          content: "{{ web_content }}"
          dest: /var/www/html/index.html
    

    注意我们是如何使用 {{ variable_name }} 来引用之前定义的变量的。这是 Ansible 用于变量的 Jinja2 模板语法。这使得任务定义具有通用性;如果你想安装 Nginx,只需更改 web_pkg 变量,而无需更改任务本身。

  4. 检查并保存 Playbook

    完整的 playbook.yml 文件现在应该如下所示。请仔细检查内容和缩进,因为 YAML 对空格非常敏感。

    ---
    - name: Deploy Apache using variables
      hosts: localhost
      become: true
      vars:
        web_pkg: httpd
        web_content: "Hello from Ansible Variables"
      tasks:
        - name: Install the latest version of Apache
          ansible.builtin.dnf:
            name: "{{ web_pkg }}"
            state: latest
    
        - name: Create a basic index.html file
          ansible.builtin.copy:
            content: "{{ web_content }}"
            dest: /var/www/html/index.html
    

    要在 nano 中保存文件,请按 Ctrl+X,然后按 Y 确认更改,最后按 Enterplaybook.yml 为文件名保存。

  5. 检查 Playbook 语法

    在运行 Playbook 之前,检查其语法是否有错误是一个好习惯。

    ansible-playbook --syntax-check playbook.yml
    

    如果语法正确,你将看到 Playbook 的文件路径作为输出,确认其有效:

    playbook: playbook.yml
    

    如果看到任何错误,请使用 nano playbook.yml 重新打开文件并修复它们。请特别注意正确的缩进(通常为两个空格)。

  6. 运行 Playbook

    现在,执行 Playbook。Ansible 将连接到 localhost,读取变量并运行任务。

    ansible-playbook playbook.yml
    

    你应该会看到指示每个任务成功执行的输出。changed 状态意味着 Ansible 对系统进行了修改,例如安装了软件包或创建了文件。

    PLAY [Deploy Apache using variables] *******************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Install the latest version of Apache] ************************************
    changed: [localhost]
    
    TASK [Create a basic index.html file] ******************************************
    changed: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    如果你第二次运行该 Playbook,任务应该报告 ok 而不是 changed,因为软件包已经安装且文件已经具有正确的内容。这展示了 Ansible 的幂等性(Idempotency)。

  7. 手动验证配置

    尽管 Playbook 已完成,但你可以手动验证任务是否按预期工作。首先,检查 httpd 软件包是否已安装:

    rpm -q httpd
    

    输出应显示软件包名称和版本:

    httpd-2.4.57-7.el9.x86_64
    

    接下来,检查 index.html 文件的内容:

    cat /var/www/html/index.html
    

    输出应与 web_content 变量的值匹配:

    Hello from Ansible Variables
    

    你已成功在 Ansible Playbook 中使用变量来配置系统。

使用 Ansible 事实显示系统信息

在这一步中,你将探索 Ansible 事实(Facts)。事实是 Ansible 收集的关于其管理系统(在本例中为 localhost)的信息片段。这些信息包括操作系统、网络接口、内存等详细信息。默认情况下,Ansible 会在每个 Play 开始时收集事实,并将它们存储在一个名为 ansible_facts 的特殊变量中。使用事实可以让你创建能够适应运行环境的动态 Playbook。

  1. 导航至项目目录

    首先,确保你处于将要创建新 Playbook 的 ~/project 目录中。

    cd ~/project
    
  2. 创建显示所有事实的 Playbook

    让我们从创建一个仅显示 Ansible 可收集的关于你系统所有事实的 Playbook 开始。这将让你了解可用的海量信息。使用 nano 创建一个名为 display_facts.yml 的新文件。

    nano display_facts.yml
    

    nano 编辑器中,添加以下内容。此 Playbook 针对 localhost,并使用 ansible.builtin.debug 模块打印 ansible_facts 变量的内容。

    ---
    - name: Display all Ansible facts
      hosts: localhost
      tasks:
        - name: Print all available facts
          ansible.builtin.debug:
            var: ansible_facts
    

    保存文件并按 Ctrl+XYEnter 退出 nano

  3. 运行 Playbook

    现在,执行 Playbook 以查看结果。

    ansible-playbook display_facts.yml
    

    输出会非常长,因为 Ansible 收集了大量数据。它将是一个包含所有系统详细信息的大型 JSON 结构。这是预期的结果。

    PLAY [Display all Ansible facts] ***********************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Print all available facts] ***********************************************
    ok: [localhost] => {
        "ansible_facts": {
            "ansible_all_ipv4_addresses": [
                "172.17.0.2"
            ],
            "ansible_all_ipv6_addresses": [
                "fe80::42:acff:fe11:2"
            ],
            "ansible_apparmor": {
                "status": "disabled"
            },
            "ansible_architecture": "x86_64",
            "ansible_bios_date": "01/01/2011",
            "ansible_bios_version": "1.0",
            "ansible_cmdline": {
                "BOOT_IMAGE": "/boot/vmlinuz-5.14.0-427.16.1.el9_4.x86_64",
                "root": "UUID=...",
                "ro": true
            },
            "ansible_date_time": {
                "date": "2024-05-21",
                "day": "21",
                "epoch": "1716298855",
                ...
            },
            "ansible_distribution": "RedHat",
            "ansible_distribution_major_version": "9",
            "ansible_distribution_version": "9.4",
            ...
        }
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    
  4. 创建显示特定事实的 Playbook

    显示所有事实对于发现信息很有用,但在大多数情况下,你只需要特定的信息片段。让我们创建另一个 Playbook display_specific_facts.yml,以显示包含几个关键事实的格式化消息。

    nano display_specific_facts.yml
    

    添加以下内容。此 Playbook 使用 debug 模块的 msg 参数来打印自定义字符串。我们使用括号表示法访问单个事实,例如 ansible_facts['distribution']

    ---
    - name: Display specific Ansible facts
      hosts: localhost
      tasks:
        - name: Print a summary of system facts
          ansible.builtin.debug:
            msg: >
              The operating system is {{ ansible_facts['distribution'] }}
              version {{ ansible_facts['distribution_major_version'] }}.
              It has {{ ansible_facts['processor_cores'] }} processor cores and
              {{ ansible_facts['memtotal_mb'] }} MB of total memory.
    

    msg: > 中的 > 字符是一个 YAML 特性,允许你更整洁地编写多行字符串。保存文件并退出 nano

  5. 运行显示特定事实的 Playbook

    现在,运行这个新 Playbook。

    ansible-playbook display_specific_facts.yml
    

    输出将更加简洁易读,仅显示你请求的信息。

    PLAY [Display specific Ansible facts] ******************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Print a summary of system facts] *****************************************
    ok: [localhost] => {
        "msg": "The operating system is RedHat version 9. It has 2 processor cores and 3925 MB of total memory."
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    这展示了如何利用 Ansible 事实使你的 Playbook 能够感知其运行环境,从而实现更智能、更具条件性的自动化。

使用来自受管主机的自定义事实配置 Web 服务器

在这一步中,你将学习如何使用自定义事实。虽然 Ansible 会自动收集广泛的标准事实,但你也可以定义自己的事实。这些被称为“本地事实”或“自定义事实”。这是一个强大的功能,允许你将受管主机上的特定信息(例如 Ansible 默认不收集的应用程序设置或硬件特定数据)提供给 Playbook。

Ansible 会在受管主机上的 /etc/ansible/facts.d 目录中查找自定义事实。该目录中任何带有 .fact 扩展名的文件都将被处理。这些文件可以是简单的 INI 风格文本文件或 JSON 文件。

  1. 创建自定义事实目录

    首先,你需要创建 Ansible 查找自定义事实文件的目录。由于这是一个系统目录,你必须使用 sudo 来创建它。

    sudo mkdir -p /etc/ansible/facts.d
    

    -p 标志确保如果目录已存在,命令不会返回错误。

  2. 创建自定义事实文件

    现在,让我们创建一个自定义事实文件,为我们的 Web 服务器定义一条欢迎消息。我们将在 /etc/ansible/facts.d 目录中创建一个名为 web_config.fact 的 INI 格式文件。

    sudo nano /etc/ansible/facts.d/web_config.fact
    

    向文件中添加以下内容。这定义了一个包含键 welcome_message[webserver] 部分。

    [webserver]
    welcome_message = Welcome to the server configured by Custom Facts!
    

    保存文件并按 Ctrl+XYEnter 退出 nano

  3. 创建使用自定义事实的 Playbook

    有了自定义事实,我们现在可以创建一个读取该事实并将其用于配置 Web 服务器主页的 Playbook。在你的 ~/project 目录中,创建一个名为 configure_web.yml 的新 Playbook。

    cd ~/project
    nano configure_web.yml
    

    向 Playbook 添加以下内容。此 Playbook 将使用我们自定义事实中定义的消息更新 /var/www/html/index.html 文件。

    ---
    - name: Configure web server using custom facts
      hosts: localhost
      become: true
      tasks:
        - name: Update index.html with custom message
          ansible.builtin.copy:
            content: "{{ ansible_facts.ansible_local.web_config.webserver.welcome_message }}"
            dest: /var/www/html/index.html
    

    让我们解析一下变量 {{ ansible_facts.ansible_local.web_config.webserver.welcome_message }}

    • ansible_facts:所有事实的根字典。
    • ansible_local:存储所有自定义事实的键。
    • web_config:我们的事实文件名(web_config.fact),不带扩展名。
    • webserver:INI 文件中的部分名称 [webserver]
    • welcome_message:我们要使用的值的键。

    保存文件并退出 nano

  4. 运行配置 Playbook

    现在,执行 Playbook 以应用配置。

    ansible-playbook configure_web.yml
    

    输出应显示 copy 任务已 changed(更改)了 index.html 文件。

    PLAY [Configure web server using custom facts] *********************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Update index.html with custom message] ***********************************
    changed: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    
  5. 验证结果

    最后,让我们验证网页是否已正确更新。使用 cat 命令查看 index.html 文件的内容。

    cat /var/www/html/index.html
    

    输出现在应显示来自你的自定义事实文件的消息:

    Welcome to the server configured by Custom Facts!
    

    你已成功在受管主机上创建了自定义事实,并在 Playbook 中使用它来动态配置服务。这种技术对于使你的自动化更加灵活和数据驱动非常有用。

使用 Ansible Vault 的加密变量创建系统用户

在这一步中,你将学习如何使用 Ansible Vault 管理敏感数据,例如密码或 API 密钥。在 Playbook 中以明文形式存储敏感信息是一个重大的安全风险。Ansible Vault 提供了一种加密文件或单个变量的方法,从而保护你的机密信息。你可以在 Playbook 中使用这些加密文件,当提供正确的密码时,Ansible 会在运行时解密它们。

我们将创建一个包含用户名和哈希密码的加密文件,然后使用 Playbook 创建一个带有这些凭据的新系统用户。

  1. 导航至项目目录

    确保你处于此任务的 ~/project 目录中。

    cd ~/project
    
  2. 创建加密的 Vault 文件

    我们将使用 ansible-vault create 命令创建一个名为 secrets.yml 的新加密 YAML 文件。此命令将提示你为 Vault 创建一个密码。以后打开、编辑或使用该文件时都需要此密码。

    首先,将编辑器设置为 nano 以方便操作:

    export EDITOR=nano
    

    现在创建 Vault 文件:

    ansible-vault create secrets.yml
    

    出现提示时,输入 Vault 密码。在本实验中,为了简单起见,我们使用 labex 作为 Vault 密码。你需要输入两次。

    New Vault password:
    Confirm New Vault password:
    

    确认密码后,该命令将在 nano 文本编辑器中打开 secrets.yml 文件。

  3. 向 Vault 文件添加机密变量

    nano 编辑器中(此时正在编辑加密的 secrets.yml 文件),添加以下变量。我们将为新用户定义一个用户名和一个预哈希的密码。使用哈希密码比存储明文密码安全得多。

    username: myappuser
    pwhash: $6$mysalt$QwMzWSEyCAGmz7tzVrAi5o.8k4d05i2QsfGGwmPtlJsWhGjSjCW6yFCH/OEqEsHk7GMSxqYNXu5sshxPmWyxo0
    
    • username:我们要创建的系统用户的名称。
    • pwhash:一个安全哈希后的密码。此特定哈希对应于密码 AnsibleUserP@ssw0rd,并且是 ansible.builtin.user 模块可以理解的格式。

    保存文件并退出 nanoCtrl+X,然后 Y,然后 Enter)。你 ~/project 目录中的 secrets.yml 文件现在已加密。如果你尝试使用 cat secrets.yml 查看它,你只会看到加密文本。

  4. 创建使用 Vault 文件的 Playbook

    现在,创建一个名为 create_user.yml 的新 Playbook,它将使用来自加密 secrets.yml 文件的变量。

    nano create_user.yml
    

    添加以下内容。vars_files 指令告诉 Ansible 从指定文件加载变量。

    ---
    - name: Create a user from secret variables
      hosts: localhost
      become: true
      vars_files:
        - secrets.yml
      tasks:
        - name: Create the {{ username }} user
          ansible.builtin.user:
            name: "{{ username }}"
            password: "{{ pwhash }}"
            state: present
    

    此 Playbook 将创建一个具有 secrets.yml 中定义的名称和密码哈希的用户。保存文件并退出 nano

  5. 使用 Vault 密码运行 Playbook

    要运行使用 Vault 文件的 Playbook,你必须提供 Vault 密码。你可以使用 --ask-vault-pass 标志以交互方式执行此操作。

    ansible-playbook --ask-vault-pass create_user.yml
    

    Ansible 将提示你输入 Vault 密码。输入 labex(你在第 2 步中设置的密码)。

    Vault password:
    

    提供正确的密码后,Ansible 将在内存中解密该文件并运行 Playbook。你应该会看到以下输出,指示用户已创建。

    PLAY [Create a user from secret variables] *************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Create the myappuser user] ***********************************************
    changed: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    
  6. 验证用户是否已创建

    你可以使用 id 命令确认 myappuser 已在系统上成功创建。

    id myappuser
    

    如果用户存在,你将看到其用户 ID (uid) 和组 ID (gid) 信息。

    uid=1002(myappuser) gid=1002(myappuser) groups=1002(myappuser)
    

    这确认了你已成功使用 Ansible Vault 为自动化任务管理敏感数据。

使用 Vault 密码文件运行 Playbook 以应用配置

在这一步中,你将学习一种向 Ansible 提供 Vault 密码的更自动化方式。在上一步中,你使用了 --ask-vault-pass 以交互方式输入密码。虽然这很安全,但不适合 CI/CD 流水线等没有用户在场输入密码的自动化环境。

解决方案是使用 Vault 密码文件。这是一个包含 Vault 密码的简单文本文件。运行 Playbook 时,你可以引用此文件,Ansible 将自动从中读取密码。为了安全起见,限制此密码文件的权限以确保只有授权用户才能读取它至关重要。

  1. 导航至项目目录

    确保你处于 Playbook 和 Vault 文件所在的 ~/project 目录中。

    cd ~/project
    
  2. 创建 Vault 密码文件

    让我们创建一个文件来存储我们的 Vault 密码。将其命名为 vault_pass.txt。我们可以使用 echo 命令一步完成文件的创建并将密码 (labex) 写入其中。

    echo "labex" > vault_pass.txt
    

    你可以使用 cat 验证文件内容:

    cat vault_pass.txt
    

    输出应为:

    labex
    
  3. 保护密码文件

    将密码存储在纯文本文件中是有风险的。你必须限制其文件权限以保护它。chmod 命令允许你更改文件权限。我们将权限设置为 600,这意味着只有文件所有者(在本例中为 labex 用户)拥有读写权限。系统上的其他用户将无法访问它。

    chmod 600 vault_pass.txt
    

    你可以使用 ls -l 命令验证新权限:

    ls -l vault_pass.txt
    

    输出应以 -rw------- 开头,确认权限已受限。

    -rw-------. 1 labex labex 6 May 21 14:30 vault_pass.txt
    
  4. 修改 Playbook 以将用户添加到组

    让我们修改 create_user.yml Playbook 以执行额外操作。我们将把 myappuser 添加到 wheel 组,在许多系统上,这会授予管理(sudo)权限。这将演示运行一个对现有配置进行更改的 Playbook。

    首先,打开 create_user.yml Playbook 进行编辑。

    nano create_user.yml
    

    修改 ansible.builtin.user 任务以包含 groupsappend 参数。

    ---
    - name: Create a user from secret variables
      hosts: localhost
      become: true
      vars_files:
        - secrets.yml
      tasks:
        - name: Create the {{ username }} user and add to wheel group
          ansible.builtin.user:
            name: "{{ username }}"
            password: "{{ pwhash }}"
            state: present
            groups: wheel
            append: true
    
    • groups: wheel:指定要将用户添加到的组。
    • append: true:确保用户被添加到此组中,而不会将其从可能所属的任何其他组中移除。

    保存文件并退出 nano

  5. 使用 Vault 密码文件运行 Playbook

    现在,再次运行 Playbook。这一次,不要使用 --ask-vault-pass,而是使用 --vault-password-file 选项(或其简写别名 --vault-pass-file)来指定密码文件的路径。

    ansible-playbook --vault-password-file vault_pass.txt create_user.yml
    

    Ansible 现在将运行而不会提示输入密码,因为它直接从 vault_pass.txt 中读取密码。你应该会看到指示用户配置已更改的输出。

    PLAY [Create a user from secret variables] *************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Create the myappuser user and add to wheel group] ************************
    changed: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    changed 状态确认 Ansible 通过将用户添加到 wheel 组来修改了该用户。

  6. 验证用户的组成员身份

    最后,验证 myappuser 现在是否是 wheel 组的成员。你可以使用 groups 命令执行此操作。

    groups myappuser
    

    输出应同时显示用户的主组 (myappuser) 和 wheel 组。

    myappuser : myappuser wheel
    

    你已成功使用 Vault 密码文件以非交互方式运行 Playbook,这是自动化安全工作流的一项关键技能。

验证 Web 服务器和用户配置

在最后一步中,你将通过创建一个专门的验证 Playbook 来巩固你的学习成果。到目前为止,你一直使用 catidgroups 等标准 Linux 命令手动检查 Playbook 的结果。一种更强大且可重复的方法是使用 Ansible 本身来审计和验证系统的状态。

此 Playbook 将充当测试套件,以编程方式检查 Web 服务器是否已安装、网页内容是否正确以及系统用户是否存在且具有正确的组成员身份。这展示了 Ansible 不仅可以用于配置管理,还可以用于合规性和状态验证。

  1. 导航至项目目录

    首先,确保你处于 ~/project 目录中。

    cd ~/project
    
  2. 创建验证 Playbook

    让我们创建一个名为 verify_config.yml 的新 Playbook。此 Playbook 将包含一系列任务,用于检查你在之前步骤中应用的配置。

    nano verify_config.yml
    
  3. 添加任务以验证配置

    nano 编辑器中,添加以下内容。我们将构建一个包含多个任务的 Playbook,每个任务都旨在断言某个特定条件为真。如果任何断言失败,Playbook 将停止并报告错误,立即告诉你哪里出了问题。

    ---
    - name: Verify system configuration
      hosts: localhost
      become: true
      tasks:
        - name: Check if httpd package is installed
          ansible.builtin.dnf:
            list: httpd
          register: httpd_pkg_info
    
        - name: Assert that httpd is installed
          ansible.builtin.assert:
            that:
              - httpd_pkg_info.results | length > 0
            fail_msg: "Apache (httpd) package is not installed."
            success_msg: "Apache (httpd) package is installed."
    
        - name: Read the content of the index.html file
          ansible.builtin.slurp:
            src: /var/www/html/index.html
          register: index_file
    
        - name: Assert that the web page content is correct
          ansible.builtin.assert:
            that:
              - "'Custom Facts' in (index_file.content | b64decode)"
            fail_msg: "Web page content is incorrect."
            success_msg: "Web page content is correct."
    
        - name: Check if myappuser exists
          ansible.builtin.getent:
            database: passwd
            key: myappuser
          register: user_info
    
        - name: Assert that myappuser exists
          ansible.builtin.assert:
            that:
              - user_info.ansible_facts.getent_passwd['myappuser'] is defined
            fail_msg: "User 'myappuser' does not exist."
            success_msg: "User 'myappuser' exists."
    
        - name: Query the wheel group members
          ansible.builtin.getent:
            database: group
            key: wheel
          register: wheel_group_info
    
        - name: Assert that myappuser is in the wheel group
          ansible.builtin.assert:
            that:
              - "'myappuser' in (wheel_group_info.ansible_facts.getent_group['wheel'][2] | default('') | split(','))"
            fail_msg: "User 'myappuser' is not in the wheel group."
            success_msg: "User 'myappuser' is in the wheel group."
    

    让我们回顾一下这里使用的关键模块:

    • ansible.builtin.dnf 配合 list:这会检查软件包并 register(注册)结果。
    • ansible.builtin.slurp:这会从远程主机“吸取”整个文件内容。内容经过 base64 编码以实现安全传输。
    • ansible.builtin.getent:这是一种查询 passwdgroup 等系统数据库的安全方法。结果存储在 ansible_facts 下,因此通过 user_info.ansible_facts.getent_passwd 等键访问返回的数据。
    • ansible.builtin.assert:这是我们验证的核心。它检查给定条件是否为真。如果不是,则 Play 失败。我们提供了自定义的成功和失败消息。
    • b64decode:这是一个 Jinja2 过滤器,用于解码我们从 slurp 模块获得的 base64 内容。

    注意,我们分别查询 passwdgroup 数据库。这使得用户存在性检查和 wheel 组成员身份检查与 getent 返回的实际数据保持一致。

    保存文件并退出 nanoCtrl+XYEnter)。

  4. 运行验证 Playbook

    现在,执行你的验证 Playbook。由于它不使用任何 Vault 文件,因此无需提供密码。

    ansible-playbook verify_config.yml
    

    如果之前的所有步骤都已正确完成,Playbook 将成功运行,你将看到每个断言的自定义成功消息。

    PLAY [Verify system configuration] *********************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Check if httpd package is installed] *************************************
    ok: [localhost]
    
    TASK [Assert that httpd is installed] ******************************************
    ok: [localhost] => {
        "changed": false,
        "msg": "Apache (httpd) package is installed."
    }
    
    TASK [Read the content of the index.html file] *********************************
    ok: [localhost]
    
    TASK [Assert that the web page content is correct] *****************************
    ok: [localhost] => {
        "changed": false,
        "msg": "Web page content is correct."
    }
    
    TASK [Check if myappuser exists] ***********************************************
    ok: [localhost]
    
    TASK [Assert that myappuser exists] ********************************************
    ok: [localhost] => {
        "changed": false,
        "msg": "User 'myappuser' exists."
    }
    
    TASK [Query the wheel group members] *******************************************
    ok: [localhost]
    
    TASK [Assert that myappuser is in the wheel group] *****************************
    ok: [localhost] => {
        "changed": false,
        "msg": "User 'myappuser' is in the wheel group."
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=9    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    恭喜!你已成功使用 Ansible 定义变量、收集系统事实、使用 Vault 管理机密信息,并最终以自动化的方式验证了系统的状态。

总结

在本实验中,你学习了如何在 Ansible Playbook 中管理不同类型的数据以配置 RHEL 系统。你首先定义并使用了标准的 Playbook 变量来灵活地安装和配置 Apache Web 服务器。随后,你探索了如何利用 Ansible 的内置事实来显示系统信息,为创建动态且具备主机感知能力的自动化任务奠定了基础。

在此基础上,你通过创建和利用来自受管主机的自定义事实进一步配置了 Web 服务器。为了安全地处理敏感信息,你使用了 Ansible Vault 加密用户密码,使用此加密变量创建了一个新的系统用户,并使用 Vault 密码文件以非交互方式执行了 Playbook。实验最后验证了 Web 服务器和新系统用户均已正确配置,确认了所有所学概念的成功应用。