Ansible 角色和集合在 RHEL 上的应用

AnsibleAnsibleBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

引言

在本实验中,你将学习如何利用 Ansible Roles 和 Collections 的强大功能和可重用性,来自动化配置 Red Hat Enterprise Linux (RHEL) Web 服务器。你将通过创建自定义角色来部署特定配置,将来自 Git 仓库的外部角色作为依赖项集成,并利用 Ansible Collection 中预先构建的 RHEL System Role 来管理 SELinux 等系统服务,从而构建一个全面的自动化工作流。

整个过程始于使用 ansible-galaxy init 创建一个标准化的角色结构。然后,你将使用 requirements.yml 文件定义并安装来自 Git 仓库的角色依赖项。在集成 RHEL System Role 后,你将把这三种类型的角色——自定义角色、基于 Git 的角色和基于 Collection 的角色——整合到一个主 Playbook 中。最后,你将执行该 Playbook,并验证 Apache Web 服务器和 SELinux 设置是否已正确应用到目标 RHEL 服务器,从而展示一个完整、模块化的自动化解决方案。

使用 ansible-galaxy init 创建自定义 Ansible 角色

在本步骤中,你将开始使用 ansible-galaxy init 命令为新的 Ansible 角色创建一个标准化的目录结构。Ansible 角色是构建可重用和有组织的自动化内容的基础概念。它们允许你将任务 (tasks)、处理程序 (handlers)、变量 (variables) 和其他组件打包成一个独立的、可移植的单元。使用标准结构是一种最佳实践,可以使你的自动化内容更易于理解、管理和共享。

首先,请确保你位于正确的当前工作目录。本实验的所有操作都将在 ~/project 目录中进行。

cd ~/project

在创建角色之前,你需要确保已安装 Ansible 命令行工具。ansible-core 包提供了核心工具,包括 ansible-galaxy

使用 dnf 包管理器安装 ansible-core-y 标志会自动对任何确认提示回答“是”。

sudo dnf install -y ansible-core

你应该会看到输出,表明该软件包正在安装并且依赖项已得到解决。

...
Installed:
  ansible-core-2.16.x-1.el9.x86_64
  ...
Complete!

将所有项目角色组织在一个专用的 roles 目录中是一种常见的做法。现在创建这个目录。

mkdir roles

现在,导航到新创建的 roles 目录。你将在其中初始化你的新自定义角色。

cd roles

你现在将使用 ansible-galaxy init 命令为名为 apache.developer_configs 的角色创建一个骨架。此命令会自动生成一套标准的目录和文件,为你的角色开发提供一个干净的起点。

ansible-galaxy init apache.developer_configs

运行命令后,你将看到一条确认消息。

- Role apache.developer_configs was created successfully

要查看刚刚创建的结构,你可以使用 ls -R 命令,该命令会递归地列出目录及其所有子目录的内容。

ls -R apache.developer_configs

输出显示了 Ansible 角色的标准目录结构:

apache.developer_configs:
defaults  files  handlers  meta  README.md  tasks  templates  tests  vars

apache.developer_configs/defaults:
main.yml

apache.developer_configs/files:

apache.developer_configs/handlers:
main.yml

apache.developer_configs/meta:
main.yml

apache.developer_configs/tasks:
main.yml

apache.developer_configs/templates:

apache.developer_configs/tests:
inventory  test.yml

apache.developer_configs/vars:
main.yml

以下是其中最重要的目录的简要概述:

  • tasks: 包含角色要执行的任务的主列表。
  • handlers: 包含处理程序,这些处理程序是仅在被另一个任务通知时才运行的任务。
  • vars: 包含角色的变量。
  • templates: 包含使用 Jinja2 模板引擎的文件模板。
  • meta: 包含角色的元数据,包括对其他角色的依赖项。

你现在已经成功创建了自定义 Ansible 角色的基本结构。在接下来的步骤中,你将填充这些目录的内容来配置 Web 服务器。

