Skip to content

Latest commit

 

History

History
616 lines (424 loc) · 28.9 KB

File metadata and controls

616 lines (424 loc) · 28.9 KB

十三、负责系统管理

在本章中,我们将探讨数千名网络和系统工程师使用的一种流行自动化框架Ansible,Ansible 用于通过 SSH、Netconf 和 API 等多种传输协议管理服务器和网络设备,以提供可靠的基础设施。

我们将首先学习 ansible 中使用的术语,如何构建包含基础设施访问详细信息的清单文件,使用条件、循环和模板渲染等功能构建健壮的 ansible 剧本。

Ansible 属于软件配置管理类;它用于管理多个不同设备和服务器上的配置生命周期,确保在所有设备和服务器上应用相同的步骤,并帮助创建作为代码(IaaC)环境的基础架构。

本章将介绍以下主题:

  • Ansible 及其术语
  • 在 Linux 上安装 Ansible
  • 在特别模式下使用 Ansible
  • 创建您的第一个剧本
  • 了解 Ansible 条件、处理程序和循环
  • 处理可解释的事实
  • 使用 Ansible 模板

易懂术语

Ansible 是一个自动化工具和一个完整的框架,它提供了一个基于 Python 工具的抽象层。最初,它设计用于处理任务自动化。此任务可以在单个服务器上执行,也可以在数千台服务器上执行,ansible 将毫无问题地处理它们;后来,Ansible 的业务范围扩展到网络设备和云提供商。Ansible 遵循idempotency的概念,其中 Ansible 指令可以多次运行同一任务,并始终在所有设备上提供相同的配置,以最小的更改达到所需的状态。例如,如果我们运行 Ansible 将文件上载到特定的服务器组,然后再次运行它,Ansible 将首先验证该文件是否已存在于远程目标中,从而导致以前的执行。如果它存在,ansible 将不会上载它

再一次该特征称为幂等性

Ansible 的另一个方面是它是无代理的。Ansible 在运行任务之前不需要在服务器中安装任何代理。它利用 SSH 连接和 Python 标准库在远程服务器上执行任务,并将输出返回到 Ansible 服务器。此外,它不创建用于存储远程机器信息的数据库,而是依赖一个名为inventory的平面文本文件来存储所有必需的服务器信息,如 IP 地址、凭据和基础结构分类。以下是简单清单文件的示例:

[all:children]
web-servers
db-servers

[web-servers]
web01 Ansible_ssh_host=192.168.10.10

[db-servers]
db01 Ansible_ssh_host=192.168.10.11
db02 Ansible_ssh_host=192.168.10.12

[all:vars]
Ansible_ssh_user=root
Ansible_ssh_pass=access123

[db-servers:vars]
Ansible_ssh_user=root
Ansible_ssh_pass=access123
[local]
127.0.0.1 Ansible_connection=local Ansible_python_interpreter="/usr/bin/python"

请注意,我们将在基础架构中执行相同功能的服务器(例如数据库服务器,在一个名为[db-servers]的组中;对于[web-servers]也是如此)组合在一起。然后,我们定义一个称为[all]的特殊组,它将两个组结合起来,以防我们有一个针对所有服务器的任务。

[all:children]中的关键字children表示组内的条目也是包含主机的组。

Ansible 的即席模式允许用户直接从终端执行任务,指向远程服务器。假设您希望更新特定类型服务器(如数据库或 web 后端服务器)上的特定包,以解决新的 bug。同时,您也不希望为了执行简单的任务而开发复杂的剧本。通过利用 Ansible 中的即席模式,您可以通过在 Ansible 主机终端上键入命令在远程服务器上执行任何命令。甚至一些模块可以在终端中执行;我们将在中的部分中看到,在特别模式下使用 Ansible。

在 Linux 上安装 Ansible

