你想磨练你的系统管理或 Linux 技能吗?也许你有一些东西在你的本地局域网上运行,你想让你的生活更轻松——你从哪里开始呢?在本文中,我将解释如何设置工具来简化多台机器的管理。
当涉及到远程管理工具时,SaltStack、Puppet、Chef 和 Ansible 是一些流行的选择。在本文中,我将重点介绍 Ansible,并解释它如何在你拥有 5 台虚拟机或 1,000 台虚拟机时提供帮助。
我们的旅程从多台机器的基本管理开始,无论它们是虚拟的还是物理的。我假设你对你想实现的目标有一个概念,并且具备基本的 Linux 管理技能(或者至少有能力查找执行每个任务所需的步骤)。我将向你展示如何使用这些工具,而如何使用它们则取决于你。
什么是 Ansible?
Ansible 网站将该项目解释为“一种极其简单的 IT 自动化引擎,可自动化云配置、配置管理、应用程序部署、服务内编排以及许多其他 IT 需求。” Ansible 可用于从集中位置跨一组定义的服务器执行相同的任务。
如果你熟悉 Bash for 循环,你会发现 Ansible 的运行方式与之类似。然而,不同之处在于 Ansible 是幂等的。用外行的话来说,这意味着通常只有当操作会导致更改时,Ansible 才会执行请求的操作。例如,如果你要执行 Bash for 循环以在所有机器上创建一个用户,它可能看起来像这样
for server in serverA serverB serverC; do ssh ${server} "useradd myuser"; done
这将在 serverA、serverB 和 serverC 上创建 myuser;但是,无论用户是否存在,每次运行 for 循环时都会运行 user add 命令。幂等系统将首先检查用户是否存在,如果不存在,该工具将创建它。这当然是一个简化的示例,但是随着时间的推移,幂等工具的好处将变得更加清晰。
Ansible 如何工作?
Ansible 将 Ansible playbook 转换为通过 SSH 运行的命令,这在管理类 Unix 环境时有几个好处
- 你正在管理的大多数(如果不是全部)类 Unix 机器都默认运行 SSH。
- 依赖 SSH 意味着远程主机上不需要代理。
- 在大多数情况下,不需要安装额外的软件,因为 Ansible 需要 Python 2.6 才能运行。大多数(如果不是全部)Linux 发行版都默认安装了此版本(或更高版本)。
- Ansible 不需要主节点。它可以从任何安装了 Ansible 包并具有足够 SSH 访问权限的主机运行。
- 尽管可以在 cron 作业中运行 Ansible,但默认情况下 Ansible 仅在你告诉它运行时才运行。
设置 SSH 密钥身份验证
使用 Ansible 的常用方法是设置无密码 SSH 密钥,以方便管理。(可以使用 Ansible Vault 来处理密码和其他敏感信息,但这超出了本文的范围。)现在,只需使用示例 1 中所示的以下命令生成 SSH 密钥即可。
示例 1:生成 SSH 密钥
[09:44 user ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:TpMyzf4qGqXmx3aqZijVv7vO9zGnVXsh6dPbXAZ+LUQ user@user-fedora
The key's randomart image is:
+---[RSA 2048]----+
| |
| |
| E |
| o . .. |
| . + S o+. |
| . .o * . .+ooo|
| . .+o o o oo+.*|
|. .ooo* o. * .*+|
| . o+*BO.o+ .o|
+----[SHA256]-----+
在示例 1 中,使用 Enter 键接受默认值。SSH 密钥可以由任何非特权用户生成,并安装在远程系统上任何用户的 SSH authorized_keys 文件中。密钥生成后,需要将其复制到远程主机。为此,运行以下命令
ssh-copy-id root@servera
注意:Ansible 不需要 root 访问权限;但是,如果你选择使用非 root 用户,则必须为你想要完成的任务配置适当的 sudo 权限。
系统将提示你输入 servera 的 root 密码,这将允许你的 SSH 密钥安装在远程主机上。首次安装 SSH 密钥后,通过 SSH 登录远程主机时将不再提示你输入 root 密码。
安装 Ansible
Ansible 包的安装仅在示例 1 中生成 SSH 密钥的主机上是必需的。如果你运行的是 Fedora,你可以发出以下命令
sudo dnf install ansible -y
如果你运行的是 CentOS,则需要配置企业 Linux 附加软件包 (EPEL) 存储库
sudo yum install epel-release -y
然后你可以使用 yum 安装 Ansible
sudo yum install ansible -y
对于基于 Ubuntu 的系统,你可以从 PPA 安装 Ansible
sudo apt-get install software-properties-common -y
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible -y
如果你使用的是 macOS,建议通过 Python PIP 完成安装
sudo pip install ansible
有关其他发行版,请参阅 Ansible 安装文档。
使用 Ansible 清单
Ansible 使用一个名为清单的 INI 样式文件来跟踪它可以管理的服务器。默认情况下,此文件位于 /etc/ansible/hosts 中。在本文中,我将使用示例 2 中所示的 Ansible 清单对所需的主机执行操作(为了简洁起见,已将其精简)
示例 2:Ansible hosts 文件
[arch]
nextcloud
prometheus
desktop1
desktop2
vm-host15
[fedora]
netflix
[centos]
conan
confluence
7-repo
vm-server1
gitlab
[ubuntu]
trusty-mirror
nwn
kids-tv
media-centre
nas
[satellite]
satellite
[ocp]
lb00
ocp_dns
master01
app01
infra01
每个组,通过方括号和组名(例如 [group1])表示,是一个任意组名,可以应用于一组服务器。一个服务器可以存在于多个组中而没有问题。在本例中,我为操作系统(arch、ubuntu、centos、fedora)以及服务器功能(ocp、satellite)设置了组。Ansible 主机文件可以处理比我正在使用的功能更高级的功能。有关更多信息,请参阅 清单文档。
运行 ad hoc 命令
将 SSH 密钥复制到清单中的所有服务器后,你就可以开始使用 Ansible 了。Ansible 的一个基本功能是运行 ad hoc 命令的能力。语法是
ansible-a "some command"
例如,如果你想更新所有 CentOS 服务器,你可以运行
ansible centos -a 'yum update -y'
注意:基于服务器的操作系统命名组不是必需的。正如我将要讨论的,Ansible Facts 可用于收集此信息;但是,当尝试使用 Facts 时,发出 ad hoc 命令会变得更加复杂,因此为了方便起见,如果你管理异构环境,我建议创建一些基于操作系统的组。
这将循环遍历 centos 组中的每个服务器并安装所有更新。一个更有用的 ad hoc 命令是 Ansible ping 模块,它用于验证服务器是否已准备好接收命令
ansible all -m ping
这将导致 Ansible 尝试通过 SSH 登录到清单中的所有服务器。示例 3 中可以看到 ping 命令的截断输出。
示例 3:Ansible ping 命令输出
nwn | SUCCESS => {
"changed": false,
"ping": "pong"
}
media-centre | SUCCESS => {
"changed": false,
"ping": "pong"
}
nas | SUCCESS => {
"changed": false,
"ping": "pong"
}
kids-tv | SUCCESS => {
"changed": false,
"ping": "pong"
}
...
运行 ad hoc 命令的能力对于快速任务很有用,但是如果你希望以后能够以可重复的方式运行相同的任务怎么办?为此,Ansible 实现了 playbook。
用于复杂任务的 Ansible playbook
Ansible playbook 是一个 YAML 文件,其中包含 Ansible 在运行期间应完成的所有指令。为了本练习的目的,我将不深入探讨更高级的主题,例如 Roles 和 Templates。如果你有兴趣了解更多信息,文档 是一个很好的起点。
在上一节中,我鼓励你使用 ssh-copy-id 命令来传播你的 SSH 密钥;但是,本文的重点是如何以一致的、可重复的方式完成任务。示例 4 演示了一种方法,以幂等的方式确保目标主机上存在 SSH 密钥。
示例 4:Ansible playbook “push_ssh_keys.yaml”
---
- hosts: all
gather_facts: false
vars:
ssh_key: '/root/playbooks/files/laptop_ssh_key'
tasks:
- name: copy ssh key
authorized_key:
key: "{{ lookup('file', ssh_key) }}"
user: root
在示例 4 的 playbook 中,所有关键部分都已突出显示。
- hosts: 行指示 playbook 应评估哪些主机组。在本例中,它将检查我们清单中的所有主机。
gather_facts: 行指示 Ansible 尝试查找有关每个主机的详细信息。稍后我将更详细地检查这一点。现在,gather_facts 设置为 false 以节省时间。
vars: 部分,顾名思义,用于定义可以在整个 playbook 中使用的变量。在示例 4 这样简短的 playbook 中,它更多的是一种便利,而不是必需品。
最后,主要部分由 tasks: 指示。这是大多数指令所在的位置。每个任务都应具有 - name:。这就是 Ansible 在执行运行或 playbook 执行时显示的内容。
authorized_key: 标题是 playbook 正在使用的 Ansible 模块的名称。可以通过命令行 ansible-doc -a 访问有关 Ansible 模块的信息;但是,在 Web 浏览器中查看 文档 可能更方便。authorized_key 模块 有大量入门示例。要运行示例 4 中的 playbook,只需使用 ansible-playbook 命令
ansible-playbook push_ssh_keys.yaml
如果是第一次将 SSH 密钥添加到框中,SSH 将提示你输入 root 用户的密码。
现在你的服务器已传播 SSH 密钥,是时候做一些更有趣的事情了。
Ansible 和收集 facts
Ansible 能够收集有关目标系统的各种 facts。如果你有大量主机,这可能会消耗大量时间。根据我的经验,每个主机可能需要 1 到 2 秒,甚至更长;但是,收集 facts 也有好处。考虑以下 playbook,用于关闭用户以 root 用户身份使用密码登录的功能
示例 5:锁定 root SSH 帐户
---
- hosts: all
gather_facts: true
vars:
tasks:
- name: Enabling ssh-key only root access
lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^PermitRootLogin'
line: 'PermitRootLogin without-password'
notify:
- restart_sshd
- restart_ssh
handlers:
- name: restart_sshd
service:
name: sshd
state: restarted
enabled: true
when: ansible_distribution == 'RedHat'
- name: restart_ssh
service:
name: ssh
state: restarted
enabled: true
when: ansible_distribution == 'Debian'
在示例 5 中,使用 conditional 才会执行。在本例中,基于 Red Hat 的发行版将其 SSH 服务命名为不同于基于 Debian 的发行版,这是条件语句的目的。尽管还有其他方法可以实现相同的效果,但该示例有助于演示 Ansible facts。如果你想查看 Ansible 默认收集的所有 facts,你可以在 localhost 上运行 setup 模块
ansible localhost -m setup |less
Ansible 发现的任何 fact 都可以用于做出决策,其方式与示例 4 中显示的 vars: 部分非常相似。不同之处在于 Ansible facts 被认为是内置变量,因此不必由管理员定义。
下一步
现在你已经拥有了开始研究 Ansible 和创建自己的 playbook 的工具。Ansible 是一个具有如此深度、复杂性和灵活性的工具,以至于在一篇文章中不可能涵盖所有内容。本文应该足以激起你的兴趣并激励你探索 Ansible 提供的可能性。在我的下一篇文章中,我将讨论 Copy、systemd、service、apt、yum、virt 和 user 模块。我们可以将这些模块组合起来创建更新和安装 playbook,并创建一个基本的 Git 服务器来存储可能创建的所有 playbook。
6 条评论