使用 requirements.yml 从 Git 仓库安装角色依赖项

在本步骤中,你将学习如何管理来自外部源(如 Git 仓库)的角色依赖项。这在大型 Ansible 项目中是一种常见做法,你可以在其中重用社区或其他团队开发的角色。Ansible 使用一个文件(通常命名为 requirements.yml)来定义要安装的角色列表。

你的自定义角色 apache.developer_configs 将依赖于一个基础的 Apache 角色,以确保 Web 服务器已安装并运行。你将定义此依赖项并进行安装。

首先,请确保你位于主项目目录中。如果你仍然在上一 B 步骤的 roles 子目录中,请导航回 ~/project

cd ~/project

现在,你将在 roles 目录中创建 requirements.yml 文件。此文件将列出你的项目所需的所有外部角色。使用 nano 编辑器来创建和编辑该文件。

nano roles/requirements.yml

将以下内容添加到文件中。此条目指示 ansible-galaxy 从公共 Git 仓库下载特定版本的 Apache 角色,并在本地将其命名为 infra.apache

- name: infra.apache
  src: https://github.com/geerlingguy/ansible-role-apache.git
  scm: git
  version: 3.2.0

让我们来分解一下这个定义:

  • name: 这是角色的本地名称。即使源仓库名称不同,它也会被安装到名为 infra.apache 的目录中。
  • src: Git 仓库的源 URL。
  • scm: 指定源代码管理工具,本例中为 git
  • version: 要使用的特定 Git 分支、标签或提交哈希。固定版本对于确保你的自动化稳定且可预测至关重要。

保存文件并退出 nano,按 Ctrl+X,然后按 Y,最后按 Enter

requirements.yml 文件就位后,你现在可以使用 ansible-galaxy install 命令下载并安装该角色。

  • -r 标志指向你的 requirements 文件。
  • -p 标志指定角色应安装的路径。
ansible-galaxy install -r roles/requirements.yml -p roles

你将看到输出确认下载和安装过程。

Starting galaxy role install process
- downloading role 'ansible-role-apache', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/ansible-role-apache/archive/3.2.0.tar.gz
- extracting infra.apache to /home/labex/project/roles/infra.apache
- infra.apache (3.2.0) was installed successfully

为了确认角色已正确安装,请列出 roles 目录的内容。

ls -l roles

现在你应该会看到 infra.apache 目录以及你之前创建的 apache.developer_configs 角色。

total 12
drwxr-xr-x. 9 labex labex 4096 Nov 10 10:10 apache.developer_configs
drwxr-xr-x. 9 labex labex 4096 Nov 10 10:15 infra.apache
-rw-r--r--. 1 labex labex  118 Nov 10 10:12 requirements.yml

你现在已成功将外部 Git 仓库声明为依赖项并将其安装到你的项目中。下一步是将此依赖项集成到你的自定义角色的元数据中。

集成来自 Ansible Collection 的 RHEL 系统角色

在本步骤中,你将使用 Ansible Collections,这是分发 Ansible 内容(包括角色、模块和插件)的标准方式。你将安装 Community General collection,它提供了一组用于自动化常见管理任务(包括 SELinux 管理)的有用模块。

对于我们的 Web 服务器场景,我们需要正确配置 SELinux,以允许 Apache 服务监听非标准端口。community.general collection 包含非常适合此任务的 SELinux 模块。

首先,请确保你位于主项目目录中。

cd ~/project

将 collections 安装在项目目录内是一种最佳实践,可以使你的项目自包含。创建一个名为 collections 的目录来存储它们。

mkdir collections

现在,使用 ansible-galaxy collection install 命令安装所需的 collections。-p 标志指示命令将 collections 安装到你刚刚创建的 collections 目录中。

ansible-galaxy collection install community.general ansible.posix -p collections

该命令将下载 collections 及其依赖项。你将看到类似以下的输出:

