简介
简而言之,服务器配置管理(也被广泛称为 IT 自动化)是将基础设施管理转化为代码库的解决方案,描述了部署服务器所需的所有流程,并将其转化为一组可以进行版本控制和轻松重复使用的配置脚本。它可以极大地提高任何服务器基础设施的完整性。
在之前的指南中,我们讨论了实施配置管理策略对服务器基础设施的主要好处,配置管理工具的工作原理以及这些工具通常具有的共同点。
本系列的这一部分将带领您通过使用 Ansible 自动化服务器配置的过程,Ansible 是一种提供完整自动化框架和编排能力的配置管理工具,同时保持了极致简单和极简的目标。我们将重点关注用于创建一个简化示例以完全自动化部署 Ubuntu 18.04 上的 Apache 的语言术语、语法和功能。
以下列表包含了我们需要自动化的所有步骤,以实现我们的目标:
- 更新
apt
缓存 - 安装 Apache
- 创建自定义文档根目录
- 在自定义文档根目录中放置一个
index.html
文件 - 应用模板以设置我们的自定义虚拟主机
- 重启 Apache
我们将首先查看 Ansible 使用的术语,然后概述可以用于编写 playbook 的主要语言特性。在指南结束时,您将找到一个完整的配置示例,用于自动化在 Ubuntu 18.04 上设置 Apache 的步骤的描述内容。
入门
在我们可以更深入地了解 Ansible 之前,重要的是我们要熟悉这个工具引入的重要术语和概念。
术语
以下列表包含了 Ansible 使用的最相关术语的快速概述:
- 控制节点:安装了 Ansible 的机器,负责在您管理的服务器上运行配置。
- 清单:包含有关您正在管理的服务器的信息的
INI
文件。 - Playbook:包含一系列应该自动化的程序的
YAML
文件。 - 任务:定义要执行的单个过程的块,例如:安装一个软件包。
- 模块:模块通常抽象出系统任务,如处理软件包或创建和更改文件。Ansible 有多种内置模块,但您也可以创建自定义模块。
- 角色:一组相关的 playbooks、模板和其他文件,以预定义的方式组织,以便促进重用和共享。
- Play:从头到尾执行的配置称为 play。
- 事实:包含有关系统的信息的全局变量,如网络接口或操作系统。
- 处理程序:用于触发服务状态更改,如重新启动或重新加载服务。
任务格式
任务定义了应该由 Ansible 执行的单个自动化步骤。它通常涉及使用模块或执行原始命令。以下是一个任务的样子:
- name: 这是一个任务 apt: name=vim state=latest
name
部分实际上是可选的,但建议使用,因为在执行任务时会显示在配置的输出中。apt
部分是一个内置的 Ansible 模块,它抽象了基于 Debian 的发行版上的软件包管理。这个示例任务告诉 Ansible 要将软件包 vim
的状态更改为 latest
,这将导致软件包管理器在尚未安装时安装此软件包。
Playbook 格式
Playbooks 是包含一系列指令以自动化服务器配置的 YAML
文件。以下示例是一个简单的 playbook,执行两个任务:更新 apt
缓存,然后安装 vim
:
--- - hosts: all become: true tasks: - name: 更新 apt 缓存 apt: update_cache=yes - name: 安装 Vim apt: name=vim state=latest
YAML
依赖缩进来序列化数据结构。因此,在编写 playbooks 时,尤其是在复制示例时,您需要特别小心地保持正确的缩进。
在本指南结束之前,我们将看到一个更真实的 playbook 示例,并对其进行详细解释。下一节将为您介绍可以用于编写 Ansible playbook 的最重要元素和功能的概述。
编写 Playbooks
现在您已经熟悉了 Ansible 的基本术语和 playbook 中的任务的格式,我们将学习一些 playbook 功能,这些功能可以帮助我们创建更多功能的自动化。
使用变量
在 Ansible 中,有多种定义变量的方式。最简单的方法是使用 playbook 的 vars
部分。下面的示例定义了一个名为 package
的变量,稍后在一个任务中使用:
--- - hosts: all become: true vars: package: vim tasks: - name: 安装软件包 apt: name={{ package }} state=latest
package
变量具有全局作用域,这意味着它可以从配置的任何地方访问,甚至可以从包含的文件和模板中访问。
使用循环
循环通常用于使用不同的输入值重复执行任务。例如,您可以创建一个单一任务,并使用循环来重复执行该任务,以安装您想要安装的所有不同软件包,而不是为安装10个不同软件包创建10个任务。
要在任务中创建循环,请在数组值中包含选项 with_items
。内容可以通过循环变量 item
进行访问,如下例所示:
- name: 安装软件包 apt: name={{ item }} state=latest with_items: - vim - git - curl
您还可以使用数组变量来定义您的项目:
--- - hosts: all become: true vars: packages: [ 'vim', 'git', 'curl' ] tasks: - name: 安装软件包 apt: name={{ item }} state=latest with_items: "{{ packages }}"
使用条件语句
条件语句可用于根据变量或命令输出动态决定是否执行任务。
以下示例仅会关闭基于 Debian 的系统:
- name: 关闭基于 Debian 的系统 command: /sbin/shutdown -t now when: ansible_os_family == "Debian"
条件语句 when
接收一个要评估的表达式作为参数。只有在表达式评估为 true
时,任务才会执行。在我们的示例中,我们测试了一个事实,以检查操作系统是否来自 Debian 家族。
在 IT 自动化中,条件语句的常见用例是任务的执行取决于命令的输出。使用 Ansible,我们实现这一点的方式是注册一个变量来保存命令执行的结果,然后在随后的任务中测试这个变量。我们可以测试命令的退出状态(成功或失败)。我们还可以检查输出中的特定内容,尽管这可能需要使用正则表达式和字符串解析命令。
下面的示例展示了基于 php -v
命令输出的两个条件任务。我们将测试命令的退出状态,因为我们知道如果此服务器上未安装 PHP,则命令将无法执行。任务中的 ignore_errors
部分很重要,以确保在命令执行失败时继续进行配置。
- name: 检查 PHP 是否已安装 register: php_installed command: php -v ignore_errors: true - name: 仅当 PHP 已安装时执行此任务 debug: var=php_install when: php_installed|success - name: 仅当 PHP 未安装时执行此任务 debug: msg='PHP 未安装' when: php_installed|failed
此处使用的 debug
模块是一个用于显示变量内容或调试消息的有用模块。它可以打印字符串(使用 msg
参数)或打印变量的内容(使用 var
参数)。
使用模板
模板通常用于设置配置文件,允许使用变量和其他旨在使这些文件更加灵活和可重用的功能。Ansible 使用 Jinja2 模板引擎。
以下示例是一个用于设置 Apache 虚拟主机的模板,使用变量设置此主机的文档根目录:
<VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot {{ doc_root }} <Directory {{ doc_root }}> AllowOverride All Require all granted </Directory> </VirtualHost>
内置模块 template
用于从任务中应用模板。如果您将上述模板文件命名为 vhost.tpl
,并将其放在与您的 playbook 相同的目录中,这是您将模板应用于替换默认 Apache 虚拟主机的方式:
- name: 更改默认 Apache 虚拟主机 template: src: vhost.tpl dest: /etc/apache2/sites-available/000-default.conf
定义和触发处理程序
处理程序用于触发服务的状态更改,例如 重启 或 停止。尽管它们看起来与常规任务非常相似,但处理程序仅在先前从任务的 notify
指令触发时执行。它们通常被定义为 playbook 的 handlers
部分中的数组,但也可以存在于单独的文件中。
让我们考虑我们之前使用模板的示例,我们设置了一个 Apache 虚拟主机。如果您想要确保在虚拟主机更改后重新启动 Apache,您首先需要为 Apache 服务创建一个处理程序。这是如何在 playbook 中定义处理程序的方式:
handlers: - name: 重启 apache service: name=apache2 state=restarted - name: 其他处理程序 service: name=other state=restarted
这里的 name
指令很重要,因为它将是此处理程序的唯一标识符。要从任务中触发此处理程序,您应该使用 notify
选项:
- name: 更改默认 Apache 虚拟主机 template: src: vhost.tpl dest: /etc/apache2/sites-available/000-default.conf notify: 重启 apache
我们已经看到了一些您可以用来开始编写 Ansible playbook 的最重要功能。在下一节中,我们将深入探讨一个更真实的 playbook 示例,该 playbook 将自动安装和配置 Ubuntu 上的 Apache。
示例 Playbook
现在让我们来看一个 Playbook,它将自动化安装 Apache web 服务器在 Ubuntu 18.04 系统中,正如本指南介绍中所讨论的那样。
完整的示例,包括用于设置 Apache 和由 web 服务器提供的 HTML 文件的模板文件,可以在 Github 上找到。该文件夹还包含一个 Vagrantfile,让您可以使用由 Vagrant 管理的虚拟机在简化的设置中测试 Playbook。
Playbook 内容
以下是 Playbook 的完整内容,供您参考:
--- - hosts: all become: true vars: doc_root: /var/www/example tasks: - name: Update apt apt: update_cache=yes - name: Install Apache apt: name=apache2 state=latest - name: Create custom document root file: path={{ doc_root }} state=directory owner=www-data group=www-data - name: Set up HTML file copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644 - name: Set up Apache virtual host file template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf notify: restart apache handlers: - name: restart apache service: name=apache2 state=restarted
让我们更详细地检查这个 Playbook 的每个部分:
hosts: all
Playbook 开始时指定应该应用于清单中的所有主机(hosts: all
)。也可以将 Playbook 的执行限制为特定主机或主机组。这个选项可以在执行时被覆盖。
become: true
become: true
部分告诉 Ansible 在执行此 Playbook 中的所有任务时使用特权升级(sudo)。这个选项可以在任务级别上被覆盖。
vars
定义一个变量 doc_root
,稍后在任务中使用。这个部分可以包含多个变量。
tasks
定义实际任务的部分。第一个任务更新 apt
缓存,第二个任务安装 apache2
软件包。
第三个任务使用内置模块 file 创建一个目录作为我们的文档根目录。这个模块可以用来管理文件和目录。
第四个任务使用模块 copy 将本地文件复制到远程服务器。我们正在复制一个简单的 HTML 文件,作为由 Apache 托管的网站。
handlers
最后,我们有 handlers
部分,声明了服务。我们定义了 restart apache
处理程序,它在第四个任务中被通知,那里应用了 Apache 模板。
运行 Playbook
一旦您将此 Playbook 的内容下载到您的 Ansible 控制节点,您可以使用 ansible-playbook
在清单中的一个或多个节点上执行它。以下命令将在默认清单文件中的所有主机上执行 Playbook,使用 SSH 密钥对身份验证连接为当前系统用户:
ansible-playbook playbook.yml
您还可以使用 -l
限制执行到清单中的单个主机或主机组:
ansible-playbook -l host_or_group playbook.yml
如果您需要指定不同的 SSH 用户连接到远程服务器,您可以在该命令中包含参数 -u user
:
ansible-playbook -l host_or_group playbook.yml -u remote-user
有关如何运行 Ansible 命令和 Playbook 的更多信息,请参考我们的指南《在 Ubuntu 18.04 上安装和配置 Ansible》。
结论
Ansible 是一个极简的 IT 自动化工具,学习曲线低,使用 YAML
编写其配置脚本。它有大量内置模块,可用于抽象任务,如安装软件包和处理模板。它简化的基础设施要求和简单的语言对于刚开始使用配置管理的人来说可能是一个很好的选择。然而,它可能缺乏一些您可以在更复杂的工具如 Puppet 和 Chef 中找到的高级功能。
在本系列的下一部分中,我们将看到 Puppet 的实际概述,Puppet 是一个流行且成熟的配置管理工具,它使用基于 Ruby 的表达性和强大的自定义 DSL 来编写配置脚本。