Ansible:像系统管理员一样思考的自动化框架

作者:Shawn Powers

多年来,我撰写并培训过关于各种 DevOps 工具的文章,尽管它们都很棒,但很明显,它们中的大多数都是从开发人员的角度设计的。 这没什么错,因为以编程方式进行配置管理正是重点。 然而,直到我开始使用 Ansible,我才觉得它是一款系统管理员会很快欣赏的工具。

这种欣赏部分来自于 Ansible 与其客户端计算机通信的方式——即通过 SSH。 作为系统管理员,你们都非常熟悉通过 SSH 连接到计算机,因此从一开始,您就比其他替代方案更了解 Ansible。

考虑到这一点,我计划撰写几篇文章,探讨如何利用 Ansible。 这是一个很棒的系统,但当我第一次接触它时,并不清楚如何开始。 并不是说学习曲线陡峭。 实际上,如果有什么问题的话,那就是在开始使用 Ansible 之前,我真的没有那么多东西需要学习,这让我感到困惑。 例如,如果您不必安装代理程序(Ansible 没有在客户端计算机上安装任何软件),您该如何开始?

到达起跑线

Ansible 最初让我感到如此困难的原因是它在配置服务器/客户端关系方面非常灵活,我不知道我应该做什么。 事实是 Ansible 并不真正在意您如何设置 SSH 系统; 它将利用您拥有的任何配置。 只有几件事需要考虑:

  1. Ansible 需要通过 SSH 连接到客户端计算机。

  2. 连接后,Ansible 需要提升权限,以便它可以配置系统、安装软件包等等。

不幸的是,这两个考虑因素确实打开了潘多拉魔盒。 允许连接到远程计算机并提升权限是一件可怕的事情。 由于某种原因,当您只是在远程计算机上安装一个代理并让 Chef 或 Puppet 处理权限提升时,感觉不那么脆弱。 这并不是说 Ansible 不安全,而是它将安全决策掌握在您手中。

接下来,我将列出一些可能的配置,以及每种配置的优点和缺点。 这不是一个详尽的列表,但它应该让您沿着正确的思路思考,了解什么最适合您的环境。 我还应该注意到,我不会提及 Vagrant 之类的系统,因为虽然 Vagrant 非常适合构建用于测试和开发的快速基础设施,但它与一组服务器截然不同,以至于这些考虑因素过于不同,无法真正比较。

一些 SSH 场景

1) 使用 Ansible 配置中的密码以 root 用户身份 SSH 进入远程计算机。

我从一个糟糕的想法开始。 这种设置的“优点”是它消除了权限提升的需要,并且远程服务器上不需要其他用户帐户。 但是,这种便利的代价是不值得的。 首先,大多数系统不允许您以 root 用户身份通过 SSH 进入,除非您更改默认配置。 这些默认配置的存在是因为,坦率地说,允许 root 用户远程连接是一个坏主意。 其次,将 root 密码放在 Ansible 机器上的纯文本配置文件中是令人震惊的。 真的,我提到这种可能性是因为它一种可能性,但应该避免使用它。 请记住,Ansible 允许您自己配置连接,并且它会让您做非常愚蠢的事情。 请不要这样做。

2) 以普通用户身份 SSH 进入远程计算机,使用存储在 Ansible 配置中的密码。

这种情况的一个优点是它不需要对客户端进行太多配置。 大多数用户默认都能够通过 SSH 进入,因此 Ansible 应该能够使用凭据并顺利登录。 我个人不喜欢将密码以纯文本形式存储在配置文件中的想法,但至少它不是 root 密码。 如果您使用此方法,请务必考虑如何在远程服务器上进行权限提升。 我知道我还没有谈到权限提升,但如果您的配置文件中有密码,则很可能使用相同的密码来获得 sudo 访问权限。 因此,只需一次疏忽,您不仅会危及远程用户的帐户,还可能危及整个系统。

3) 以普通用户身份 SSH 进入远程计算机,使用没有空密码的密钥对进行身份验证。

这消除了将密码存储在配置文件中的需要,至少对于登录过程而言是这样。 没有密码的密钥对并不理想,但这是我在像我家这样的环境中经常做的事情。 在我的内部网络上,我通常使用没有密码的密钥对来自动化许多需要身份验证的事情,例如 cron 作业。 这不是最安全的选项,因为泄露的私钥意味着对远程用户帐户的无限制访问,但我更喜欢它而不是配置文件中的密码。

4) 以普通用户身份 SSH 进入远程计算机,使用受密码保护的密钥对进行身份验证。