Starting galaxy collection install process
Process install dependency map
Starting collection install process
Installing 'community.general:11.0.0' to '/home/labex/project/collections/ansible_collections/community/general'
Installing 'ansible.posix:2.0.0' to '/home/labex/project/collections/ansible_collections/ansible/posix'
...
community.general:11.0.0 was installed successfully
ansible.posix:2.0.0 was installed successfully

为了验证该 collection 现在是否可供你的项目使用,你可以通过指定 collections 路径来列出所有已安装的 collections。

ansible-galaxy collection list -p collections

输出将显示已安装的 collections 及其在项目中的安装路径。

## /home/labex/project/collections/ansible_collections
Collection              Version
----------------------- -------
ansible.posix           2.0.0
community.general       11.0.0

在 playbook 中使用 collection 中的模块时,你必须使用其完全限定的集合名称 (Fully Qualified Collection Name, FQCN) 来引用它。对于 SELinux 管理,你将使用 ansible.posix.selinux 来管理 SELinux 状态,使用 community.general.seport 来管理 SELinux 端口。

你现在已成功安装了包含 SELinux 管理模块的强大 collections。在下一步中,你将组合一个 playbook,该 playbook 使用你的自定义角色、来自 Git 的角色以及来自这些 collections 的 SELinux 模块来完全配置开发 Web 服务器。

组合并运行包含自定义角色、Git 角色和系统角色的 Playbook

在本步骤中,你将整合所有已准备好的组件:你的自定义角色、来自 Git 的依赖项以及 RHEL 系统角色。你将创建一个主 Playbook,该 Playbook 协调这些角色,以完全配置开发 Web 服务器。

将此步骤视为从不同零件组装复杂机器——每个角色都有特定的用途,它们协同工作以创建完整的 Web 服务器环境。让我们将其分解为易于管理的块:

首先,请确保你位于主项目目录中。

cd ~/project

在深入配置之前,让我们了解一下我们正在创建的内容:

  • Ansible 配置 (Ansible Configuration):设置 Ansible 的行为方式以及它查找文件的位置
  • 清单 (Inventory):定义要管理的服务器(在我们的例子中是 localhost)
  • 变量 (Variables):存储我们的角色将使用的数据(开发者信息、SELinux 设置)
  • 自定义角色内容 (Custom Role Content):实际配置开发者环境的任务
  • 主 Playbook (Main Playbook):按正确顺序运行所有内容的协调器

1. 创建 Ansible 配置和清单

ansible.cfg 文件就像一个配置文件,它告诉 Ansible 如何运行。没有它,你需要在每个命令中指定路径和选项。有了它,Ansible 就能自动知道在哪里找到你的角色、collections 和清单。

使用 nano 创建 ansible.cfg 文件。此文件告诉 Ansible 在哪里查找你的角色、collections 和清单。

nano ansible.cfg

添加以下内容。让我们了解每一行:

[defaults]
inventory = inventory                 ## 告诉 Ansible 使用名为 'inventory' 的文件
roles_path = roles                   ## 在 'roles' 目录中查找角色
collections_paths = collections      ## 在 'collections' 目录中查找 collections
host_key_checking = False           ## 跳过 SSH 密钥验证(在实验环境中很有用)

[privilege_escalation]
become = True                       ## 自动使用 sudo 执行需要提升权限的任务

每个设置的作用:

  • inventory = inventory: 无需每次都输入 -i inventory,Ansible 将自动使用此文件
  • roles_path = roles: Ansible 将在 roles 目录中查找角色
  • collections_paths = collections: Ansible 将在此处查找已安装的 collections
  • host_key_checking = False: 防止在实验环境中出现 SSH 密钥验证错误
  • become = True: 在需要时自动使用提升的权限运行任务

保存并退出 nano(按 Ctrl+X,然后按 Y,然后按 Enter)。

清单文件告诉 Ansible 要管理哪些机器。在我们的例子中,我们正在配置本地机器。

