介绍
Ansible是一个强大的配置管理系统,用于在各种环境中设置和管理基础架构和应用程序。虽然Ansible提供易于阅读的语法,灵活的工作流程和强大的工具,但是当它们因部署环境和功能而异时,管理大量的主机可能会很困难。 在本指南中,我们将讨论使用Ansible来处理多级部署环境的一些策略。通常,对不同阶段的要求将导致不同数量和配置的部件。例如,开发服务器的内存需求可能不同于分段和生产的内存需求,并且重要的是明确控制表示这些需求的变量如何划分优先级。在本文中,我们将讨论一些可以提取这些差异的方法,以及Ansible提供的一些构造来鼓励配置重用。用Ansible管理多级环境的不完全策略
虽然有很多方法可以管理Ansible中的环境,但Ansible本身并不提供有意义的解决方案。相反,它提供了许多可用于管理环境并允许用户选择的构造。 我们将在本指南中展示方法依赖于Ansible 组变量和 多库存 。然而,还有一些值得考虑的策略。我们将探讨下面的一些想法,以及为什么在复杂环境中实施时会出现问题。 如果你想开始使用Ansible推荐的策略,请跳到节上 使用Ansible组和多个库存 。仅依赖于组变量
乍看起来,组变量可能会提供Ansible需要的环境之间的所有分隔。您可以将某些服务器指定为属于您的开发环境,而其他服务器可以分配到暂存区和生产区。 Ansible使创建组和为其分配变量变得容易。 然而,组交叉带来了这个系统的严重问题。组通常用于对多个维度进行分类。例如:- 部署环境(本地,dev,stage,prod等)
- 主机功能(网络服务器,数据库服务器等)
- 数据中心区域(NYC,SFO等)
使用组孩子建立层次结构
Ansible允许您指定使用的组其他组[ groupname :children]
清单中的语法。这使您能够命名其他组的某些组成员。子组可以覆盖父组设置的变量。 通常,这用于自然分类。例如,我们可以有一组名为
environments
,包括组
dev
,
stage
,
prod
。 这意味着我们可以在设置中的变量,
environment
组和中重写它们
dev
组。 你可以同样有一个名为父组
functions
包含组
web
,
database
和
loadbalancer
。 此用法不能解决组交集的问题,因为子组只覆盖其父。儿童组可以在父覆盖变数,但上述组织还没有建立组类之间的关系,就像
environments
和
functions
。两个类别之间的变量优先级仍然未定义。
有可能利用此系统通过设置非天然组成员身份。例如,如果要建立以下优先级,从最高优先级到最低优先级:
- 开发环境
- 地区
- 功能
示例清单
. . .
[function:children]
web
database
loadbalancer
region
[region:children]
nyc
sfo
environments
[environments:children]
dev
stage
prod
我们已经建立了这里层级结构,区域变量替代职能变量,因为该
region
组是一个子
function
组。 同样,在设置变量
environments
组可以覆盖任何其他人。 这意味着,如果我们设置相同的变量在不同的值
dev
,
nyc
,和
web
组,属于每个这些的主机将使用该变量从
dev
。 这实现了期望的结果并且也是可预测的。然而,这是不直观的,它混淆了真正的孩子和孩子之间的区别,需要建立等级。 Ansible的设计使其配置清晰,易于跟踪,即使对于新用户。这种类型的工作损害了这一目标。
使用允许显式加载顺序的Ansible构造
境内有Ansible几个结构,允许明确的变负荷排序,即vars_files
和
include_vars
。 这些可用于内
Ansible起着在文件中定义的命令明确加载其他变量。 该
vars_files
指令是一出戏的范围内有效,而
include_vars
模块可以在任务中使用。 总的想法是设置在只有基本的识别变量
group_vars
,然后利用这些加载与所需变量的其余部分正确的变量文件。 例如,少数的
group_vars
文件可能是这样的:
group_vars / dev
---
env: dev
group_vars / stage
---
env: stage
group_vars / web
---
function: web
group_vars / database
---
function: database
然后我们将有一个单独的vars文件,它定义每个组的重要变量。这些通常保持在一个单独的
vars
为了清楚目录。 不像
group_vars
文件,以打交道时
include_vars
,文件必须包括
.yml
文件扩展名。 让我们假设我们需要的设置
server_memory_size
变量在每一个不同的值
vars
文件。您的开发服务器可能会小于生产服务器。此外,您的Web服务器和数据库服务器可能有不同的内存要求:
vars / dev.yml
---
server_memory_size: 512mb
vars / prod.yml
---
server_memory_size: 4gb
vars / web.yml
---
server_memory_size: 1gb
vars / database.yml
---
server_memory_size: 2gb
然后,我们可以创建一个明确加载正确的一个剧本
vars
根据分配给来自主机的值文件
group_vars
文件。加载的文件的顺序将决定优先顺序,并且最后一个值胜出。 随着
vars_files
,一个例子戏是这样的:
example_play.yml
---
- name: variable precedence test
hosts: all
vars_files:
- "vars/{{ env }}.yml"
- "vars/{{ function }}.yml"
tasks:
- debug: var=server_memory_size
由于这些官能团最后加载,
server_memory_size
值将从取
var/web.yml
和
var/database.yml
文件:
ansible-playbook -i inventory example_play.yml
Output. . .
TASK [debug] *******************************************************************
ok: [host1] => {
"server_memory_size": "1gb" # value from vars/web.yml
}
ok: [host2] => {
"server_memory_size": "1gb" # value from vars/web.yml
}
ok: [host3] => {
"server_memory_size": "2gb" # value from vars/database.yml
}
ok: [host4] => {
"server_memory_size": "2gb" # value from vars/database.yml
}
. . .
如果我们切换要加载的文件的顺序,我们可以使部署环境变量更高的优先级:
example_play.yml
---
- name: variable precedence test
hosts: all
vars_files:
- "vars/{{ function }}.yml"
- "vars/{{ env }}.yml"
tasks:
- debug: var=server_memory_size
再次运行操作手册显示部署环境文件中应用的值:
ansible-playbook -i inventory example_play.yml
Output. . .
TASK [debug] *******************************************************************
ok: [host1] => {
"server_memory_size": "512mb" # value from vars/dev.yml
}
ok: [host2] => {
"server_memory_size": "4gb" # value from vars/prod.yml
}
ok: [host3] => {
"server_memory_size": "512mb" # value from vars/dev.yml
}
ok: [host4] => {
"server_memory_size": "4gb" # value from vars/prod.yml
}
. . .
等效剧本使用
include_vars
,经营作为一个任务,看起来像:
---
- name: variable precedence test
hosts: localhost
tasks:
- include_vars:
file: "{{ item }}"
with_items:
- "vars/{{ function }}.yml"
- "vars/{{ env }}.yml"
- debug: var=server_memory_size
这是Ansible允许显式排序的一个区域,这是非常有用的。然而,与前面的实施例一样,存在一些显着的缺点。 首先,使用
vars_files
和
include_vars
需要你地方紧密绑群体在不同的位置的变量。 该
group_vars
位置成为位于实际变量存根
vars
目录。 这再次增加了复杂性并降低了清晰度。 用户必须正确的变量文件匹配到主机,这恐怕是Ansible使用时会自动
group_vars
。 更重要的是,依靠这些技术使它们成为强制性的。每个剧本都需要一个部分,以正确的顺序显式加载正确的变量文件。没有这个的游戏将无法使用关联的变量。此外,运行
ansible
的即席任务命令将是任何依赖变量几乎完全是不可能的。
Ansible推荐策略:使用组和多个库存
到目前为止,我们已经研究了管理多级环境的一些策略,并讨论了为什么它们可能不是一个完整的解决方案。然而,Ansible项目确实提供了一些关于如何最好地在环境中抽象基础结构的建议。 推荐的方法是通过完全分离每个操作环境来与多级环境一起工作。不是在单个清单文件中维护所有主机,而是为每个单独的环境维护一个清单。独立group_vars
目录也保持。 基本目录结构看起来像这样:
.
├── ansible.cfg
├── environments/ # Parent directory for our environment-specific directories
│ │
│ ├── dev/ # Contains all files specific to the dev environment
│ │ ├── group_vars/ # dev specific group_vars files
│ │ │ ├── all
│ │ │ ├── db
│ │ │ └── web
│ │ └── hosts # Contains only the hosts in the dev environment
│ │
│ ├── prod/ # Contains all files specific to the prod environment
│ │ ├── group_vars/ # prod specific group_vars files
│ │ │ ├── all
│ │ │ ├── db
│ │ │ └── web
│ │ └── hosts # Contains only the hosts in the prod environment
│ │
│ └── stage/ # Contains all files specific to the stage environment
│ ├── group_vars/ # stage specific group_vars files
│ │ ├── all
│ │ ├── db
│ │ └── web
│ └── hosts # Contains only the hosts in the stage environment
│
├── playbook.yml
│
└── . . .
正如你所看到的,每个环境是不同的和分隔的。环境目录中包含一个清单文件(任意命名的
hosts
)和一个独立
group_vars
目录。 目录树中有一些明显的重复。有
web
和
db
文件为每个环境。 在这种情况下,需要重复。 通过首先在一个环境中修改变量,并在测试后将它们移动到下一个,可以跨环境推出变量更改,就像对代码或配置更改一样。 该
group_vars
变量跟踪每个环境的当前默认值。 一个限制是无法根据跨环境的功能选择所有主机。幸运的是,这与上面的可变重复问题属于同一类别。尽管为某个任务选择所有Web服务器有时很有用,但是您几乎总是希望逐个推出所有环境中的更改。这有助于防止错误影响您的生产环境。
设置跨环境变量
在推荐的设置中不可能的一件事是跨环境的可变共享。有很多方法可以实现跨环境变量共享。最简单的方法之一是利用Ansible的能力来使用目录代替文件。我们可以更换all
的每个中的文件
group_vars
与目录中
all
目录。 在目录中,我们可以再次在文件中设置所有特定于环境的变量。然后,我们可以创建指向包含跨环境变量的文件位置的符号链接。这两个都将应用于环境中的所有主机。 首先在层次结构中的某个位置创建一个跨环境变量文件。在这个例子中,我们将其放置在
environments
的目录。将所有跨环境变量放在该文件中:
cd environments
touch 000_cross_env_vars
接下来,将进入一个
group_vars
目录下,重命名
all
文件,并创建
all
目录。将重命名的文件移动到新目录中:
cd dev/group_vars
mv all env_specific
mkdir all
mv env_specific all/
接下来,您可以创建一个指向跨环境变量文件的符号链接:
cd all/
ln -s ../../../000_cross_env_vars .
当您为每个环境完成上述步骤后,您的目录结构将如下所示:
.
├── ansible.cfg
├── environments/
│ │
│ ├── 000_cross_env_vars
│ │
│ ├── dev/
│ │ ├── group_vars/
│ │ │ ├── all/
│ │ │ ├── 000_cross_env_vars -> ../../../000_cross_env_vars
│ │ │ │ └── env_specific
│ │ │ ├── db
│ │ │ └── web
│ │ └── hosts
│ │
│ ├── prod/
│ │ ├── group_vars/
│ │ │ ├── all/
│ │ │ │ ├── 000_cross_env_vars -> ../../../000_cross_env_vars
│ │ │ │ └── env_specific
│ │ │ ├── db
│ │ │ └── web
│ │ └── hosts
│ │
│ └── stage/
│ ├── group_vars/
│ │ ├── all/
│ │ │ ├── 000_cross_env_vars -> ../../../000_cross_env_vars
│ │ │ └── env_specific
│ │ ├── db
│ │ └── web
│ └── hosts
│
├── playbook.yml
│
└── . . .
内设置的变量
000_cross_env_vars
文件将提供给各环境的具有低优先级。
设置默认环境清单
它可以设定在一个默认清单文件ansible.cfg
文件。这是一个好主意,有几个原因。 首先,它允许你离开了明确的库存标志
ansible
和
ansible-playbook
。所以不要输入:
ansible -i environments/dev -m ping
您可以通过键入以下内容访问默认广告资源:
ansible -m ping
其次,设置默认清单有助于防止意外更改意外影响登台或生产环境。默认情况下,您的开发环境中,最不重要的基础架构会受到更改的影响。推动修改新的环境则是一个明确的操作要求的
-i
标志。 要设置默认目录,打开你的
ansible.cfg
文件。 这可能是在项目的根目录下,或在
/etc/ansible/ansible.cfg
根据您的配置。
注:下面的例子演示编辑ansible.cfg
在项目目录中的文件。
如果您使用的是/etc/ansibile/ansible.cfg
进行更改文件,修改下面的编辑路径。
当使用/etc/ansible/ansible.cfg
,如果你的库存保持在外面/etc/ansible
目录,确保设置时要使用绝对路径,而不是相对路径的inventory
价值。
nano ansible.cfg
如上所述,建议将开发环境设置为默认清单。注意我们如何选择整个环境目录,而不是它包含的主机文件:
[defaults]
inventory = ./environments/dev
您现在应该能够使用默认的库存没有
-i
选项。 非默认的库存仍然需要使用
-i
,这有助于保护他们免受意外更改。