这是一种非常安全的远程访问处理方式,因为它需要两个不同的身份验证因素:1) 私钥和 2) 解密私钥的密码。 如果您只是交互式地运行 Ansible,这可能是理想的设置。 当您运行命令时,Ansible 应该提示您输入私钥的密码,然后它将使用密钥对登录到远程系统。 是的,也可以通过仅使用标准密码登录而不指定配置文件中的密码来完成相同的操作,但是如果您无论如何都要在命令行上键入密码,为什么不添加密钥对提供的保护层呢?

5) 使用受密码保护的密钥对进行 SSH,但使用 ssh-agent 来“解锁”私钥。

这并不能完美地回答无人值守的自动化 Ansible 命令的问题,但它确实使相当安全的设置也变得方便。 ssh-agent 程序对密码进行一次身份验证,然后使用该身份验证进行未来的连接。 当我使用 Ansible 时,这就是我认为我想要做的事情。 如果我完全诚实,我仍然通常使用没有密码的密钥对,但这通常是因为我正在处理我的家庭服务器,而不是容易受到攻击的东西。

在配置 SSH 环境时,还有一些其他注意事项需要牢记。 也许您可以限制 Ansible 用户(通常是您的本地用户名),使其只能从特定的 IP 地址登录。 也许您的 Ansible 服务器可以位于不同的子网中,位于强大的防火墙后面,这样它的私钥更难远程访问。 也许 Ansible 服务器本身没有安装 SSH 服务器,因此根本没有传入访问。 同样,Ansible 的优势之一是它使用 SSH 协议进行通信,并且您多年来一直在调整该协议,使其成为最适合您环境的系统。 我不太喜欢宣称什么是“最佳实践”,因为实际上,最佳实践是考虑您的环境并选择最适合您情况的设置。

权限提升

一旦您的 Ansible 服务器通过 SSH 连接到其客户端,它就需要能够提升权限。 如果您选择了上面的选项 1,您已经是 root 用户,这是一个无关紧要的问题。 但是由于没有人选择选项 1(对吧?),您需要考虑客户端计算机上的普通用户如何获得访问权限。 Ansible 支持各种各样的提升系统,但在 Linux 中,最常见的选项是 sudo 和 su。 与 SSH 一样,有一些情况需要考虑,尽管肯定还有其他选择。

1) 使用 su 提升权限。

对于 Red Hat/CentOS 用户,本能可能是使用 su 以获得系统访问权限。 默认情况下,这些系统在安装期间配置 root 密码,要获得特权访问,您需要键入密码。 使用 su 的问题在于,虽然它为您提供了对远程系统的完全访问权限,但它也为您提供了对远程系统的完全访问权限。 (是的,那是讽刺。)此外,su 程序无法使用密钥对进行身份验证,因此密码必须以交互方式键入或存储在配置文件中。 并且由于它实际上是 root 密码,因此将其存储在配置文件中听起来应该是一个可怕的想法,因为它确实如此。

2) 使用 sudo 提升权限。

这是 Debian/Ubuntu 系统的配置方式。 正确组中的用户有权 sudo 命令并以 root 权限执行它。 开箱即用,这仍然存在密码存储或交互式键入的问题。 由于将用户密码存储在配置文件中似乎稍微不那么可怕,我想这比使用 su 更进一步,但如果密码泄露,它仍然会提供对系统的完全访问权限。 (毕竟,键入 sudo su - 将允许用户成为 root 用户,就像他们拥有 root 密码一样。)

3) 使用 sudo 提升权限并在 sudoers 文件中配置 NOPASSWD。

同样,在我的本地环境中,这就是我所做的。 这并不完美,因为它为用户帐户提供了不受限制的 root 访问权限,并且不需要任何密码。 但是,当我这样做并使用没有密码的 SSH 密钥对时,我可以轻松地自动化 Ansible 命令。 我再次注意到,虽然它很方便,但它不是一个非常安全的想法。

4) 使用 sudo 提升权限并在特定可执行文件上配置 NOPASSWD。

这个想法可能是安全性和便利性之间最好的折衷方案。 基本上,如果您知道您计划使用 Ansible 做什么,您可以为远程用户提供 NOPASSWD 权限,仅用于它需要使用的那些应用程序。 这可能会有点令人困惑,因为 Ansible 对很多事情都使用 Python,但经过足够的反复试验,您应该能够弄清楚。 这需要更多的工作,但确实消除了一些明显的安全漏洞。