nano inventory

添加以下行:

localhost ansible_connection=local

这意味着:

  • localhost: 我们目标主机的名称
  • ansible_connection=local: 使用本地连接而不是 SSH(因为我们正在管理运行 Ansible 的同一台机器)

保存并退出 nano

2. 定义角色变量

Ansible 中的变量就像你的角色可以使用的设置。你无需在任务中硬编码用户名或端口号等值,而是在变量文件中定义它们。这使得你的自动化具有灵活性和可重用性。

group_vars/all 目录是一个特殊位置,Ansible 会自动加载适用于所有主机的变量。此目录中的任何 YAML 文件都可供你的 Playbook 和角色使用。

创建适用于所有主机的变量目录结构:

mkdir -p group_vars/all

现在,创建一个文件来定义开发者信息。此数据将由你的自定义角色用于创建用户帐户和 Web 配置。

nano group_vars/all/developers.yml

添加以下内容:

---
web_developers:
  - username: jdoe ## 第一位开发者
    port: 9081 ## 此开发者网站的自定义端口
  - username: jdoe2 ## 第二位开发者
    port: 9082 ## 此开发者网站的自定义端口

此数据结构的含义:

  • web_developers: 一个包含开发者信息的列表
  • 每个开发者都有一个 username 和一个 port
  • 你的自定义角色将遍历此列表以创建每个开发者的配置

保存并退出。

接下来,为 SELinux 配置创建一个变量文件。SELinux(Security-Enhanced Linux)是一个控制应用程序可以做什么的安全模块。

nano group_vars/all/selinux.yml

添加以下内容:

---
selinux_state: enforcing ## 将 SELinux 设置为 enforcing 模式(最高安全性)
selinux_ports: ## 允许 Apache 使用的端口列表
  - ports: "9081" ## 允许端口 9081
    proto: "tcp" ## 协议:TCP
    setype: "http_port_t" ## SELinux 类型:HTTP 端口
    state: "present" ## 添加此规则
  - ports: "9082" ## 允许端口 9082
    proto: "tcp" ## 协议:TCP
    setype: "http_port_t" ## SELinux 类型:HTTP 端口
    state: "present" ## 添加此规则

理解 SELinux 设置:

  • selinux_state: enforcing: SELinux 将主动阻止未经授权的操作
  • selinux_ports: 端口配置列表
  • http_port_t: 允许 Apache 绑定到端口的 SELinux 类型
  • 默认情况下,Apache 只能使用端口 80 和 443;我们需要显式允许 9081 和 9082

保存并退出。

3. 填充自定义角色

你的 apache.developer_configs 角色目前只有目录结构,但没有实际内容。我们需要添加:

  • 模板 (Templates):可以包含变量的文件(使用 Jinja2 语法)
  • 任务 (Tasks):Ansible 将执行的实际工作
  • 处理程序 (Handlers):仅在被通知时才运行的特殊任务(例如重启服务)
  • 元数据 (Metadata):关于角色依赖项的信息

模板允许你创建基于变量进行调整的配置文件。.j2 扩展名表示这是一个 Jinja2 模板。

nano roles/apache.developer_configs/templates/developer.conf.j2

添加以下内容:

{% for dev in web_developers %}
Listen {{ dev.port }}
<VirtualHost *:{{ dev.port }}>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/{{ dev.username }}

    <Directory /var/www/{{ dev.username }}>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>
{% endfor %}

理解模板语法:

  • {% for dev in web_developers %}:开始遍历开发者列表的循环
  • {{ dev.port }}:插入此开发者的端口号
  • {{ dev.username }}:插入此开发者的用户名
  • {% endfor %}:结束循环
  • 结果将是为每个开发者生成的单独的虚拟主机配置

这会创建什么: 对于我们的两位开发者,此模板将生成 Apache 配置,该配置:

  1. 使 Apache 监听端口 9081 和 9082
  2. 创建从 /var/www/jdoe/var/www/jdoe2 提供内容的虚拟主机
  3. 为每个目录设置适当的权限

