在本文中,您将学习如何创建 Ansible 剧本。作为练习,您将在两台目标计算机上安装 Apache Web 服务器并更改欢迎页面。

一、简介

一、简介

在前两篇 Ansible 博文中,您学习 了如何设置 Ansible 测试环境以及 如何创建 Ansible 清单。这篇文章是这个系列的延续,但没有必要阅读前两篇文章。在本文中,您将学习如何创建 Ansible 剧本。剧本由执行任务的一个或多个剧本组成。这些任务调用 Ansible 模块。如果您还不了解这一点,请不要担心,这就是您将要学习的内容。还建议阅读 Ansible 文档中的剧本介绍。

如果您没有阅读之前的博客或仅作为提醒,该环境由一台控制器和两台 Target 机器组成。Controller 和 Target 机器在 VirtualBox VM 中运行。Ansible 脚本的开发是在主机上使用 IntelliJ 完成的。这些文件通过脚本从主机同步到控制器。在这个博客中,机器有以下 IP 地址:

  1. 控制器:192.168.2.11
  2. 目标 1:192.168.2.12
  3. 目标 2:192.168.2.13

本博客中使用的文件可在 GitHub 上相应的 git 存储库中找到。

2.先决条件

2.先决条件

以下先决条件适用于此博客:

  1. 你需要一个Ansible测试环境,看 之前的一篇博客如何搭建测试环境;
  2. 您需要具备 Ansible Inventory 和 Ansible Vault 的基础知识, 如果您没有这方面的知识,请参阅之前的博客;
  3. 如果您使用自己的环境,您应该知道 Ubuntu 22.04 LTS 用于 Controller 和 Target 机器以及 Ansible 版本 2.13.3;
  4. 基本的 Linux 知识。
3. 你的第一本剧本

3. 你的第一本剧本

作为第一个 playbook,您将创建一个 playbook,它将 ping Target1 和 Target2 机器。该剧本可以在 git 存储库中找到playbook-ping-targets-success.yml,如下所示:

- name: Ping target1

hosts: target1
tasks:
- name: Ping test
ansible.builtin.ping:
- name: Ping target2
hosts: target2
tasks:
- name: Ping test
ansible.builtin.ping:

让我们看看这个剧本是什么样子的。剧本由剧本组成。在这个剧本中,可以找到名称 Ping target1和 两个剧本Ping target2。hosts对于每个剧本,您可以通过引用清单文件中的名称的参数来指示它需要在何处运行 。

剧本由任务组成。在这两个剧本中,只有一个任务是用 name 定义的 Ping test。

任务调用 Ansible 模块。可以在此处找到可以使用的模块列表 。了解存在哪些模块、如何找到它们、如何使用它们等非常重要。Ping 模块的文档 是本示例所需要的,因此请花点时间看看它。

最后要注意的是,使用了 FQCN(完全合格的集合名称)。这被认为是最佳实践。

从 Controller 机器运行 playbook。如果您按原样使用 git 存储库中的文件,则需要输入保管库密码,即itisniceweather.

$ ansible-playbook playbook-ping-targets-success.yml -i inventory/inventory.ini --ask-vault-pass
Vault password:
PLAY [Ping target1] ***********************************************************************************************
TASK [Gathering Facts] ********************************************************************************************
ok: [target1]
TASK [Ping test] **************************************************************************************************
ok: [target1]
PLAY [Ping target2] ***********************************************************************************************
TASK [Gathering Facts] ********************************************************************************************
ok: [target2]
TASK [Ping test] **************************************************************************************************
ok: [target2]
PLAY RECAP ********************************************************************************************************
target1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
target2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

日志记录准确显示执行了哪些播放和哪些任务,以及它们是否执行成功。

Ping 模块还提供了使命令崩溃的选项。在Target1播放中,data为了让命令崩溃,添加了参数。该剧本可以在 git 存储库中找到,格式为playbook-ping-targets-failure.yml.- name: Ping target1

hosts: target1
tasks:
- name: Ping test
ansible.builtin.ping:
data: crash
...

执行此 playbook 将使 Target1 play 崩溃并且该 playbook 刚刚结束。

