在 RHEL 上实现 Ansible Playbook

AnsibleAnsibleBeginner
立即练习

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

引言

在本实验中,你将学习如何实现一个完整的 Ansible playbook,在 Red Hat Enterprise Linux (RHEL) 系统上部署一个 Apache Web 服务器。你将从设置 Ansible 项目的基础组件开始,包括创建一个静态 inventory 文件来定义你的托管节点,以及使用 ansible.cfg 文件配置本地 Ansible 环境。

在初始设置之后,你将编写一个多任务 playbook 来自动化核心部署过程。这包括安装和启动 Apache 服务,部署自定义网页,以及配置系统防火墙以允许 HTTP 流量。为了完成实验,你将在 playbook 中添加第二个 play,从命令行测试 Web 服务器,以验证整个部署是否成功。

为 Web 服务器创建静态 Inventory 文件

在本步骤中,你将学习 Ansible inventory 的基础知识。Inventory 是一个文本文件,列出了 Ansible 将要管理的服务器(或“托管节点”)。你将为一组 Web 服务器创建一个简单的静态 inventory 文件,并学习如何验证其内容。

首先,你需要确保你的系统已安装 Ansible。由于它不是默认安装的,你将使用 dnf 包管理器来安装它。

  1. 打开你的终端并安装 ansible-core 包,它提供了 Ansible 的基础命令行工具。

    sudo dnf install -y ansible-core

    你应该会看到输出表明该软件包正在安装和验证。

    ...
    Installed:
      ansible-core-2.16.x-x.el9.x86_64
    ...
    Complete!
  2. 为了更好地组织,请在你的主目录下为这个项目创建一个专用目录。我们将其命名为 ansible-lab

    mkdir -p ~/project/ansible-lab
  3. 进入你新创建的项目目录。本实验中所有后续操作都将在此位置进行。

    cd ~/project/ansible-lab
  4. 现在,你将创建你的第一个 inventory 文件。Inventory 文件通常以类似 INI 的格式编写。你将使用 nano 文本编辑器创建一个名为 inventory 的文件。

    nano inventory
  5. nano 编辑器中,添加以下内容。此配置定义了一个名为 [webservers] 的组,并将你的本地机器 localhost 添加到该组中。

    • [webservers] 是一个组名。组用于通过单个命令定位多个主机。
    • localhost 是你要管理的机器的主机名。在这种情况下,它是 LabEx 虚拟机本身。
    • ansible_connection=local 是一个特殊变量,它告诉 Ansible 直接在控制节点(你的虚拟机)上执行命令,而不是尝试通过 SSH 连接到它。
    [webservers]
    localhost ansible_connection=local

    要在 nano 中保存文件,请按 Ctrl+O,然后按 Enter 确认文件名,最后按 Ctrl+X 退出编辑器。

  6. 创建了 inventory 文件后,你可以使用 ansible-inventory 命令来解析该文件并显示其中包含的主机列表。-i 标志指定了 inventory 文件的路径。

    ansible-inventory --list -i inventory

    该命令将输出 inventory 的 JSON 格式表示,这证实了 Ansible 可以正确读取和理解你的文件。

    {
      "_meta": {
        "hostvars": {
          "localhost": {
            "ansible_connection": "local"
          }
        }
      },
      "all": {
        "children": ["ungrouped", "webservers"]
      },
      "webservers": {
        "hosts": ["localhost"]
      }
    }

你已成功创建了一个基本的静态 inventory 文件,并验证了 Ansible 可以正确解析它。此 inventory 文件将是你后续步骤中编写 playbook 的基础。

使用 ansible.cfg 配置 Ansible 环境

在本步骤中,你将创建一个 Ansible 配置文件 ansible.cfg。此文件允许你设置 Ansible 的默认行为,从而避免反复在命令行中输入常用选项。通过将 ansible.cfg 文件放在你的项目目录中,你可以定义诸如默认 inventory 文件路径之类的设置,Ansible 在该目录运行时将自动使用这些设置。

