Ansible:自动化引擎

Ansible 是一种自动化和配置工具,可以轻松地使用所需的软件、配置选项甚至内容来配置系统。它是一个用 Python 编写的命令行工具,它使用 SSH 连接来运行这些操作。这意味着您需要做的就是与机器建立可行的 SSH 连接,Ansible 将运行您想要运行的任何操作。Ansible 可以运行单个命令,也可以使用所谓的 playbook 来运行多个命令。Ansible playbook 是用 YAML 编写的,这使得理解它们变得非常容易。

我过去曾尝试使用其他配置工具,如 Puppet 和 Chef,但这些工具总是难以掌握。当我开始使用 Ansible 时,不到 20 分钟我就在服务器上安装和配置软件。Ansible 使用的 YAML 文件可以轻松查看正在发生的事情,并且具有足够的功能来支持一些非常复杂的配置。

安装 Ansible

Ansible 可以通过 Linux 上的 apt 或 yum 包管理器安装,但您需要先设置一些源存储库。如果您使用的是 yum,那么您将需要安装 EPEL 库。要通过 apt 安装,可以使用以下命令。

sudo add-apt-repository ppa:rquillo/ansible
sudo apt-get update
sudo apt-get install ansible

但是,安装 Ansible 的最简单方法是使用 Python easy_install 和 pip 工具。大多数使用 Python 的系统都应该有 easy_install 工具,但如果没有安装它,那么你可以使用 python-setuptools 安装它。

sudo apt-get install python-setuptools

Ansible 实际上是通过 pip Python 包管理器安装的,不应直接通过 easy_install 安装。如果 pip 在您的 Python 版本中尚不可用,您可以使用以下命令获取 pip。

sudo easy_install pip

在安装 Ansible 之前,您可能需要安装几个依赖项,也可以通过 pip 获得。

sudo pip install paramiko PyYAML jinja2 httplib2 markupsafe

然后可以使用以下命令安装 Ansible。

sudo pip install ansible

尝试安装 Ansible 或任何依赖项时,您可能会看到类似以下错误的内容。

src/MD2.c:31:20: fatal error: Python.h: No such file or directory
 
 #include "Python.h"
 
                    ^
 
compilation terminated.

要解决这个问题,您需要安装 python-dev 包。Python.h是 gcc 用来编译 Python 应用程序的头文件,并且需要编译一些依赖项。

sudo apt-get install python-dev

有关安装 Ansible 的更多信息,请参阅 Ansible 安装文档。

库存文件

清单文件告诉 Ansible 在运行命令时需要查看哪些主机。该文件包含一个主机列表,这些主机可以分成多个组,允许对某些服务器执行某些操作。典型的清单文件如下所示。

[webservers]
web1.example.com
web2.example.com
 
[dbservers]
db.example.com

Ansible 有一个全局清单文件,用作所有请求的默认值,通常存储在 /etc/ansible/hosts 位置。使用默认主机文件可能会导致一些混乱,根据我的经验,最好忽略这一点,并为每个项目使用清单文件。您可以告诉 Ansible 在运行命令时您希望使用哪个清单文件。因此最好创建一个名为的文件hosts.ini并将其保存到您的 Ansible 项目中。我将在下一节中介绍运行 Ansible 命令。

清单文件在 Ansible 清单文档中有详细描述。

提供 Ansible 访问

默认情况下,Ansible 将尝试使用 OpenSSH 连接到您的主机。因此,您需要确保库存文件中的所有主机都存在访问密钥(或用户名和密码)。允许访问 Ansible 的最安全方法是使用 ssh 密钥。这些可以通过本地机器上的 ssh 配置来假设,也可以通过清单文件专门发布给服务器。要将 ssh 密钥详细信息传递给主机,请使用 ansible_ssh_user 发出用户并使用 ansible_ssh_private_key_file 传递私钥文件。

[webservers]
web1.example.com ansible_ssh_user=remoteuser ansible_ssh_private_key_file=~/.ssh/privatekey

在您的清单文件中使用 ssh 密钥之前,最好先检查它们是否允许您访问。

如果您绝对需要,您还可以使用 ansible_ssh_user 和 ansible_ssh_pass 参数将用户详细信息和密码发送到清单文件中的主机。这可能是一个很大的安全问题,因此除非您绝对别无选择,否则您不应该这样做。

[webservers]
web1.example.com ansible_ssh_user=root ansible_ssh_pass=password

运行 Ansible

在 Ansible 中要做的最简单的事情是使用“ping”命令。这不会像在 ping 主机时那样通过端口 1 运行通常的 ping 命令。相反,它运行一个 Ansible 进程,该进程登录到远程机器,上传 ping 命令并执行它。这将返回一个字符串“pong”,它是在远程服务器上运行的命令的输出。如果此处返回任何内容,则主机被认为是可行的并通过了测试。在主机上运行 ping 是检查主机是否处于活动状态以及您的 Ansible 设置是否可以访问该主机的好方法。如果 ping 失败,则 Ansible 可能无法访问主机,您需要重新检查连接。

要在hosts.ini文件中的所有主机上运行 ping 命令,请使用以下命令。

ansible --inventory-file=hosts.ini all -m ping

该命令具有以下组件:

  • --inventory-file=hosts.ini:这告诉 Ansible 要使用哪个主机文件。在这种情况下,我们引用了当前目录中名为“hosts.ini”的文件。

  • all:hosts.ini文件可以分成多个部分,这里的“全部”部分是一种引用文件中每个主机的方式,无论它被放入哪个组。在此处传递 'web servers' 或 'dbservers' 将引用该组中的所有服务器。

  • -m ping:-m 告诉 Ansible 我们要在这些主机上运行命令,在这种情况下,我们传递单个参数 'ping'。

