首页 > 解决方案 > 如何使用 Ansible 为 group_vars 配置属性优先级

问题描述

我的 Ansible 角色中有一个vars/sonarqube.yml包含内容的文件

---
lvm_roles:
  sonarqube:
    size: '10g'
    path: '{{ sonar_home }}'

和一个group_vars/all/lvm.yml包含内容的文件

lvm_roles:
  sonarqube:
    size: '20g'

ansible.cfg我有一条线

hash_behaviour = merge

没有merge结果的事实将是

lvm_roles:
  sonarqube:
    size: '20g'

换句话说,我失去了pathvar。

结果merge

lvm_roles:
  sonarqube:
    size: '10g'
    path: '/opt/sonarqube'

然而,我想要和预期的结果是

lvm_roles:
  sonarqube:
    size: '20g'
    path: '/opt/sonarqube'

所以期望的行为是

  1. Ansible 合并变量
  2. 在我的角色中配置group_vars优先于配置。

我可以在 Ansible 中配置此行为吗?如何?

标签: ansibleansible-facts

解决方案


优先级在 Ansible 中是不可配置的,您不能group_vars以高于vars角色目录中的配置的优先级进行配置。

你想要的是Ansible 不支持的条件默认变量。如此处所示,有条件地设置 Ansible 角色默认值,此处在 vars ansible 中使用条件

这是 Ansible 作为 IaC 工具绝对缺乏的一个领域。例如,它是 Chef 中非常常用的功能。来自Chef Apache 食谱的attributes/default.rb的片段演示了这种常见模式

....
case node['platform_family']
when 'rhel', 'fedora', 'amazon'
  if node['platform'] == 'amazon'
    default['apache']['package'] = 'httpd24'
    default['apache']['devel_package'] = 'httpd24-devel'
  else
    default['apache']['package'] = 'httpd'
    default['apache']['devel_package'] = 'httpd-devel'
  end
  default['apache']['service_name'] = 'httpd'
  default['apache']['perl_pkg']    = 'perl'
  default['apache']['apachectl']   = '/usr/sbin/apachectl'
  default['apache']['dir']         = '/etc/httpd'
  default['apache']['log_dir']     = '/var/log/httpd'

可以将目录中的配置vars与 Chef 中的“覆盖”属性进行比较。Chef 食谱中的配置具有较低的优先级,但您可以使用“覆盖”属性来提供非常高的优先级。然而,在食谱中使用“覆盖”属性是非常少见的。它们的实际用途非常有限。反之亦然,Ansiblevars目录用于创建覆盖几乎所有其他配置的高优先级配置,其实际用途非常有限。

如果您不同意,请分享我们绝对需要在角色中进行高优先级配置的角色示例。例如,您可以共享一个链接到一个演示实际使用的 Ansible 角色。

vars角色目录很有用,但不适用于其预期用途。在实践中,该目录用于存储条件配置。配置获得高优先级的事实比期望或预期的结果更成问题。

geerlingguy.posttgresql角色证明了这一点。在这个角色中,geerlingguy 使用“伪变量”来解决 Ansible 没有条件默认变量的事实。

例如在vars/Debian-7.yml中引入了一个变量__postgresql_data_dir。此变量获得高优先级。

__postgresql_data_dir: "/var/lib/postgresql/{{ __postgresql_version }}/main" 

postgresql_data_dir除了可以用来模拟条件默认变量(如tasks/variables.yml中所示)之外,它没有任何实际用途

- name: Define postgresql_data_dir.
  set_fact:
    postgresql_data_dir: "{{ __postgresql_data_dir }}"
  when: postgresql_data_dir is not defined

如果可以配置优先规则将是有意义的,因为varsAnsible 角色中的目录通常由于其高优先级而具有有限的实际用途。如geerlingguy.posttgresqlvars角色所证明的那样,postgresql_data_dir为了降低该目录中配置的优先级,需要实际使用目录技巧。

如果您不喜欢这种技巧,您可以选择使用Set Ansible role defaults 有条件地或邪恶的内联编码中所述的解决方法set_fact,如使用 vars ansible 中的条件中所述。

建议 Ansible 社区将vars目录的预期用途从“覆盖”配置更改为“条件”配置。对角色中的配置给予高优先级是非常罕见的要求。然而,条件配置非常普遍。


推荐阅读