$ ansible-playbook playbook-ping-targets-failure.yml -i inventory/inventory.ini --ask-vault-pass
Vault password:
PLAY [Ping target1] ***********************************************************************************************
TASK [Gathering Facts] ********************************************************************************************
ok: [target1]
TASK [Ping test] **************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: Exception: boom
fatal: [target1]: FAILED! => {"changed": false, "module_stderr": "Shared connection to 192.168.2.12 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/osboxes/.ansible/tmp/ansible-tmp-1662800777.2553337-6094-259627128894774/AnsiballZ_ping.py\", line 107, in \r\n _ansiballz_main()\r\n File \"/home/osboxes/.ansible/tmp/ansible-tmp-1662800777.2553337-6094-259627128894774/AnsiballZ_ping.py\", line 99, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File \"/home/osboxes/.ansible/tmp/ansible-tmp-1662800777.2553337-6094-259627128894774/AnsiballZ_ping.py\", line 47, in invoke_module\r\n runpy.run_module(mod_name='ansible.modules.ping', init_globals=dict(_module_fqn='ansible.modules.ping', _modlib_path=modlib_path),\r\n File \"/usr/lib/python3.10/runpy.py\", line 209, in run_module\r\n return _run_module_code(code, init_globals, run_name, mod_spec)\r\n File \"/usr/lib/python3.10/runpy.py\", line 96, in _run_module_code\r\n _run_code(code, mod_globals, init_globals,\r\n File \"/usr/lib/python3.10/runpy.py\", line 86, in _run_code\r\n exec(code, run_globals)\r\n File \"/tmp/ansible_ansible.builtin.ping_payload_xnphtwh8/ansible_ansible.builtin.ping_payload.zip/ansible/modules/ping.py\", line 89, in \r\n File \"/tmp/ansible_ansible.builtin.ping_payload_xnphtwh8/ansible_ansible.builtin.ping_payload.zip/ansible/modules/ping.py\", line 79, in main\r\nException: boom\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
PLAY RECAP ********************************************************************************************************

target1 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0

4. 安装 Apache 网络服务器

4. 安装 Apache 网络服务器

在第二个练习中,您将在目标机器上安装 Apache Webserver 并更改欢迎页面。最终的剧本可以在 git 存储库中找到,格式为 playbook-httpd-target1.yml. 您将在本节中学习如何创建此最终版本。

4.1 安装包

4.1 安装包

要安装软件包,您可以使用 Apt 模块。它包含许多参数,您只会使用其中的几个:

  1. name:要安装的包的名称;
  2. update_cache: apt-get update在安装之前运行;
  3. state:表示所需的包状态, present在这里就好了。

这个剧本中的其他项目现在应该已经很熟悉了。

- name: Install Apache webserver
hosts: target1
tasks:
- name: Install apache httpd (state=present is optional)
ansible.builtin.apt:
name: apache2
update_cache: yes
state: present

运行剧本。

$ ansible-playbook playbook-httpd-target1.yml -i inventory/inventory.ini --ask-vault-pass
Vault password:
PLAY [Install Apache webserver] *****************************************************************************************
TASK [Gathering Facts] **************************************************************************************************
ok: [target1]
TASK [Install apache httpd (state=present is optional)] ****************************************************************

这本剧本并没有结束。它挂起,您可以使用 CTRL+C 停止它。

那么这里发生了什么?您可能知道,为了安装软件包,您需要 sudo 权限。不管怎样,Ansible 需要知道是否需要提升权限,并且您需要向 Ansible 提供 sudo 密码。可以在 Ansible 文档中阅读详细说明。简短的版本是,您需要添加 become带有 value 的参数 yes。但这还不是全部,您还需要 --ask-become-pass在运行 Ansible playbook 时添加命令行参数。这样,Ansible 将要求您提供 sudo 密码。

添加了参数的剧本become如下所示:

- name: Install Apache webserver
hosts: target1
become: yes
tasks:
- name: Install apache httpd (state=present is optional)
ansible.builtin.apt:
name: apache2
update_cache: yes
state: present

运行此剧本成功。如您所见,需要输入 become 密码和 vault 密码。

$ ansible-playbook playbook-httpd-target1.yml -i inventory/inventory.ini --ask-vault-pass --ask-become-pass
BECOME password:
Vault password:
PLAY [Install Apache webserver] ****************************************************************************************
TASK [Gathering Facts] *************************************************************************************************
ok: [target1]
TASK [Install apache httpd (state=present is optional)] ***************************************************************
changed: [target1]
PLAY RECAP *************************************************************************************************************

target1 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

在输出日志记录中,您还注意到第 11 行的 Target1 已更改。记住这一点,这在稍后再次运行剧本时很重要。

通过浏览器(或通过 curl 命令)导航到 Target1 机器的 IP 地址:http: //192.16.2.12。如果您有与本博客中使用的测试环境类似的测试环境,则可以从您的主机执行此操作。如您所见,显示了 Apache Web 服务器的默认欢迎页面。

打开网易新闻 查看精彩图片

4.2 更改欢迎页面

4.2 更改欢迎页面

在剧本中,您还可以更改欢迎页面的内容。您可以为此使用复制模块。将以下任务添加到剧本中。

- name: Create index page
ansible.builtin.copy:
content: 'Hello world from target 1'
dest: /var/www/html/index.html

执行剧本。

$ ansible-playbook playbook-httpd-target1.yml -i inventory/inventory.ini --ask-vault-pass --ask-become-pass
BECOME password:
Vault password:
PLAY [Install Apache webserver] ****************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************
ok: [target1]
TASK [Install apache httpd (state=present is optional)] ***************************************************************************************************
ok: [target1]
TASK [Create index page] ***********************************************************************************************************************************
changed: [target1]
PLAY RECAP *************************************************************************************************************************************************
target1 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

首先,仔细查看日志记录。任务Install apache httpd现在只是返回ok而不是changed。这意味着 Ansible 没有再次安装 Apache Webserver。Ansible 任务是幂等的。这意味着您可以一遍又一遍地执行它们,结果将是相同的。另请注意,欢迎页面现已更改。通过浏览器或通过 curl 验证这一点。

$ curl http://192.168.2.12
Hello world from target 1

4.3 安装Target2

4.3 安装Target2

作为最后一个练习,您可以添加第二个步骤以在 Target2 上安装 Apache Webserver 并相应地更改欢迎页面,以便它从 Target2 欢迎您。该剧本可以在 git 存储库中找到,格式为playbook-httpd-target1-and-target2.yml.

- name: Install Apache webserver for target 1
hosts: target1
become: yes
tasks:
- name: Install apache httpd (state=present is optional)
ansible.builtin.apt:
name: apache2
update_cache: yes
state: present
- name: Create index page for target 1
ansible.builtin.copy:
content: 'Hello world from target 1'
dest: /var/www/html/index.html
- name: Install Apache webserver for target2
hosts: target2
become: yes
tasks:
- name: Install apache httpd (state=present is optional)
ansible.builtin.apt:
name: apache2
update_cache: yes
state: present
- name: Create index page for target 2
ansible.builtin.copy:
content: 'Hello world from target 2'
dest: /var/www/html/index.html

执行剧本,您现在有足够的信心自己探索日志记录。

$ ansible-playbook playbook-httpd-target1-and-target2.yml -i inventory/inventory.ini --ask-vault-pass --ask-become-pass
BECOME password:
Vault password:
PLAY [Install Apache webserver for target 1] *****************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************
ok: [target1]
TASK [Install apache httpd (state=present is optional)] *****************************************************************************************************************
ok: [target1]
TASK [Create index page for target 1] ************************************************************************************************************************************
ok: [target1]
PLAY [Install Apache webserver for target2] ******************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************
ok: [target2]
TASK [Install apache httpd (state=present is optional)] *****************************************************************************************************************
changed: [target2]
TASK [Create index page for target 2] ************************************************************************************************************************************
changed: [target2]
PLAY RECAP ***************************************************************************************************************************************************************
target1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
target2 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0

验证欢迎页面是否已正确更改。

$ curl http://192.168.2.12
Hello world from target 1
$ curl http://192.168.2.13
Hello world from target 2

果然不出所料!

5.结论

5.结论

在本文中,您继续学习 Ansible。您学习了有关 Ansible playbook 的基础知识,并编写并执行了将 Apache Webserver 安装到两台目标机器上的 playbook。您现在可以编写自己的剧本并继续学习。