你应该仍然处于上一步的 ~/project/ansible-lab 目录中。

  1. 使用 nano 文本编辑器在当前目录(~/project/ansible-lab)中创建一个名为 ansible.cfg 的新文件。

    nano ansible.cfg
  2. nano 编辑器中,添加以下内容。此配置告诉 Ansible 在哪里可以找到你的默认 inventory 文件。

    • [defaults] 部分是 ansible.cfg 文件的一个标准部分,你可以在其中定义大多数默认设置。
    • inventory = ./inventory 行将默认 inventory 设置为位于当前目录(.)下的 inventory 文件。
    [defaults]
    inventory = ./inventory

    通过按 Ctrl+O,然后按 Enter 保存文件,最后按 Ctrl+X 退出。

  3. 现在你已经配置了默认 inventory 路径,只要你还在 ~/project/ansible-lab 目录中,就不再需要对 Ansible 命令使用 -i 标志了。

    为了测试这一点,再次运行 ansible-inventory --list 命令,但这次省略 -i inventory 部分。

    ansible-inventory --list

    你应该会看到与上一步完全相同的 JSON 输出,这证实了由于新的 ansible.cfg 配置,Ansible 能够自动找到并使用你的 inventory 文件。

    {
      "_meta": {
        "hostvars": {
          "localhost": {
            "ansible_connection": "local"
          }
        }
      },
      "all": {
        "children": ["ungrouped", "webservers"]
      },
      "webservers": {
        "hosts": ["localhost"]
      }
    }

通过创建特定于项目的 ansible.cfg,你已经提高了工作流程的效率。这是 Ansible 项目中常见的做法,以确保一致的行为并减少命令行复杂性。

编写 Playbook 来安装和启动 Apache 服务

在本步骤中,你将编写你的第一个 Ansible Playbook。Playbook 是一个用 YAML 格式编写的文件,它描述了要在托管主机上执行的一系列任务。你将创建一个 Playbook,该 Playbook 将在你的 inventory 中定义的 localhost 机器上安装 Apache Web 服务器(httpd)并启动其服务。

你应该仍然处于 ~/project/ansible-lab 目录中。

  1. 首先,使用 nano 文本编辑器创建一个名为 apache.yml 的新文件。此文件将包含你的 Playbook。

    nano apache.yml
  2. nano 编辑器中,你将定义一个“play”。Play 是 Playbook 的核心单元,它将一组主机映射到一组任务。将以下内容添加到 apache.yml

    • ---: 这是一个标准的 YAML 标记,表示文档的开始。
    • - name: ...: 这是你的 play 的开始。给它一个描述性的名称是一种最佳实践。
    • hosts: webservers: 这告诉 Ansible 在你的 inventory 文件中的 webservers 组中的所有主机上运行此 play。
    • become: true: 这指示 Ansible 使用权限提升(如 sudo)来执行任务。这对于安装软件或管理服务等操作是必需的。
    • tasks:: 这个关键字开始要执行的任务列表。
    ---
    - name: Install and start Apache web server
      hosts: webservers
      become: true
      tasks:
  3. 现在,将任务添加到你的 Playbook 中。每个任务都是一个调用 Ansible 模块的单一操作。YAML 中的缩进至关重要,因此请确保任务在 tasks: 部分下正确缩进。

    • 任务 1:安装 httpd。 此任务使用 ansible.builtin.dnf 模块来确保安装 httpd 包。state: present 参数意味着如果包缺失,Ansible 将安装它;如果已安装,则不执行任何操作。
    • 任务 2:启动 httpd 服务。 此任务使用 ansible.builtin.service 模块。state: started 确保服务正在运行,而 enabled: true 确保它将在系统启动时自动启动。

    将以下任务添加到你的 apache.yml 文件中,直接放在 tasks: 行下方:

    - name: Install httpd package
      ansible.builtin.dnf:
        name: httpd
        state: present
    
    - name: Start and enable httpd service
      ansible.builtin.service:
        name: httpd
        state: started
        enabled: true
  4. 你完整的 apache.yml Playbook 现在应该如下所示。请仔细检查缩进。

    ---
    - name: Install and start Apache web server
      hosts: webservers
      become: true
      tasks:
        - name: Install httpd package
          ansible.builtin.dnf:
            name: httpd
            state: present
    
        - name: Start and enable httpd service
          ansible.builtin.service:
            name: httpd
            state: started
            enabled: true

    保存文件并退出 nanoCtrl+OEnterCtrl+X)。

  5. 在运行你的 Playbook 之前,最好使用 ansible-playbook 命令和 --syntax-check 标志来检查其语法错误。

    ansible-playbook --syntax-check apache.yml

    如果语法正确,该命令将打印 Playbook 的文件名而不会出现任何错误。

    playbook: apache.yml
  6. 现在,执行 Playbook。

    ansible-playbook apache.yml

    Ansible 将执行这些任务。由于这是第一次运行,你将看到两个任务的状态都显示为 changed,这表明系统状态已被修改。

    PLAY [Install and start Apache web server] *************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Install httpd package] ***************************************************
    changed: [localhost]
    
    TASK [Start and enable httpd service] ******************************************
    changed: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  7. 最后,通过使用 curllocalhost 请求默认网页来验证 Apache Web 服务器是否正在运行。

    curl http://localhost

    你应该会看到默认的 Apache 测试页面,这证实了你的 Playbook 已成功运行。

    <html>
      <head>
        <title>Test Page</title>
      </head>
      <body>
        <h1>Test Page</h1>
        <p>This is the default test page for the Apache HTTP server.</p>
      </body>
    </html>