实施您的计划

一旦您决定如何处理 Ansible 身份验证和权限提升,您就需要进行设置。 在您精通 Ansible 之后,您可能可以使用该工具本身来帮助“引导”新的客户端,但首先,手动配置客户端非常重要,这样您就知道发生了什么。 从您熟悉的流程开始自动化远比从一开始就进行自动化要好。

我过去曾写过关于 SSH 密钥对的文章,并且网上有无数关于设置它的文章。 从您的 Ansible 计算机来看,简短版本如下所示:


# ssh-keygen
# ssh-copy-id -i .ssh/id_dsa.pub remoteuser@remote.computer.ip
# ssh remoteuser@remote.computer.ip

如果您选择在创建密钥对时不使用密码,那么最后一步应该让您无需键入密码或密码即可进入远程计算机。

为了在 sudo 中设置权限提升,您需要编辑 sudoers 文件。 您不应直接编辑该文件,而应使用:


# sudo visudo

这将打开 sudoers 文件,并允许您安全地进行更改(它在您保存时会进行错误检查,因此您不会因拼写错误而意外地将自己锁定)。 文件中有示例,因此您应该能够弄清楚如何分配您想要的确切权限。

一旦全部配置完成,您应该在将 Ansible 引入之前手动测试它。 尝试 SSH 进入远程客户端,然后尝试使用您选择的任何方法提升权限。 一旦您配置了连接方式,就该安装 Ansible 了。

安装 Ansible

由于 Ansible 程序仅安装在单台计算机上,因此启动并运行并不是一件难事。 Red Hat/Ubuntu 系统打包安装的方式略有不同,但两者都不困难。

在 Red Hat/CentOS 中,首先启用 EPEL 存储库:


sudo yum install epel-release

然后安装 Ansible:


sudo yum install ansible

在 Ubuntu 中,首先启用 Ansible PPA:


sudo apt-add-repository spa:ansible/ansible
(press ENTER to access the key and add the repo)

然后安装 Ansible:


sudo apt-get update
sudo apt-get install ansible

配置 Ansible 主机文件

Ansible 系统无法知道您要控制哪些客户端,除非您为其提供计算机列表。 该列表非常简单,它看起来像这样:


# file /etc/ansible/hosts

[webservers]
blogserver ansible_host=192.168.1.5
wikiserver ansible_host=192.168.1.10

[dbservers]
mysql_1 ansible_host=192.168.1.22
pgsql_1 ansible_host=192.168.1.23

带括号的部分指定组。 单个主机可以列在多个组中,并且 Ansible 可以引用单个主机或组。 这也是配置文件的位置,如果这是您计划的设置类型,则可以在其中存储纯文本密码。 配置文件中的每一行配置一个主机,您可以在 ansible_host 语句后添加多个声明。 一些有用的选项是:


ansible_ssh_pass
ansible_become
ansible_become_method
ansible_become_user
ansible_become_pass

Ansible Vault

我还应该注意到,虽然设置更复杂,并且不太可能是您在首次涉足 Ansible 世界时会做的事情,但该程序确实提供了一种在 vault 中加密密码的方法。 一旦您熟悉 Ansible 并想要将其投入生产,将这些密码存储在加密的 Ansible vault 中是理想的选择。 但本着先爬后走的精神,我建议您首先在非生产环境中开始并使用无密码方法。

测试您的系统

最后,您应该测试您的系统以确保您的客户端正在连接。 ping 测试将确保 Ansible 计算机可以 ping 每个主机:


ansible -m ping all

运行后,您应该看到每个已定义主机的消息,如果 ping 成功,则显示 ping: pong。 这实际上并没有测试身份验证,只是测试网络连接。 尝试以下操作来测试您的身份验证:


ansible -m shell -a 'uptime' webservers

您应该看到 webservers 组中每个主机的 uptime 命令的结果。

在以后的文章中,我计划开始深入研究 Ansible 管理远程计算机的能力。 我将研究各种模块,以及如何使用 ad-hoc 模式在几次击键中完成在命令行上单独处理需要很长时间才能完成的任务。 如果您没有从上面的示例 Ansible 命令中获得预期的结果,请花时间确保身份验证正常工作。 如果您遇到困难,请查看 Ansible 文档 以获得更多帮助。

Shawn 是 Linux Journal 的副编辑,并且从一开始就接触 Linux。 他对开源充满热情,并且热爱教学。 他还喝了太多的咖啡,这经常在他的写作中表现出来。

加载 Disqus 评论