Ansible 包在所有主要的 Linux 发行版上都可用。在本节中,我们将把它安装到 Ubuntu 和 CentOS 机器上。Ansible 2.5 版本是在开发本书时使用的,它同时支持 Python2.6 和 Python2.7。此外,从 2.2 版开始,Ansible 提供了 Python 3.5+的技术预览。

论 RHEL 与 CentOS

在安装 Ansible 之前,您需要安装并启用 EPEL 存储库。要执行此操作,请使用以下命令:

sudo yum install epel-release

然后,继续安装 Ansible 软件包,如以下命令所示:

sudo yum install Ansible

Ubuntu

首先,确保您的系统是最新的,并添加 Ansible 频道。最后,安装 Ansible 软件包本身,如以下代码段所示:

$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:Ansible/Ansible
$ sudo apt-get update
$ sudo apt-get install Ansible

欲了解更多安装风格,请访问 Ansible 官方网站(http://docs.Ansible.com/Ansible/latest/installation_guide/intro_installation.html?#installing-控制机器)。

您可以通过运行Ansible --version检查安装的版本来验证您的安装:

The Ansible configuration files are usually stored in /etc/Ansible, with the filename Ansible.cfg.

在特别模式下使用 Ansible

当您需要在远程机器上执行简单操作,而不创建复杂和持久的任务时,可以使用 Ansible 即席模式。这是用户通常在第一次使用 Ansible 时开始的地方,然后在剧本中执行高级任务。

执行 ad-hoc 命令需要两件事。首先,您需要清单文件中的主机或组;其次,您需要针对目标机器执行 Ansible 模块:

  1. 首先,让我们定义主机,并将 CentOS 和 Ubuntu 机器添加到一个单独的组中:
[all:children]
centos-servers
ubuntu-servers

[centos-servers]
centos-machine01 Ansible_ssh_host=10.10.10.193

[ubuntu-servers]
ubuntu-machine01 Ansible_ssh_host=10.10.10.140

[all:vars]
Ansible_ssh_user=root
Ansible_ssh_pass=access123

[centos-servers:vars]
Ansible_ssh_user=root
Ansible_ssh_pass=access123

[ubuntu-servers:vars]
Ansible_ssh_user=root
Ansible_ssh_pass=access123

[routers]
gateway ansible_ssh_host = 10.10.88.110 ansible_ssh_user=cisco ansible_ssh_pass=cisco

[local]
127.0.0.1 Ansible_connection=local Ansible_python_interpreter="/usr/bin/python"
  1. 将此文件保存为hosts,保存在/root/下,或保存在AutomationServer中您的主目录下。
  2. 然后,使用ping模块运行Ansible命令:
# Ansible -i hosts all -m ping

-i参数将接受我们添加的清单文件,-m参数将指定 Ansible 模块的名称。

运行该命令后,您将获得以下输出,指示连接到远程计算机时出现故障:

ubuntu-machine01 | FAILED! => {
 "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host."
}
centos-machine01 | FAILED! => {
 "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host."
}

这是因为远程机器不在 Ansible 服务器的known_hosts内;它可以通过两种方法来解决。

第一种方法是手动对它们进行 SSHing,这将向服务器添加主机指纹。或者,您可以在 Ansible 配置中完全禁用主机密钥检查,如以下代码段所示:

sed -i -e 's/#host_key_checking = False/host_key_checking = False/g' /etc/Ansible/Ansible.cfg

sed -i -e 's/#   StrictHostKeyChecking ask/   StrictHostKeyChecking no/g' /etc/ssh/ssh_config

重新运行Ansible命令,三台机器输出成功:

127.0.0.1 | SUCCESS => {
 "changed": false, 
 "ping": "pong"
}
ubuntu-machine01 | SUCCESS => {
 "changed": false, 
 "ping": "pong"
}
centos-machine01 | SUCCESS => {
 "changed": false, 
 "ping": "pong"
}

The ping module in Ansible does not perform the ICMP operation against the device. It actually tries to log in to the device by using the SSH with provided credentials; if the login succeeds, it will return the pong keyword to the Ansible host.

另一个有用的模块是aptyum,用于在 Ubuntu 或 CentOS 服务器上管理软件包。以下示例将在 Ubuntu 机器上安装apache2包:

# Ansible -i hosts ubuntu-servers -m apt -a "name=apache2 state=present" 

apt模块中的状态可以有以下值:

| 状态 | 动作 | | absent | 从系统中删除包。 | | present | 确保该软件包已安装在系统上。 | | latest | 确保软件包为最新版本。 |

您可以通过运行Ansible-doc <module_name>访问 Ansible 模块文档;您将看到模块的完整选项和示例。

service模块用于管理服务的操作和当前状态。您可以在state选项中将服务状态更改为startedrestartedstopped,ansible 将运行相应的命令来更改状态。同时,您可以通过配置enabled来配置服务是在引导时启用还是禁用。

#Ansible -i hosts centos-servers -m service -a "name=httpd state=stopped, enabled=no"

您还可以通过提供服务名称来重新启动服务,state设置为restarted

#Ansible -i hosts centos-servers -m service -a "name=mariadb state=restarted"

在即席模式下运行 Ansible 的另一种方法是直接将命令传递给 Ansible,而不是使用内置模块,而是使用-a参数:

#Ansible -i hosts all -a "ifconfig"

您甚至可以通过运行reboot命令重新启动服务器;但这一次,我们将只在 CentOS 服务器上运行它:

#Ansible -i hosts centos-servers -a "reboot"

有时,您需要使用其他用户运行命令(或模块)。当您在远程服务器上运行脚本并将特定权限分配给不同于 SSH 用户的用户时,这将非常有用。在这种情况下,我们将添加-u--become--ask-become-pass-K开关。这将使 Ansible 使用提供的用户名运行命令,并提示您输入用户密码:

#Ansible -i hosts ubuntu-servers --become-user bassim  --ask-become-pass -a "cat /etc/sudoers"

Ansible 的实际工作原理

Ansible 基本上是用 Python 编写的,但是它使用自己的 DSL(领域特定语言)。您可以使用此 DSL 进行编写,ansible 将在远程机器上将其转换为 Python 以执行任务。因此,它首先验证任务语法并将模块从 Ansible 主机复制到远程服务器,然后通过 SSH 在机器上执行。

执行的结果以json格式返回给 Ansible 主机,因此您可以通过知道其键来匹配任何返回值:

对于在网络操作系统)上安装 Python 的网络设备,Ansible 使用 API 或netconf(如果网络设备支持)(如 Juniper 和 Cisco Nexus);或者,它只是使用 paramikoexec_command()函数执行命令,并将输出返回给 Ansible 主机。这可以通过使用raw模块来完成,如以下代码段所示:

