Ansible:分层应用角色模板

时间:2018-07-06 18:01:17

标签: ansible ansible-template ansible-role

我打算使用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'

它可以工作,但是不幸的是,它应用了所有父角色的模板,然后应用了所有子角色的模板。 万一剧本由于某种原因中止执行,这会浪费工作,并且很危险,因为主机可能会留下系统文件的通用版本。

因此,对于上面的示例树,将role1应用于一组主机Ansible时:

  1. 应用/etc/hosts角色中的/etc/resolv.confcommon
  2. 应用/etc/hosts角色中的/etc/httpd/conf/httpd.confrole1

但我希望它这样做:

  1. /etc/resolv.conf角色申请common
  2. /etc/hosts角色(最具体的版本)中应用role1
  3. /etc/httpd/conf/httpd.conf角色申请role1

由于管理开销,添加新文件或特定于角色的版本以覆盖通用文件时,由于管理开销,模板文件不应在任务/剧本中明确列出,我们不想更改任何剧本或其他配置。

Ansible可以实现吗?

我可以看到使用外部脚本的一种可能的解决方案(如https://docs.ansible.com/ansible/2.4/playbooks_loops.html#iterating-over-the-results-of-a-program-execution中所述),但是我不确定如何将角色层次结构传递到脚本中。

1 个答案:

答案 0 :(得分:0)

我的想法:

首选: 将“公共”文件任务更改为“公共”处理程序。我选择处理程序的原因是我们可以有条件地包括处理程序。另外,我们还有角色前/后处理程序。通知角色中尚未完成的所有任务以及必须完成的任务都可以在角色扮演之前完成。

第二选择: 有条件地包含任务,我认为需要付出很多努力才能将标签附加到包含的文件中。 例如:

---
-name: task inclusion
Hosts: localhost
Gether_facts: false
Tasks:
Include: common.yaml
When: item | bool
A_list:
  -true
  -false

希望这会有所帮助。

问候 苏达喀尔