添加任务以部署网页

在本步骤中,你将扩展你的 Playbook 以执行更实际的 Web 服务器配置。你将添加一个任务来部署自定义的 index.html 页面。这演示了如何使用 Ansible 的文件管理模块来管理文件。

你应该仍然处于 ~/project/ansible-lab 目录中。

  1. 首先,创建一个简单的 HTML 文件,你的 Playbook 将部署该文件。使用 nano 在当前目录中创建一个名为 index.html 的文件。

    nano index.html
  2. 将以下 HTML 内容添加到文件中。这将是你自定义网页的内容。

    <h1>Welcome to the Ansible-managed Web Server!</h1>
    <p>This page was deployed using an Ansible Playbook.</p>

    保存并退出 nanoCtrl+OEnterCtrl+X)。

  3. 现在,你将更新你的 apache.yml Playbook 以添加新任务。为避免 YAML 格式错误,建议用下面显示的完整内容重新创建该文件。

    重要提示:为确保正确的 YAML 格式并避免缩进错误,请删除现有的 apache.yml 文件,并用下面显示的完整内容创建一个新文件。

    rm apache.yml
    nano apache.yml
  4. 你将向 Playbook 添加一个新任务。此任务会将 index.html 文件复制到 Web 服务器的文档根目录(/var/www/html/)。

    • 任务:部署 index.html。 此任务使用 ansible.builtin.copy 模块。src 指定控制节点上的源文件(index.html),dest 指定托管主机上的目标路径。
  5. 复制并粘贴下面完整的 apache.yml Playbook 内容。这确保了正确的 YAML 格式和缩进。

    ---
    - name: Install and start Apache web server
      hosts: webservers
      become: true
      tasks:
        - name: Install httpd package
          ansible.builtin.dnf:
            name: httpd
            state: present
    
        - name: Deploy custom index.html
          ansible.builtin.copy:
            src: index.html
            dest: /var/www/html/index.html
    
        - name: Start and enable httpd service
          ansible.builtin.service:
            name: httpd
            state: started
            enabled: true

    保存并退出 nano

  6. 保存文件并退出 nanoCtrl+OEnterCtrl+X),然后运行更新后的 Playbook。

    ansible-playbook apache.yml

    这次,你应该会看到新任务正在执行。“Install httpd”和“Start httpd”任务应报告 ok,因为它们的目标状态已满足。“Deploy custom index.html”任务将报告 changed

    PLAY [Install and start Apache web server] *************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Install httpd package] ***************************************************
    ok: [localhost]
    
    TASK [Deploy custom index.html] ************************************************
    changed: [localhost]
    
    TASK [Start and enable httpd service] ******************************************
    ok: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  7. 最后,再次使用 curl 来验证你的自定义网页是否已提供服务。

    curl http://localhost

    输出现在应该是你的 index.html 文件中的内容。

    <h1>Welcome to the Ansible-managed Web Server!</h1>
    <p>This page was deployed using an Ansible Playbook.</p>

实现第二个 Play 来测试 Web 服务器部署