# Ansible -i hosts routers -m raw -a "show arp" 
gateway | SUCCESS | rc=0 >>

Sat Apr 21 01:33:58.391 CAIRO

Address         Age        Hardware Addr   State      Type  Interface
85.54.41.9         -          45ea.2258.d0a9  Interface  ARPA  TenGigE0/2/0/0
10.88.18.1      -          d0b7.428b.2814  Satellite  ARPA  TenGigE0/2/0/0
192.168.100.1   -          00a7.5a3b.4193  Interface  ARPA  GigabitEthernet100/0/0/9
192.168.100.2   02:08:03   fc5b.3937.0b00  Dynamic    ARPA  \

创建您的第一个剧本

现在魔术派对可以开始了。Ansible playbook 是一组需要按顺序执行的命令(称为任务),它描述了执行完成后主机的所需状态。将剧本视为一本手册,其中包含一组关于如何更改基础设施状态的说明;每个指令都依赖于许多内置的 Ansible 模块来执行任务。例如,您可能有一个剧本,用于构建由 SQL Server 组成的 web 应用程序,充当后端数据库和 nginx web 服务器。如果您想删除 web 应用程序,playbook 将有一个针对每组服务器执行的任务列表,将其状态从No-Exist更改为Present,或更改为RestartedAbsent

