您想提升您的系统管理或 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 主机文件可以处理比我使用的功能更高级的功能。有关更多信息,请参阅 清单文档。
运行临时命令
将 SSH 密钥复制到清单中的所有服务器后,您就可以开始使用 Ansible 了。Ansible 的一个基本功能是运行临时命令的能力。语法是
ansible-a "some command"
例如,如果您想更新所有 CentOS 服务器,您可以运行
ansible centos -a 'yum update -y'
注意:基于服务器的操作系统命名组不是必需的。正如我将要讨论的,Ansible Facts 可用于收集此信息;但是,当尝试使用 Facts 时,发出临时命令变得更加复杂,因此为了方便起见,如果您管理异构环境,我建议创建一些基于操作系统的组。
这将循环遍历 centos 组中的每个服务器并安装所有更新。一个更有用的临时命令是 Ansible ping 模块,它用于验证服务器是否已准备好接收命令
ansible all -m ping
这将导致 Ansible 尝试通过 SSH 登录到清单中的所有服务器。ping 命令的截断输出可以在示例 3 中看到。
示例 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"
}
...
运行临时命令的能力对于快速任务很有用,但是如果您希望以后以可重复的方式运行相同的任务怎么办?为此,Ansible 实现了 playbook。
用于复杂任务的 Ansible playbook
Ansible playbook 是一个 YAML 文件,其中包含 Ansible 在运行期间应完成的所有指令。就本练习而言,我不会深入探讨更高级的主题,例如角色和模板。如果您有兴趣了解更多信息,文档 是一个很好的起点。
在上一节中,我鼓励您使用 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 条评论