要在主机上运行“ls -la”(为了获得目录列表),只需将 ping 更改为 command 以便向server(s).

ansible --inventory-file=hosts.ini all -m command -a "ls -la"

如果您尝试以这种方式使用清单文件并得到类似于以下内容的错误。

ERROR: problem running /path/to/host.ini --list ([Errno 8] Exec format error)

然后您可以尝试删除 ini 文件的可执行状态,因为 Ansible 无法读取该文件,如果它是可执行的。

chmod -x host.ini

这解决了我遇到的错误并允许我继续。

以这种方式通过 Ansible 运行命令称为“ad-hoc”,因为您一次只能运行一个命令。向服务器发出命令的最佳方式是使用 playbook。

剧本

Ansible playbook 是一种在远程服务器上运行命令的更强大(且可重复)的方式。基本思想是您创建一系列书籍,Ansible 将阅读这些书籍并执行这些书籍中描述的操作。Playbooks 是用 YAML 编写的,但语法很容易掌握。

要对所有使用 playbook 的主机重复 ping 命令,请创建一个 playbook 文件(带有 YAML 扩展名)并将以下内容放入其中。这基本上可以为所有给定的主机运行任务中的任何内容,并且与剧本所能获得的一样简单。

---
- hosts: all
  tasks:
  - name: ping all hosts
    action: ping

要运行 Ansible playbook,您需要使用 ansible-playbook 命令,将要使用的 playbook 和包含主机的清单文件传递给它。

ansible-playbookplaybook.yml-i host.ini

剧本 YAML 文件的剖析非常简单。它需要以“---”开头,它是 YAML 语法声明的一部分。在此之后,您需要说明要处理哪些主机,我在上面的示例中使用了“全部”,以便包含清单文件中的每个服务器,但是您可以在此处包含一个或多个组甚至一个主机模式. 主机模式是通过使用正则表达式匹配其名称或 IP 地址来引用一台或多台主机的方法。

Ansible 中有许多可用的模块,ping 可能是最简单的。在开始尝试做任何其他事情之前,我倾向于将 ping 添加到我的许多剧本中,作为对服务器的简单连接检查。有关可用模块的完整列表,请查看 Ansible 文档中的 Ansible 模块列表。

playbook 的一个很好的例子是在设置 Apache 主机时。这很容易做到,但显然需要几个步骤才能启动和运行。以下是在基于 Debian/Ubuntu 的系统上安装 Apache 的剧本示例。

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  tasks:
  - name: ensure apache is at the latest version
    apt: pkg=apache2 state=latest
  - name: ensure apache is running
    service: name=httpd state=started
  - name: write the apache config file
    template: xx_src=httpd.j2 dest=/etc/apache2/httpd.conf
    notify:
    - restart apache
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

上述剧本将执行以下操作:

  • 第一步是使用主机部分在“webservers”组中的清单文件中查找所有服务器。文档的其余部分是主机部分的一部分,因此所有命令、变量和其他操作仅在这些服务器上运行。

  • Apache 服务器配置的一些变量在“vars”部分中设置。

  • 在称为“任务”的部分下定义了一组任务。这具有以下操作:

    • 使用 apt 模块安装 Apache2。

    • 确保 Apache2 服务器正在运行。

    • 将模板(名为 httpd.j2,在当前目录中找到)复制到服务器配置区域。这是一个使用 j2 模板系统的例子,它是 python 的一部分。Ansible 中定义的任何变量都可以通过用双花括号引用来包含在文档中。例如,要包含端口号,您将包含 '{{ http_port }} ' 变量。一旦此作业完成,处理程序“restart apache”也会收到通知。

  • 在重新启动 Apache2 的剧本底部定义了一个处理程序。这可以在剧本过程中通过通知处理程序随时调用。

如果您继续上面的示例以包含 PHP 和 MySQL 之类的内容,那么 Playbook 显然会变得非常复杂。可以使用 include 语句将 playbook 分成多个部分,但组织 playbook 的最佳方法是使用角色和标签。角色和标签允许您将剧本分成不同的配置和功能部分,并使管理不同主机上的不同软件需求变得更加容易。

要将上面的示例更改为基于角色的方法,我们需要首先设置正确的目录和结构。角色保存在名为“roles”的目录中,每个角色在其中都有自己的目录。每个角色被分成单独的目录,Ansible 将在任务和处理程序目录中查找名为“main.yml”的文件。使用上述配置,我们将playbook.yml文件中的 Apache2 配置步骤拆分为单独的组件,并像这样安排它们。

playbook.yml
roles/
   apache2/
     templates/httpd.j2
     tasks/main.yml
     handlers/main.yml

例如,tasks/main.yml 文件包含以下内容。

---
 - name: ensure apache is at the latest version
   apt: pkg=apache2 state=latest
 - name: ensure apache is running
   service: name=httpd state=started
 - name: write the apache config file
   template: xx_src=httpd.j2 dest=/etc/apache2/httpd.conf
   notify:
   - restart apache

为了在我们的剧本中包含一个角色,我们需要playbook.yml稍微调整文件。

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  roles:
    apache2

通过创建角色配置文件,然后将它们添加到主剧本文件中角色声明下的角色集,可以将更多角色添加到该服务器。

有关 playbook 的更多信息,请参阅 Ansible playbooks 文档。