拥有 playbook 而不是临时命令的威力在于,您可以使用它在任何地方配置和设置基础设施。用于创建开发环境的相同过程将在生产环境中使用。playbook 用于创建在基础架构上运行的自动化工作流:

剧本是用 YAML 编写的,我们在第 6 章配置生成器中用 Python 和 Jinja2讨论了这一点。剧本由多个剧本组成,针对清单文件中定义的一组主机执行。主机将被转换为 Pythonlist,列表中的每个项目将被称为play。在上例中,db-servers任务是一些重头戏,仅针对db-servers执行。在 playbook 执行期间,您可以决定运行文件中的所有播放,仅运行特定播放,或运行具有特定标记的任务,而不管它们属于哪个播放。

现在,让我们看一下我们的第一个剧本,以了解它的外观和感觉:

- hosts: centos-servers
  remote_user: root

  tasks:
    - name: Install openssh
      yum: pkg=openssh-server state=installed

    - name: Start the openssh
      service: name=sshd state=started enabled=yes

这是一个简单的剧本,一个play包含两个tasks

  1. 安装openssh-server
  2. 安装后启动sshd服务,并确保在引导时可用。

现在,我们需要将其应用于特定主机(或一组主机)。因此,我们将hosts设置为CentOS-servers,这是之前在库存文件中定义的,并且我们还将remote_user设置为根目录,以确保它之后的任务将以根目录权限执行。

任务将由名称和 Ansible 模块组成。该名称用于描述任务。为任务提供名称不是强制性的,但建议您这样做,以防您需要从特定任务开始执行。

第二部分是 Ansible 模块,它是强制性的。在我们的示例中,我们使用核心模块yumopenssh-server包安装到目标服务器上。第二个任务具有相同的结构,但这次,我们将使用另一个名为service的核心模块来启动并启用sshd守护进程。

最后一个注意事项是观察 Ansible 内部不同组件的缩进。例如,任务的名称应该在同一级别,而tasks应该与同一行上的hosts对齐。

让我们在自动化服务器中运行 playbook 并检查输出:

#Ansible-playbook -i hosts first_playbook.yaml 

PLAY [centos-servers] **********************************************************************

TASK [Gathering Facts] *********************************************************************
ok: [centos-machine01]

TASK [Install openssh] *********************************************************************
ok: [centos-machine01]

TASK [Start the openssh] *******************************************************************
ok: [centos-machine01]
PLAY RECAP *********************************************************************************
centos-machine01           : ok=3    changed=0    unreachable=0    failed=0   

您可以看到剧本是在centos-machine01上执行的,任务是按剧本中的定义顺序执行的。

YAML requires that you preserve the indentation level and don't mix between the tabs and spaces; otherwise, it will give an error. Many text editors and IDEs will convert the tab to a set of white spaces. An example of that option is shown in the following screenshot, in the notepad++ editor preferences:

了解 Ansible 条件、处理程序和循环

在本章的这一部分,我们将了解 Ansible 剧本中的一些高级功能。

设计条件

Ansible playbook 可以根据任务内部特定条件的结果执行任务(或跳过任务),例如,当您希望在特定的操作系统系列(Debian 或 CentOS)上安装软件包时,或当操作系统是特定版本时,甚至当远程主机是虚拟的而不是裸机时。这可以通过在任务内部使用when子句来完成。

让我们对之前的 playbook 进行改进,并将openssh-server安装限制在基于 CentOS 的系统上,这样当它击中使用apt模块而不是yum模块的 Ubuntu 服务器时,就不会出现错误。

首先,我们将在inventory文件中添加以下两个部分,将 CentOS 和 Ubuntu 机器分组到infra部分:

[infra:children]
centos-servers
ubuntu-servers

[infra:vars]
Ansible_ssh_user=root
Ansible_ssh_pass=access123

