背景:我想写一个适用于不同操作系统的ansible playbook。它的基本功能之一是使用DbSet
命令安装软件包(在ansible 2.0中新引入)。
问题是每个操作系统上的软件包列表都不同。我想在某处指定常用的,然后分别放置Ubuntu特定的和CentOS特定的。那么对于CentOS,CentOS6和CentOS7也有一些常见的和不同的,所以我想在某处为CentOS放置常用的,在其他地方放置CentOS6和CentOS7。
我想到的最直接的方法就是拥有group_vars,但是,我知道的方式不会起作用。假设在group_vars下我有文件all,ubuntu,centos,centos6和centos7来定义变量,其优先顺序是不确定的。对于CentOS6主机,它分为all,centos和centos6。无法指定package
应优先于centos6
且centos
超过centos
。
我找到的另一种方法是在ansible.cfg中设置all
,然而,这会修改全局行为,这会过度杀伤。可能存在需要默认行为的情况,因此全局修改它并不是一个好方法。
我应该如何以干净的方式组织所有事情,尽可能地分享和重复使用普通事物?
答案 0 :(得分:3)
我使用的一种常见方法是在角色的vars
目录中定义OS专用默认变量文件,然后将它们包含在main.yml
任务的开头。 Ansible帮助我使用{{ ansible_distribution }}
和{{ ansible_distribution_version }}
自动识别当前使用的分配,因此我只需相应地命名OS专用的yml文件。
角色目录树
my_role/
├── handlers
│ ├── main.yml
│ └── Ubuntu14.04.yml
├── tasks
│ ├── main.yml
│ └── Ubuntu14.04.yml
├── templates
│ └── Ubuntu14_04.config.j2
└── vars
└── Ubuntu14.04.yml
在main.yml
中,您首先包含默认的操作系统特定变量,然后运行特定于操作系统的任务:
<强>任务/ main.yml:强>
---
- name: include distribution specific vars
include_vars: "{{ ansible_distribution }}{{ ansible_distribution_version }}.yml"
- name: include distribution specific install
include: "{{ ansible_distribution }}{{ ansible_distribution_version }}.yml"
- name: Do general stuff
...
现在,您可以在每个发行版的vars文件中轻松定义包,例如,Ubuntu14.04:
<强>乏/ Ubuntu14.04.yml:强>
---
my_role_packages:
- a
- b
最后将它们安装在您的分发特定设置任务中。
<强>任务/ Ubuntu14.04.yml:强>
---
- name: Install packages for Ubuntu14.04
apt:
name={{ item }}
state=present
update_cache=yes
with_items: "{{ my_role_packages }}"
您现在还可以轻松定义特定于操作系统的处理程序和模板,例如:
<强>处理程序/ main.yml:强>
---
- name: distribution specific handler
include: "{{ ansible_distribution }}{{ ansible_distribution_version }}.yml"
关于全局设置hash_behaviour=merge
,此处引用official Ansible documentation:
有些用户更喜欢哈希变量(又名'词典') 在Python术语中)合并。此设置称为“合并”。 除非您认为,否则我们通常建议您不要使用此设置 绝对需要它,以及官方例子中的剧本 repos不使用此设置。
最初我来自SaltStack世界并且习惯于将默认值map.jinja
中的哈希值与专用支柱合并,但在Ansible中我开始更多地依赖变量前缀,因此不是
nginx:
pkg: "nginx"
repo: "deb http://nginx.org/packages/ubuntu/ trusty nginx"
我会写
nginx_pkg: "nginx"
nginx_repo: "deb http://nginx.org/packages/ubuntu/ trusty nginx"
为了避免在上升变量层次结构时意外覆盖哈希值。如果在某些情况下您仍然喜欢合并,则可以在变量文件中使用jinja2 combine
过滤器:dict_a: {{ dict_b|combine(dict_c) }}
。
Ansible文档强调大量使用group_vars
,我发现这是一个很好的建议。这里的一般方法是在我的库存文件中定义我的组,例如:
<强>主机/测试强>
[app]
app-test-a
app-test-b
[app_test:children]
app
<强>主机/活强>
[app]
app-live-a
app-live-b
[app_live:children]
app
现在我可以轻松地使用group_vars
根据定义的组包含变量:
group_vars/
├── all.yml
├── app_test.yml
├── app_live.yml
└── app.yml
我还建议您查看Ansible Galaxy个角色。他们总是一个很好的起点来获得一些想法(包括这个想法)。另一个很好的灵感来源是DebObs repository。