保存并退出。

任务是 Ansible 执行的实际工作。每个任务都使用 Ansible 模块来完成特定操作。

nano roles/apache.developer_configs/tasks/main.yml

添加以下内容,并让我们了解每个任务:

---
## 任务 1:为每个开发者创建用户帐户
- name: Create developer user accounts
  ansible.builtin.user: ## 使用 'user' 模块
    name: "{{ item.username }}" ## 创建具有此名称的用户
    state: present ## 确保用户存在
  loop: "{{ web_developers }}" ## 对列表中的每个开发者执行此操作

## 任务 2:为每个开发者创建 Web 根目录
- name: Create developer web root directories
  ansible.builtin.file: ## 使用 'file' 模块
    path: "/var/www/{{ item.username }}" ## 创建此目录
    state: directory ## 确保它是一个目录
    owner: "{{ item.username }}" ## 设置所有者
    group: "{{ item.username }}" ## 设置组
    mode: "0755" ## 设置权限 (rwxr-xr-x)
  loop: "{{ web_developers }}"

## 任务 3:为每个开发者创建示例网页
- name: Create a sample index.html for each developer
  ansible.builtin.copy: ## 使用 'copy' 模块
    content: "Welcome to {{ item.username }}'s dev space\n" ## 文件内容
    dest: "/var/www/{{ item.username }}/index.html" ## 放置文件的位置
    owner: "{{ item.username }}" ## 文件所有者
    group: "{{ item.username }}" ## 文件组
    mode: "0644" ## 文件权限 (rw-r--r--)
  loop: "{{ web_developers }}"

## 任务 4:部署 Apache 配置文件
- name: Deploy developer apache configs
  ansible.builtin.template: ## 使用 'template' 模块
    src: developer.conf.j2 ## 源模板文件
    dest: /etc/httpd/conf.d/developer.conf ## 服务器上的目标位置
    mode: "0644" ## 文件权限
  notify: restart apache ## 在此更改时触发 restart apache 处理程序

理解关键概念:

  • loop: 对列表中的每个项重复任务
  • {{ item.username }}:引用循环中当前项的用户名
  • notify: restart apache: 当此任务进行更改时,它将触发一个名为“restart apache”的处理程序
  • 文件权限:0755 表示所有者可以读/写/执行,其他人可以读/执行;0644 表示所有者可以读/写,其他人只能读

保存并退出。

处理程序是仅在被其他任务通知时才运行的特殊任务。它们通常用于重启服务等操作。

nano roles/apache.developer_configs/handlers/main.yml

添加以下内容:

---
- name: restart apache ## 此名称必须与 notify: 语句匹配
  ansible.builtin.service: ## 使用 'service' 模块
    name: httpd ## 服务名称(在 RHEL 上,Apache 称为 'httpd')
    state: restarted ## 重启服务

为什么使用处理程序?

  • 效率:仅当配置实际更改时才重启服务
  • 顺序:所有任务先运行,然后所有处理程序在最后运行
  • 幂等性:多个任务可以通知同一个处理程序,但它只运行一次

保存并退出。

最后,我们需要告诉 Ansible,我们的自定义角色依赖于我们之前安装的 infra.apache 角色。

nano roles/apache.developer_configs/meta/main.yml

将文件内容替换为:

---
dependencies:
  - role: infra.apache ## 此角色必须在我们的自定义角色之前运行

这有什么作用:

  • 当 Ansible 运行 apache.developer_configs 时,它将首先自动运行 infra.apache
  • 这确保在添加自定义配置之前已安装并配置好 Apache
  • 依赖项按列出的顺序运行

保存并退出。

4. 组合并运行主 Playbook

Playbook 就像一个告诉 Ansible 该做什么以及按什么顺序做的食谱。我们的 Playbook 将:

  1. 配置 SELinux 设置 (pre_tasks)
  2. 运行我们的角色(包括依赖项链)