然后,我们将重新设计 playbook 中的任务,使其具有when子句,该子句将任务执行限制为仅基于 CentOS 的机器。这应理解为if the remote machine is CentOS based, then I will execute the task; otherwise, skip

- hosts: infra
  remote_user: root

  tasks:
    - name: Install openssh
      yum: pkg=openssh-server state=installed
      when: Ansible_distribution == "CentOS"

    - name: Start the openssh
      service: name=sshd state=started enabled=yes
      when: Ansible_distribution == "CentOS"

让我们运行剧本:

# Ansible-playbook -i hosts using_when.yaml 

PLAY [infra] *******************************************************************************

TASK [Gathering Facts] *********************************************************************
ok: [centos-machine01]
ok: [ubuntu-machine01]

TASK [Install openssh] *********************************************************************
skipping: [ubuntu-machine01]
ok: [centos-machine01]

TASK [Start the openssh] *******************************************************************
skipping: [ubuntu-machine01]
ok: [centos-machine01]

PLAY RECAP *********************************************************************************
centos-machine01           : ok=3    changed=0    unreachable=0    failed=0 
ubuntu-machine01           : ok=1    changed=0    unreachable=0    failed=0  

请注意,剧本首先收集有关远程机器的事实(我们将在本章后面讨论),然后检查操作系统。当任务点击ubuntu-machine01时,将跳过该任务,该任务将在 CentOS 上正常运行。

为了运行任务,您还可以有多个需要为真的条件。例如,您可以使用以下 playbook,它首先验证两件事,即机器基于 Debian,其次验证它是虚拟机,而不是纯金属:

- hosts: infra
  remote_user: root

  tasks:
    - name: Install openssh
      apt: pkg=open-vm-tools state=installed
      when:
        - Ansible_distribution == "Debian"
        - Ansible_system_vendor == "VMware, Inc."

运行此剧本将产生以下输出:

# Ansible-playbook -i hosts using_when_1.yaml 

PLAY [infra] *******************************************************************************

TASK [Gathering Facts] *********************************************************************
ok: [centos-machine01]
ok: [ubuntu-machine01]

TASK [Install openssh] *********************************************************************
skipping: [centos-machine01]
ok: [ubuntu-machine01]

PLAY RECAP *********************************************************************************
centos-machine01           : ok=1    changed=0    unreachable=0    failed=0
ubuntu-machine01           : ok=2    changed=0    unreachable=0    failed=0 

Ansiblewhen子句也接受表达式。例如,您可以检查返回的输出(使用 register 标志保存的输出)中是否存在特定关键字,并在此基础上执行任务。

以下剧本将验证 OSPF 邻居状态。第一个任务将在路由器上执行show ip ospf neighbor,并将输出注册到名为neighbors的变量中。下一个任务将检查返回的输出中是否有EXSTARTEXCHANGE;如果找到,它会将消息打印回控制台:

hosts: routers

tasks:
  - name: "show the ospf neighbor status"
    raw: show ip ospf neighbor
    register: neighbors

  - name: "Validate the Neighbors"
    debug:
      msg: "OSPF neighbors stuck"
    when: ('EXSTART' in neighbors.stdout) or ('EXCHANGE' in neigbnors.stdout)

您可以在查看when条款中常用的事实 http://docs.Ansible.com/Ansible/latest/user_guide/playbooks_conditionals.html#commonly-使用事实

在 ansible 中创建循环

Ansible 提供了许多方法来在游戏中重复相同的任务,但每次都有不同的值。例如,当您想在服务器上安装多个软件包时,不需要为每个软件包创建任务。相反,您可以创建一个任务来安装一个包,并为该任务提供一个包名列表,Ansible 将对它们进行迭代,直到完成安装。为了实现这一点,我们需要在包含列表的任务内部使用with_items标志,并使用变量{{ item }},它作为列表中项目的占位符。playbook 将利用with_items标志迭代一组包,并将它们提供给yum模块,该模块需要包的名称和状态:

