深入探索 DevOps 武器库:Ansible 简介

如果您需要并行部署数百台服务器或客户端节点,无论是在本地还是在云端,并且您需要配置每一个节点,您会怎么做?您如何做到?您甚至从哪里开始?许多配置管理框架的存在就是为了解决大部分(如果不是全部)这些问题和担忧。Ansible 就是其中一个框架。

您可能已经听说过 Ansible,但对于那些没有听说过或不知道它是什么的人来说,Ansible 是一个配置管理和配置工具。(我稍后会详细解释这意味着什么。)它与其他工具非常相似,例如 Puppet、Chef 和 Salt。

为什么要使用 Ansible?嗯,因为它很容易掌握。我并不是说其他的不简单,但 Ansible 让个人很容易快速上手。这是因为 Ansible 使用 YAML 作为其配置、部署和部署的基础。而且由于这种方法,任务以特定的顺序执行。在执行过程中,如果您遇到语法错误,它会在您遇到错误时失败,这可能会使其更容易调试。

现在,什么是 YAML?YAML(或 YAML Ain't Markup Language)是一种人类可读的数据序列化语言,主要用于捕获配置文件。您知道 JSON 比 XML 更容易实现和使用吗?嗯,YAML 采用比 JSON 更简单的方法。这是一个典型的包含列表的 YAML 结构示例


data:
    - var1:
        a: 1
        b: 2
    - var2:
        a: 1
        b: 2
        c: 3

现在,让我们回到 Ansible。Ansible 是一个开源自动化平台,可免费用于 Linux、macOS 和 BSD。同样,它非常容易设置和使用,而不会牺牲任何功能。Ansible 旨在帮助您进行配置管理、应用程序部署和各种任务的自动化。它在 IT 编排领域中非常有效,您需要在其中按顺序运行特定任务,并创建必须在多个不同服务器或设备上发生的一系列事件。

这是一个很好的例子:假设您有一组 Web 服务器位于负载均衡器后面。您需要升级这些 Web 服务器,但您还需要确保在升级过程中,除了一个服务器之外,所有服务器都保持在线。Ansible 可以处理如此复杂的任务。

Ansible 使用 SSH 来管理网络上的远程系统,这些系统不仅需要本地安装 SSH,还需要安装 Python。这意味着您不必为 Ansible 安装和配置客户端-服务器环境。

安装 Ansible

虽然您可以从源代码(从公共 Git 仓库或 tarball)构建软件包,但大多数现代 Linux 发行版都会在其本地软件包仓库中提供二进制软件包。您需要在至少一台机器(您的控制节点)上安装 Ansible。请记住,远程机器上只需要 SSH 和 Python。

在 Red Hat 或 CentOS 上安装


$ sudo yum install ansible

在 Ubuntu 上安装


$ sudo apt install ansible

配置您的 SSH 密钥并在远程主机上安装它们

一旦您在每个节点上安装了 SSH 密钥作为授权密钥,生活将会变得更加轻松。此练习的目的是提供从一个节点到另一个节点的访问权限,而无需每次登录都输入密码。此功能有助于使用 SSH 协议进行自动化和无密码登录。SSH 中基于密钥的身份验证的另一个名称是公钥身份验证。

创建 RSA 密钥对


$ ssh-keygen -t rsa

为了简单起见,让我们将密钥的位置和密码都保留为默认值。继续按 Enter 键,直到返回到 shell 提示符。

SSH 密钥创建完成后,将公钥复制到远程服务器。在本练习中,您需要从控制节点复制到远程节点


$ cat ~/.ssh/id_rsa.pub | ssh user@192.168.1.109 "cat >>
 ↪~/.ssh/authorized_keys"

根据需要替换用户名和 IP 地址。 您可以通过从指定的控制节点 SSH 到远程节点来确保一切正常。如果操作正确,系统将不会提示您输入密码,并且您将自动登录到远程机器的 shell。

定义远程机器

让我们定义哪些节点将成为控制节点的远程节点。但在执行此操作之前,让我们首先重新定位默认主机配置文件


$ sudo mv /etc/ansible/hosts /etc/ansible/hosts.orig

创建一个新的 /etc/ansible/hosts 文件,并定义一个新组,其中包含要在同一组下标识的 IP 地址列表。在本例中,让我们定义一个名为 web 的组,并在其下添加一个远程节点 192.168.1.109


[web]
192.168.1.109

如果您想向此组添加更多节点,您可以在新行上执行此操作。例如


[web]
192.168.1.109
192.168.1.110
192.168.1.111

如果您想在本地机器而不是两个或多个单独的节点上测试此操作,请创建一个名为 local 的组,并添加 localhost IP 地址


[local]
127.0.0.1

运行基本任务

现在您已经完成了所有这些操作,您应该能够在定义的远程服务器上运行任务。但是,首先让我们确保一切顺利。请记住,Ansible 需要能够通过 SSH 直接登录到远程节点,并且无需密码。如果您还没有这样做,请参考上面的 SSH 密钥部分。运行以下命令


$ ansible all -m ping

您的响应应类似于以下 JSON 输出,用于 /etc/ansible/hosts 文件中定义的所有组中的所有节点


192.168.1.109 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

如果您想在组 web 下的所有节点上运行命令,并且您知道该组中的每个节点都是基于 Debian 的发行版,您将运行以下命令


$ ansible web -m shell -a 'cat /etc/debian_version'

注意:-m 选项定义要使用的模块。第一个尝试使用了 ping 模块,此示例显示调用 shell 来执行基于 shell 的命令。

上述命令的输出将类似于以下内容


192.168.1.109 | CHANGED | rc=0 >>
buster/sid

现在假设您需要以完全不同的用户身份运行命令


$ ansible web --become-user=root -m shell -a 'tail -n5
 ↪/var/log/syslog'

您可以依赖 --become-user= 选项并将所需的用户附加到参数。上面的 tail 命令将输出您通常期望的内容


192.168.1.109 | CHANGED | rc=0 >>
Jun 15 20:17:51 ubuntu-test systemd[1]: Started Session 9
 ↪of user petros.
Jun 15 20:17:52 ubuntu-test ansible-command: Invoked with
 ↪creates=None executable=None _uses_shell=True
 ↪strip_empty_ends=True _raw_params=cat
 ↪/etc/debian_version removes=None argv=None warn=True
 ↪chdir=None stdin_add_newline=True stdin=None
Jun 15 20:25:12 ubuntu-test systemd[1]: Started Session 10
 ↪of user petros.
Jun 15 20:25:13 ubuntu-test ansible-command: Invoked with
 ↪creates=None executable=None _uses_shell=True
 ↪strip_empty_ends=True _raw_params=tail -n5
 ↪/var/log/messages removes=None argv=None warn=True
 ↪chdir=None stdin_add_newline=True stdin=None
Jun 15 20:25:34 ubuntu-test ansible-command: Invoked with
 ↪creates=None executable=None _uses_shell=True
 ↪strip_empty_ends=True _raw_params=tail -n5
 ↪/var/log/syslog removes=None argv=None warn=True
 ↪chdir=None stdin_add_newline=True stdin=None

创建 Playbook

使用这些基本功能,您可以轻松地将一些命令批量处理到网络中的各个节点,但通常您会发现自己需要运行多个 shell 命令。这就是 Playbook 的用武之地。Playbook 运行多个任务,并提供比您的临时命令更高级的功能。

假设您想在远程节点上线时安装几个软件包。您需要创建一个 YAML 文件来捕获这些操作。使用文本编辑器,创建一个名为 package-install.yml 的文件,其 YAML 结构如下


---
- hosts: web
  tasks:
   - name: Install Make
     apt: pkg=make state=present update_cache=true
     become: yes
   - name: Install GCC
     apt: pkg=gcc state=present update_cache=true
     become: yes

您基本上是告诉 Ansible,您想在组 web 中的所有节点上安装 Make 和 GCC 软件包(以及其依赖项)。您还告诉 Ansible,您需要以特权用户的身份安装这两个软件包,并使用 become: yes 字段。

现在是时候启动 Ansible Playbook 了。如果您尚未以特权用户身份执行,则需要添加 --ask-become-pass 选项,这将提示您输入密码以 suroot 以执行所需的操作。这仅在同一组下的所有节点共享相同的用户和密码方案时才有效


$ ansible-playbook --ask-become-pass package-install.yml
BECOME password:

PLAY [web]
**************************************************************

TASK [Gathering Facts]
**************************************************************
ok: [192.168.1.109]

TASK [Install Make]
**************************************************************
 [WARNING]: Updating cache and auto-installing missing
 ↪dependency: python-apt

changed: [192.168.1.109]

TASK [Install GCC]
**************************************************************
changed: [192.168.1.109]

PLAY RECAP
**************************************************************
192.168.1.109       : ok=3    changed=2    unreachable=0
 ↪failed=0    skipped=0    rescued=0    ignored=0

现在您应该开始看到一些真正的威力了:Make 和 GCC 都已安装到组中的节点上。

处理程序

Ansible 支持一个名为处理程序的事件处理系统。处理程序有点像任务,它可以完成任务可以完成的任何事情,但它会在被另一个任务调用时运行。处理程序仅在调用其侦听的事件时才会采取操作。

假设您的 YAML 文件如下所示


---
- hosts: web
  tasks:
   - name: Install Apache
     apt: pkg=apache2 state=present update_cache=true
     become: yes
     notify:
      - Start Apache
  handlers:
   - name: Start Apache
     service: name=apache2 state=started

这指示 Ansible 运行一个名为“Install Apache”的任务,一旦完成,它将通知一个名为“Start Apache”的处理程序来启动 Web 服务。它能够通过 service 模块启动 Web 服务,该模块支持您典型的 start、stop、restart 和 reload 命令。(我之前提到了模块的概念,如果您还记得 pingshell。)上述 YAML 结构的输出应如下所示


$ ansible-playbook --ask-become-pass package-install.yml
BECOME password:

PLAY [web]
**************************************************************

TASK [Gathering Facts]
**************************************************************
ok: [192.168.1.109]

TASK [Install Apache]
**************************************************************
changed: [192.168.1.109]

RUNNING HANDLER [Start Apache]
**************************************************************
ok: [192.168.1.109]

PLAY RECAP
**************************************************************
192.168.1.109      : ok=3    changed=1    unreachable=0
 ↪failed=0   skipped=0    rescued=0    ignored=0

总结

这里的示例非常小且有限。正如您可能已经猜到的那样,您可以在单个 YAML 文件中添加更多任务并通知更多处理程序。它不需要仅限于几个。可能需要一些时间和反复试验才能构建足够的列表来处理自动化环境中的每个操作。您可以使用 Ansible 做更多的事情,还有更多内容需要介绍。虽然本指南为您的入门提供了良好的基础,但我仅触及了这个极其强大的配置管理框架的表面。

资源

Petros Koutoupis,LJ 特约编辑,目前是 Cray Lustre 高性能文件系统部门的高级性能软件工程师。他还是 RapidDisk 项目的创建者和维护者。Petros 在数据存储行业工作了十多年,并帮助开创了当今广泛使用的许多技术。

加载 Disqus 评论