创建主 Playbook 文件:

nano web_dev_server.yml

添加以下内容并附带详细说明:

---
- name: Configure Dev Web Server ## Playbook 名称
  hosts: localhost ## 在 localhost 上运行
  pre_tasks: ## 在角色之前运行的任务
    ## 任务 1:配置 SELinux 模式
    - name: Set SELinux to enforcing mode
      ansible.posix.selinux: ## 来自 ansible.posix collection 的模块
        policy: targeted ## 使用 'targeted' SELinux 策略
        state: "{{ selinux_state }}" ## 使用我们定义的变量
      when: selinux_state is defined ## 仅当变量存在时运行

    ## 任务 2:配置 SELinux 端口
    - name: Configure SELinux ports for Apache
      community.general.seport: ## 来自 community.general collection 的模块
        ports: "{{ item.ports }}" ## 端口号
        proto: "{{ item.proto }}" ## 协议 (tcp)
        setype: "{{ item.setype }}" ## SELinux 类型 (http_port_t)
        state: "{{ item.state }}" ## present 或 absent
      loop: "{{ selinux_ports }}" ## 遍历我们的端口列表
      when: selinux_ports is defined ## 仅当变量存在时运行

  roles: ## 要执行的角色
    - apache.developer_configs ## 我们的自定义角色(它将触发 infra.apache)

理解执行顺序:

  1. pre_tasks: SELinux 配置首先运行
  2. roles: 依赖项角色运行 (infra.apache),然后是我们的自定义角色
  3. handlers: 任何被通知的处理程序最后运行

为什么这个顺序很重要:

  • 在 Apache 尝试绑定到自定义端口之前必须配置好 SELinux
  • 在配置虚拟主机之前必须安装好 Apache
  • 服务重启发生在所有配置完成后

保存并退出。

现在你已准备好执行你的完整自动化:

ansible-playbook web_dev_server.yml

Playbook 将执行,你将看到详细的输出。以下是你期望看到的:

PLAY [Configure Dev Web Server] *************************************************

TASK [Gathering Facts] **********************************************************
ok: [localhost]                     ## Ansible 收集系统信息

TASK [Set SELinux to enforcing mode] *******************************************
changed: [localhost]                ## SELinux 模式已更改

TASK [Configure SELinux ports for Apache] **************************************
changed: [localhost] => (item={'ports': '9081', 'proto': 'tcp', 'setype': 'http_port_t', 'state': 'present'})
changed: [localhost] => (item={'ports': '9082', 'proto': 'tcp', 'setype': 'http_port_t', 'state': 'present'})

TASK [infra.apache : Ensure Apache is installed.] *******************************
changed: [localhost]                ## Apache 包已安装

TASK [apache.developer_configs : Create developer user accounts] ****************
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})

TASK [apache.developer_configs : Create developer web root directories] *********
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})

TASK [apache.developer_configs : Create a sample index.html for each developer] *
changed: [localhost] => (item={'username': 'jdoe', 'port': 9081})
changed: [localhost] => (item={'username': 'jdoe2', 'port': 9082})

TASK [apache.developer_configs : Deploy developer apache configs] ***************
changed: [localhost]                ## 配置文件已创建

RUNNING HANDLER [apache.developer_configs : restart apache] *********************
changed: [localhost]                ## Apache 已重启

PLAY RECAP **********************************************************************
localhost                  : ok=17   changed=12   unreachable=0    failed=0    skipped=3    rescued=0    ignored=0

你已成功组合并运行了一个复杂的 Playbook,该 Playbook 结合了来自不同来源的多个角色,以创建完整的 Web 开发环境!

验证 RHEL 服务器上的 SELinux 和 Apache 配置

在最后一步中,你将验证你的 Ansible 自动化是否已正确配置系统。确认服务是否按预期运行以及安全策略(SELinux)是否已正确应用至关重要。你将使用标准的 RHEL 命令行工具来检查系统状态。