- hosts: infra
  remote_user: root

  tasks:
    - name: "Modifying Packages"
      yum: name={{ item.name }} state={{ item.state }}
      with_items:
        - { name: python-keyring-5.0-1.el7.noarch, state: absent }
        - { name: python-django, state: absent }
        - { name: python-django-bash-completion, state: absent }
        - { name: httpd, state: present }
        - { name: httpd-tools, state: present }
        - { name: python-qpid, state: present }
      when: Ansible_distribution == "CentOS"

可以将状态值硬编码为present;在这种情况下,将安装所有软件包。但是,在前一种情况下,with_items将向yum模块提供这两个元素。

剧本的输出如下:

使用处理程序触发任务

可以您已经在系统中安装和删除了一系列软件包。您已将文件复制到服务器或从服务器复制文件。通过使用 Ansible playbook,您已经改变了服务器中的许多内容。现在,您需要重新启动一些其他服务,或者在文件中添加一些行,以完成服务的配置。所以,您应该添加一个新任务,对吗?是的,没错。然而,Ansible 提供了另一个很棒的选项,称为处理程序,它不会在命中时自动执行(与任务不同),而是只在调用时执行。这为您提供了在执行游戏中的任务时调用它们的灵活性。

处理程序与主机和任务具有相同的对齐方式,并且位于每个播放的底部。当需要调用处理程序时,使用原始任务内部的notify标志来确定将执行哪个处理程序;Ansible 将把它们联系在一起。

让我们看一个例子。我们将编写一个剧本,在 CentOS 服务器上安装和配置 KVM。KVM 在安装后需要进行一些更改,例如加载sysctl,启用kvm802.1q模块,以及在boot加载kvm

- hosts: centos-servers
  remote_user: root

  tasks:
    - name: "Install KVM"
      yum: name={{ item.name }} state={{ item.state }}
      with_items:
        - { name: qemu-kvm, state: installed }
        - { name: libvirt, state: installed }
        - { name: virt-install, state: installed }
        - { name: bridge-utils, state: installed }

      notify:
        - load sysctl
        - load kvm at boot
        - enable kvm

  handlers:
    - name: load sysctl
      command: sysctl -p

    - name: enable kvm
      command: "{{ item.name }}"
      with_items:
        - {name: modprobe -a kvm}
        - {name: modprobe 8021q}
        - {name: udevadm trigger}

    - name: load kvm at boot
      lineinfile: dest=/etc/modules state=present create=True line={{ item.name }}
      with_items:
        - {name: kvm}

安装任务完成后注意notify的用法。当任务运行时,它将依次通知三个处理程序,以便它们执行。处理程序将在任务成功执行后运行。这意味着,如果任务无法运行(例如,找不到kvm包,或者没有 internet 连接来下载它),系统将不会发生任何更改,并且kvm将不会启用。

处理程序的另一个很棒的特性是,它只在任务发生更改时运行。例如,如果重新运行任务,Ansible 将不会安装kvm包,因为它已经安装;它不会调用任何处理程序,因为它不会检测到系统中的任何更改。

我们将添加关于两个模块的最后说明:lineinfilecommand。第一个模块实际上是使用正则表达式从配置文件中插入或删除行;我们使用它是为了将kvm插入/etc/modules,在机器启动时自动引导 KVM。第二个模块command用于直接在设备上执行 shell 命令,并将输出返回给 Ansible 主机。

处理可解释的事实

Ansible 不仅用于部署和配置远程主机。它可以用来收集关于他们的各种信息和事实。事实收集可能需要大量时间来收集繁忙系统中的所有信息,但将提供目标机器的完整视图。

收集到的事实可以在以后的剧本中用于设计任务条件。例如,我们使用when条款将openssh安装限制为仅基于 CentOS 的系统:

when: Ansible_distribution == "CentOS"

