【发布时间】:2018-07-06 18:01:17
【问题描述】:
我打算使用 Ansible 来管理相当大的一组 Linux 服务器,它们之间有很多变化。
主机将被分组为角色,它们之间具有层次结构,有一个 common 角色,其他所有角色都依赖于它,子角色依赖于 common,并且可能有孙子角色依赖于它们,对依赖深度没有限制。
common
|___ role1
|___ role2
|___ role3
|___ role3.1
每个角色都有自己的系统配置文件模板子集。
roles/
common/
templates/
etc/
hosts
resolv.conf
tasks/
main.yml
system-settings.yml # imported in main.yml
role1/
templates/
etc/
hosts # role-specific version, overrides 'common'
httpd/
conf/
httpd.conf
tasks/
main.yml
system-settings.yml # imported in main.yml
role2/
role3/
role3.1/
棘手的部分是我想分层应用这些模板,类似于 Ansible 解析变量范围的方式。 因此,对于给定的子角色,将应用模板文件的最具体版本,如果该角色中不存在模板,则应用父角色的版本,搜索到根级别。
我已经(在某种程度上)通过将以下内容放入每个角色的system-settings.yml 来实现这一点:
- name: Create directories
file:
path: /{{ item.path }}
state: directory
mode: '{{ item.mode }}'
with_filetree: templates/
when: item.state == 'directory'
- name: Template files
template:
src: '{{ item.src }}'
dest: /{{ item.path }}
mode: '{{ item.mode }}'
with_filetree: templates/
when: item.state == 'file'
- name: Recreate symlinks
file:
src: '{{ item.src }}'
dest: /{{ item.path }}
state: link
force: yes
mode: '{{ item.mode }}'
with_filetree: templates/
when: item.state == 'link'
它有效,但不幸的是它应用了所有父角色的模板,然后是所有子角色的模板。 如果 playbook 执行由于某种原因中止,这是一种工作浪费和危险,因为主机可能会留下系统文件的通用版本。
因此,对于上面的示例树,当将role1 应用于一组主机 Ansible 时:
- 从
common角色应用/etc/hosts和/etc/resolv.conf - 从
role1角色应用/etc/hosts和/etc/httpd/conf/httpd.conf
但我希望它这样做:
- 从
common角色申请/etc/resolv.conf - 从
role1角色申请/etc/hosts(最具体的版本) - 从
role1角色申请/etc/httpd/conf/httpd.conf
由于管理开销、添加新文件或角色特定版本以覆盖我们不想更改任何剧本或其他配置。
这可以通过 Ansible 实现吗?
我可以看到使用外部脚本的可能解决方案(如https://docs.ansible.com/ansible/2.4/playbooks_loops.html#iterating-over-the-results-of-a-program-execution 中所述),但我不确定如何将角色层次结构传递到脚本中。
【问题讨论】:
-
我没有你工作的全部细节,但我认为你在 ansible 上的使用并不是最简单的,因为你试图用不同的角色修改相同的文件。创建角色对文件的修改拥有独占所有权,并根据事实和您分配给目标的角色将内容放入模板中,应该更容易和更可靠。例如,公共文件应该只在你的公共角色中修改,并且你根据模板中分配的角色放置逻辑。
标签: ansible ansible-template ansible-role