介绍
Ansible 是一种现代配置管理工具,可促进设置和维护远程服务器的任务,其极简设计旨在让用户快速启动和运行。Ansible 使用清单文件来跟踪哪些主机是您的基础架构的一部分,以及如何访问它们以运行命令和剧本。
您可以通过多种方式设置 Ansible 清单文件,具体取决于您的环境和项目需求。在本指南中,我们将演示如何创建清单文件并将服务器组织成组和子组,如何设置主机变量,以及如何使用模式来控制每个主机和每个组的 Ansible 命令和剧本的执行。
先决条件
为了遵循本指南,您需要:
- 一个 Ansible 控制节点:一台安装了 Ansible 并配置为使用 SSH 密钥连接到 Ansible 主机的 Ubuntu 20.04 机器。确保控制节点有一个具有 sudo 权限的普通用户并启用了防火墙,如我们的初始服务器设置指南中所述。要设置 Ansible,请按照我们关于如何在 Ubuntu 20.04 上安装和配置 Ansible 的指南进行操作。
- 两个或多个 Ansible 主机:两个或多个远程 Ubuntu 20.04 服务器。
第 1 步 – 创建自定义清单文件
安装后,Ansible 会创建一个清单文件,该文件通常位于/etc/ansible/hosts
. 当自定义清单文件未随-i
选项提供时,在剧本或命令执行期间,这是 Ansible 使用的默认位置。
即使您可以毫无问题地使用此文件,但使用每个项目的清单文件是一个很好的做法,以避免在执行命令和剧本时混合服务器。如果您将清单文件包含在项目的代码存储库中,那么拥有每个项目的清单文件也将有助于与合作者共享您的供应设置。
首先,访问您的主文件夹并创建一个新目录来保存您的 Ansible 文件:
- cd ~
- mkdir ansible
移动到该目录并使用您选择的文本编辑器打开一个新的清单文件。在这里,我们将使用nano
:
- cd ansible
- nano inventory
您的节点列表(每行一个服务器)足以设置功能清单文件。主机名和 IP 地址可以互换:
203.0.113.111
203.0.113.112
203.0.113.113
server_hostname
设置清单文件后,您可以使用该ansible-inventory
命令来验证和获取有关您的 Ansible 清单的信息:
- ansible-inventory -i inventory --list
Output{
"_meta": {
"hostvars": {}
},
"all": {
"children": [
"ungrouped"
]
},
"ungrouped": {
"hosts": [
"203.0.113.111",
"203.0.113.112",
"203.0.113.113",
"server_hostname"
]
}
}
即使我们没有在我们的清单中设置任何组,输出显示 Ansible 自动推断的 2 个不同的组:all
和ungrouped
。顾名思义,all
用于引用库存文件中的所有服务器,无论它们如何组织。该ungrouped
组用于指代未在组内列出的服务器。
使用自定义清单运行命令和剧本
要使用自定义清单文件运行 Ansible 命令,请使用以下-i
选项:
- ansible all -i inventory -m ping
这将在您的自定义清单文件中列出的所有主机ping
上执行该模块。
同样,这是使用自定义清单文件执行 Ansible playbook 的方式:
- ansible-playbook -i inventory playbook.yml
注意:有关如何连接节点的更多信息,请参阅我们的如何使用 Ansible指南,因为它演示了更多连接选项。
到目前为止,我们已经了解了如何创建基本清单以及如何使用它来运行命令和剧本。在下一步中,我们将看到如何将节点组织成组和子组。
步骤 2 — 将服务器组织成组和子组
在清单文件中,您可以将服务器组织成不同的组和子组。除了帮助保持主机井然有序之外,这种做法还将使您能够使用组变量,该功能可以极大地促进使用 Ansible管理多个暂存环境。
一个主机可以是多个组的一部分。在INI格式下面的清单文件演示了安装有四组:webservers
,dbservers
,development
,和production
。您会注意到服务器按两种不同的特性分组:它们的用途(Web 和数据库),以及它们的使用方式(开发和生产)。
[webservers]
203.0.113.111
203.0.113.112
[dbservers]
203.0.113.113
server_hostname
[development]
203.0.113.111
203.0.113.113
[production]
203.0.113.112
server_hostname
如果您要ansible-inventory
使用此清单文件再次运行该命令,您将看到以下安排:
Output{
"_meta": {
"hostvars": {}
},
"all": {
"children": [
"dbservers",
"development",
"production",
"ungrouped",
"webservers"
]
},
"dbservers": {
"hosts": [
"203.0.113.113",
"server_hostname"
]
},
"development": {
"hosts": [
"203.0.113.111",
"203.0.113.113"
]
},
"production": {
"hosts": [
"203.0.113.112",
"server_hostname"
]
},
"webservers": {
"hosts": [
"203.0.113.111",
"203.0.113.112"
]
}
}
也可以汇聚多个团体为孩子们下一个“父”组。然后将“父”称为元组。以下示例演示了另一种使用元组组织先前库存的方法,以实现可比较但更细粒度的排列:
[web_dev]
203.0.113.111
[web_prod]
203.0.113.112
[db_dev]
203.0.113.113
[db_prod]
server_hostname
[webservers:children]
web_dev
web_prod
[dbservers:children]
db_dev
db_prod
[development:children]
web_dev
db_dev
[production:children]
web_prod
db_prod
您拥有的服务器越多,分解组或创建替代安排就越有意义,以便您可以根据需要定位较小的服务器组。
第 3 步 – 设置主机别名
您可以使用别名来命名服务器,以便稍后在运行命令和剧本时引用这些服务器。
要使用别名,请包含一个以ansible_host
别名命名的变量,其中包含应响应该别名的服务器的相应 IP 地址或主机名:
server1 ansible_host=203.0.113.111
server2 ansible_host=203.0.113.112
server3 ansible_host=203.0.113.113
server4 ansible_host=server_hostname
如果您要ansible-inventory
使用此清单文件运行该命令,您将看到类似于以下内容的输出:
Output{
"_meta": {
"hostvars": {
"server1": {
"ansible_host": "203.0.113.111"
},
"server2": {
"ansible_host": "203.0.113.112"
},
"server3": {
"ansible_host": "203.0.113.113"
},
"server4": {
"ansible_host": "server_hostname"
}
}
},
"all": {
"children": [
"ungrouped"
]
},
"ungrouped": {
"hosts": [
"server1",
"server2",
"server3",
"server4"
]
}
}
请注意服务器现在是如何通过它们的别名而不是它们的 IP 地址或主机名来引用的。这使得在运行命令和剧本时更容易定位单个服务器。
第 4 步 – 设置主机变量
在节点上连接和执行命令时,可以使用清单文件设置变量,这些变量将更改 Ansible 的默认行为。这实际上是我们在上一步中设置主机别名时所做的。该ansible_host
变量告诉 Ansible 在哪里可以找到远程节点,以防使用别名来引用该服务器。
可以为每个主机或每个组设置库存变量。除了自定义 Ansible 的默认设置之外,还可以从您的 playbook 访问这些变量,从而可以对单个主机和组进行进一步自定义。
以下示例显示了在连接到此清单文件中列出的每个节点时如何定义默认远程用户:
server1 ansible_host=203.0.113.111 ansible_user=sammy
server2 ansible_host=203.0.113.112 ansible_user=sammy
server3 ansible_host=203.0.113.113 ansible_user=myuser
server4 ansible_host=server_hostname ansible_user=myuser
您还可以创建一个组来聚合具有相似设置的主机,然后在组级别设置它们的变量:
[group_a]
server1 ansible_host=203.0.113.111
server2 ansible_host=203.0.113.112
[group_b]
server3 ansible_host=203.0.113.113
server4 ansible_host=server_hostname
[group_a:vars]
ansible_user=sammy
[group_b:vars]
ansible_user=myuser
此库存安排将生成以下输出ansible-inventory
:
Output{
"_meta": {
"hostvars": {
"server1": {
"ansible_host": "203.0.113.111",
"ansible_user": "sammy"
},
"server2": {
"ansible_host": "203.0.113.112",
"ansible_user": "sammy"
},
"server3": {
"ansible_host": "203.0.113.113",
"ansible_user": "myuser"
},
"server4": {
"ansible_host": "server_hostname",
"ansible_user": "myuser"
}
}
},
"all": {
"children": [
"group_a",
"group_b",
"ungrouped"
]
},
"group_a": {
"hosts": [
"server1",
"server2"
]
},
"group_b": {
"hosts": [
"server3",
"server4"
]
}
}
请注意,所有清单变量都列在由_meta
生成的 JSON 输出的节点内ansible-inventory
。
步骤 5 — 使用模式来定位命令和剧本的执行
使用 Ansible 执行命令和剧本时,您必须提供目标。模式允许您定位清单文件中的特定主机、组或子组。它们非常灵活,支持正则表达式和通配符。
考虑以下清单文件:
[webservers]
203.0.113.111
203.0.113.112
[dbservers]
203.0.113.113
server_hostname
[development]
203.0.113.111
203.0.113.113
[production]
203.0.113.112
server_hostname
现在假设您需要执行一个仅针对生产中运行的数据库服务器的命令。在这个例子中,只有server_hostname
匹配该条件;但是,也可能是该组中有大量数据库服务器。您可以使用以下模式,而不是单独针对每个服务器:
- ansible dbservers:\&production -m ping
该&
字符代表的逻辑运算AND
,这意味着有效的目标必须是在这两个群体。因为这是在 Bash 上运行的临时命令,我们必须\
在表达式中包含转义字符。
前面的示例将仅针对同时存在dbservers
于production
组和组中的服务器。如果你想反其道而行之,只针对存在于服务器dbservers
,但不是中production
组,你可以使用下面的模式来代替:
- ansible dbservers:\!production -m ping
要指示目标不能在某个组中,您可以使用该!
字符。再一次,我们\
在表达式中包含转义字符以避免命令行错误,因为&
和!
都是可以被 Bash 解析的特殊字符。
下表包含一些不同的常见模式示例,您可以在使用 Ansible 运行命令和剧本时使用这些模式:
图案 | 结果目标 |
---|---|
all |
清单文件中的所有主机 |
host1 |
单个主机 ( host1 ) |
host1:host2 |
双方host1 并host2 |
group1 |
单组 ( group1 ) |
group1:group2 |
在所有服务器group1 和group2 |
group1:\&group2 |
只有同时在group1 和 中的服务器group2 |
group1:\!group2 |
服务器在group1 除了那些也在group2 |
有关更高级的模式选项,例如使用位置模式和正则表达式来定义目标,请参阅有关模式的 Ansible 官方文档。
结论
在本指南中,我们详细了解了 Ansible 库存。我们已经了解了如何将节点组织成组和子组,如何设置库存变量,以及如何在运行命令和剧本时使用模式来定位不同的服务器组。
在本系列的下一部分中,我们将看到如何使用 Ansible ad-hoc 命令管理多个服务器。