您可以在与主机和任务相同的级别上配置gather_facts来启用/禁用 Ansible plays 中的事实收集:

- hosts: centos-servers
  gather_facts: yes
  tasks:
    <your tasks go here>

另一种收集事实并在 Ansible 中打印的方法是在特别模式下使用setup模块。返回的结果以嵌套字典和列表的形式出现,用于描述远程目标事实,例如服务器体系结构、内存、网络设置、操作系统版本等:

#Ansible -i hosts ubuntu-servers -m setup | less 

您可以使用点符号或方括号从事实中获得特定值。例如,要获取eth0的 IPv4 地址,可以使用Ansible_eth0["ipv4"]["address"]Ansible_eth0.ipv4.address

使用 Ansible 模板

使用 Ansible 的最后一步是了解它如何处理模板。Ansible 使用了 Jinja2 模板,我们在第 6 章配置生成器以及 Python 和 Jinja2中讨论了该模板。它使用 Ansible facts 或vars部分中提供的静态值填充参数,甚至使用使用register标志存储的任务结果填充参数。

在下面的示例中,我们将构建一个 Ansible playbook,它收集前面三个案例。首先,我们在vars部分定义一个名为Header的变量,将欢迎消息作为静态值保存。然后,我们启用gather_facts标志,从目标机器获取所有可能的信息。最后,我们执行date命令,获取服务器中的当前日期,并将输出存储在date_now变量中:

- hosts: centos-servers
  vars:
    - Header: "Welcome to Server facts page generated from Ansible playbook"
  gather_facts: yes
  tasks:
    - name: Getting the current date
      command: date
      register: date_now
    - name: Setup webserver
      yum: pkg=nginx state=installed
      when: Ansible_distribution == "CentOS"

      notify:
        - enable the service
        - start the service

    - name: Copying the index page
      template: src=index.j2 dest=/usr/share/nginx/html/index.html

  handlers:
    - name: enable the service
      service: name=nginx enabled=yes

    - name: start the service
      service: name=nginx state=started

在前面的剧本中使用的模板模块将接受一个名为index.j2的 Jinja2 文件,该文件位于剧本的同一目录中;然后,它将提供我们前面讨论过的三个来源的 jinj2 变量的所有值。然后,渲染文件将存储在模板模块内的dest选项提供的路径中。

index.j2的内容如下。它将是一个简单的 HTML 页面,利用 jinja2 语言生成最终的 HTML 页面:

<html>
<head><title>Hello world</title></head>
<body>

<font size="6" color="green">{{ Header }}</font>

<br>
<font size="5" color="#ff7f50">Facts about the server</font>
<br>
<b>Date Now is:</b> {{ date_now.stdout }}

<font size="4" color="#00008b">
<ul>
    <li>IPv4 Address: {{ Ansible_default_ipv4['address'] }}</li>
    <li>IPv4 gateway: {{ Ansible_default_ipv4['gateway'] }}</li>
    <li>Hostname: {{ Ansible_hostname }}</li>
    <li>Total Memory: {{ Ansible_memtotal_mb }}</li>
    <li>Operating System Family: {{ Ansible_os_family }}</li>
    <li>System Vendor: {{ Ansible_system_vendor }}</li>
</ul>
</font>
</body>
</html>

运行此 playbook 将导致在 CentOS 机器上安装 nginx web 服务器,并在其中添加一个index.html页面。您可以使用浏览器访问该页面:

您还可以利用模板模块生成网络设备配置。第 6 章配置生成器使用 Python 和生成路由器day0day1配置的 jinja2 模板可以在 Ansible playbook 中重用。

总结

Ansible 是一个非常强大的工具,用于自动化 IT 基础架构。它包含许多模块和库,几乎涵盖了系统和网络自动化中的所有内容,使得软件部署、包管理和配置管理非常容易。虽然 Ansible 可以在特别模式下执行单个模块,但 Ansible 的真正力量在于编写和开发剧本。