首先,请确保你位于主项目目录中。

cd ~/project

1. 验证 SELinux 配置

来自 collections 的 SELinux 模块的任务是将 SELinux 模式设置为 enforcing,并为 http_port_t 类型允许新端口。

使用 sestatus 命令检查当前的 SELinux 状态。

sestatus

输出应显示 SELinux 已启用并处于 enforcing 模式。

SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Memory protection checking:     actual (secure)
Max kernel policy version:      33

接下来,使用 semanage port 命令验证端口 90819082 是否已添加到 http_port_t 上下文中。你可以将输出通过管道传递给 grep 来查找相关行。

sudo semanage port -l | grep http_port_t

你应该会在默认 HTTP 端口列表中看到你自定义的端口。确切的输出可能会有所不同,但它将包含你定义的端口。

http_port_t                    tcp      9082, 9081, 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t            tcp      5988

这证实了 SELinux 模块已成功更新策略。

2. 验证 Apache 服务和配置

infra.apache 角色安装并启动了 httpd 服务。由于此容器环境中没有 systemctl,你可以使用 ps 来检查正在运行的进程。

ps aux | grep httpd

你应该会看到多个 httpd 进程正在运行,这表明服务已激活。

root        8851  0.2  0.4  25652 16228 ?        Ss   09:31   0:00 /usr/sbin/httpd -DFOREGROUND
apache      8852  0.0  0.1  25308  6044 ?        S    09:31   0:00 /usr/sbin/httpd -DFOREGROUND
apache      8853  0.0  0.3 1443348 11364 ?       Sl   09:31   0:00 /usr/sbin/httpd -DFOREGROUND
apache      8854  0.0  0.3 1443348 11480 ?       Sl   09:31   0:00 /usr/sbin/httpd -DFOREGROUND
apache      8855  0.0  0.4 1574484 15848 ?       Sl   09:31   0:00 /usr/sbin/httpd -DFOREGROUND
labex       9298  0.0  0.0   6408  2176 pts/3    S+   09:31   0:00 grep --color=auto httpd

3. 验证 Web 内容的可访问性

最后,最重要的测试是查看开发者网站是否可访问。你的 apache.developer_configs 角色在端口 90819082 上设置了虚拟主机。使用 curl 命令从每个端点请求内容。

首先,测试用户 jdoe 在端口 9081 上的网站。

curl http://localhost:9081

预期的输出是你为该用户创建的 index.html 文件的内容。

Welcome to jdoe's dev space

接下来,测试用户 jdoe2 在端口 9082 上的网站。

curl http://localhost:9082

你应该会看到相应的欢迎消息。

Welcome to jdoe2's dev space

这些成功的 curl 命令证实了 Apache 已正确配置,虚拟主机正在运行,并且 SELinux 策略允许通过自定义端口进行流量。

恭喜!你已成功构建了一个完整的 Ansible 自动化项目,该项目结合了自定义角色、来自 Git 存储库的角色以及来自 Ansible collections 的 SELinux 模块,以配置一个安全的多租户开发 Web 服务器。

总结

在本实验中,你将学习如何利用 Ansible 角色 (Roles) 和集合 (Collections) 的强大功能和结构,来自动化配置 RHEL Web 服务器。你将从使用 ansible-galaxy init 命令从头开始创建自定义角色开始,该命令为可重用的自动化内容建立了标准化的目录结构。这一基础步骤为更复杂的自动化任务奠定了基础。

在自定义角色的基础上,你将集成外部依赖项,包括通过 requirements.yml 文件中的 Git 存储库角色,以及来自 Ansible Collection 的官方 RHEL 系统角色。最后,你将把这些不同类型的角色——自定义角色、基于 Git 的角色和系统角色——组合到一个 playbook 中,执行它来配置服务器,并验证由此产生的 Apache 和 SELinux 设置,以确认自动化成功。