在最后这个步骤中,你将为你的 Playbook 添加第二个 Play。一个 Playbook 文件可以包含多个 Play,它们会按顺序执行。这对于组织针对不同主机或具有不同目的的任务非常有用。你将添加一个新 Play,该 Play 只在控制节点(localhost)上运行,以测试在第一个 Play 中配置的 Web 服务器。

你应该仍然处于 ~/project/ansible-lab 目录中。

  1. 你现在将为你的 Playbook 添加第二个 Play。为确保在添加第二个 Play 时具有正确的 YAML 格式,建议用下面显示的完整双 Play 内容重新创建该文件。

    重要提示:为避免在添加第二个 Play 时出现 YAML 缩进错误,请删除现有的 apache.yml 文件,并用下面显示的完整双 Play 内容创建一个新文件。

    rm apache.yml
    nano apache.yml
  2. 你将向 Playbook 添加第二个 Play。第二个 Play 允许你组织针对不同主机或具有不同目的的任务。

    • name: Test web server: 为新 Play 提供一个描述性名称。
    • hosts: localhost: 此 Play 将在 localhost(即控制节点本身)上运行。
    • become: false: 此测试不需要 root 权限,因此我们显式禁用了权限提升。
    • 任务:验证 Web 内容。 此任务使用 ansible.builtin.uri 模块向 Web 服务器发出 HTTP 请求。它检查服务器是否返回状态码 200(OK),并且返回的内容是否包含字符串 "Ansible-managed"。这自动化了你一直在手动进行的 curlgrep 检查。
  3. 复制并粘贴下面完整的 apache.yml Playbook 内容,该内容现在包含两个 Play:

    ---
    - name: Install and start Apache web server
      hosts: webservers
      become: true
      tasks:
        - name: Install httpd package
          ansible.builtin.dnf:
            name: httpd
            state: present
    
        - name: Deploy custom index.html
          ansible.builtin.copy:
            src: index.html
            dest: /var/www/html/index.html
    
        - name: Start and enable httpd service
          ansible.builtin.service:
            name: httpd
            state: started
            enabled: true
    
    - name: Test web server from localhost
      hosts: localhost
      become: false
      tasks:
        - name: Verify web server is serving correct content
          ansible.builtin.uri:
            url: http://localhost
            return_content: yes
            status_code: 200
          register: result
          failed_when: "'Ansible-managed' not in result.content"

    保存文件并退出 nanoCtrl+OEnterCtrl+X)。

  4. 运行完整的 Playbook。Ansible 将执行第一个 Play,发现所有任务都已处于其目标状态(ok),然后继续执行第二个 Play 来运行测试。

    ansible-playbook apache.yml

    输出将显示两个 Play 的执行情况。所有任务都应成功完成,状态为 ok

    PLAY [Install and start Apache web server] *************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Install httpd package] ***************************************************
    ok: [localhost]
    
    TASK [Deploy custom index.html] ************************************************
    ok: [localhost]
    
    TASK [Start and enable httpd service] ******************************************
    ok: [localhost]
    
    PLAY [Test web server from localhost] ******************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [Verify web server is serving correct content] ****************************
    ok: [localhost]
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=6    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

通过添加第二个 Play,你创建了一个更健壮的自动化工作流,该工作流不仅配置了服务,还包含了一个内置测试来验证部署是否成功。

总结

在本实验中,你学习了如何通过安装 ansible-core 包和构建项目目录来准备 RHEL 环境以进行 Ansible 自动化。你创建了一个基础的静态 inventory 文件来定义一组托管节点,指定了使用本地连接的 localhost。你还使用 ansible.cfg 文件配置了 Ansible 环境,使其指向你的自定义 inventory,从而为运行 Playbook 建立了一个干净且有组织的 workspace。

然后,你编写了一个全面的 Ansible Playbook 来自动化 Apache Web 服务器的部署。这包括使用 ansible.builtin.dnf 模块编写安装 httpd 包的任务,以及使用 ansible.builtin.service 模块确保服务已启动并启用。该 Playbook 通过使用 ansible.builtin.copy 模块部署自定义的 index.html 网页进行了增强。最后,你在同一个 Playbook 中实现了第二个 Play 来验证部署,使用 ansible.builtin.uri 模块测试与新部署的 Web 服务器的连接性,展示了一个完整的设置和验证工作流。