Ansible - 在 hosts.yml 和 group_vars 之间拆分 YAML 格式的变量列表

标签 ansible yaml ansible-inventory

我有以下目录结构:

├── ansible.cfg
├── hosts.yml
├── playbook.yml
├── group_vars
|   ├── all.yml
│   └── vm_dns.yml
└── roles
    └── pihole
        ├── handlers
        │   └── main.yml
        └── tasks
            └── main.yml

ansible.cfg 中,我只有:

[defaults]
inventory = ./hosts.yml

group_vars/all.yml 中,我有一些通用设置:

---
aptcachetime: 3600
locale: "en_GB.UTF-8"
timezone: "Europe/Paris"

然后在 hosts.yml 中设置我的 PiHole 虚拟机:

---
all:
  vars:
    ansible_python_interpreter: /usr/bin/python3
vm_dns:
  vars:
    dns_server: true
  hosts:
    vmb-dns:
      pihole:
        dns: 
          - "185.228.168.10"
          - "185.228.169.11"
        network:
          ipv4: "192.168.2.4/24"
          interface: eth0
    vmk-dns: 
      pihole:
        dns: 
          - "185.228.168.10"
          - "185.228.169.11"
        network:
          ipv4: "192.168.3.4/24"
          interface: eth0

此时,我没有尝试将任何变量移动到 group_vars,一切正常。
现在,我觉得可以通过将对 所有 vm_dns 主机相同的设置分解为一个 group_vars 文件来使主机文件更具可读性。所以我从 hosts.yml 中删除了所有 dnsinterface 行,并将它们放在 group_vars/vm_dns.yml 文件,像这样:

---
pihole:
  dns: 
    - "185.228.168.10"
    - "185.228.169.11"
  network:
    interface: eth0

此时,hosts.yml 包含:

---
all:
  vars:
    ansible_python_interpreter: /usr/bin/python3
vm_dns:
  vars:
    dns_server: true
  hosts:
    vmb-dns:
      pihole:
        network:
          ipv4: "192.168.2.4/24"
    vmk-dns: 
      pihole:
        network:
          ipv4: "192.168.3.4/24"

但是当我现在运行剧本时,一旦它尝试执行使用从 hosts.yml 移动到 group_vars/vm_dns.yml 的变量之一的任务>,Ansible 失败并显示 AnsibleUndefinedVariable: dict object has no attribute ...

我不太确定我是否只是误解了“Ansible 方式”,或者我正在尝试做什么(本质上是将同一列表的不同部分分成 hostsgroup_vars,我想)不仅仅是可行的。我以为 "flattening" that Ansible does本来应该处理这个问题,但似乎 Ansible 根本没有合并 group_vars/vm_dns.yml 中定义的变量。

我已经阅读了 the subject 上的文档, 并找到了一些 almost-related posts , 但没有发现以这种方式展示跨主机和 group_vars 使用的 YAML 格式列表。

编辑:与此问题实际相关的其他 SO 或 Github 问题
In Ansible, how to combine variables from separate files into one array?
https://github.com/ansible/ansible/issues/58120
https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-hash-behaviour

最佳答案

由于您在主机级别的 list 中保留了 pihole var 的定义,因此默认情况下这个定义会赢得游戏并替换先前在组级别的定义。查看variable precedence documentation .因此,如果您稍后尝试访问例如pihole.dnspihole.network.interface,映射不再存在,ansible 会引发上述错误。

这是 ansible 中的默认行为:按优先顺序用最新的变量替换先前的变量。但是您可以通过设置 hash_behaviour=merge 来更改字典的这种行为。在 ansible.cfg 中。

我对这个设置的个人实验并不十分令人满意:它在我自己的剧本/角色中表现正确,这些剧本/角色是专门为此制作的,但在包含第三方贡献(剧本片段、角色、自定义模块)时开始引发难以追踪的错误....)。所以我绝对不推荐它。而且,这个配置已经deprecated in ansible 2.10因此将在 ansible 2.14 中删除。如果你仍然想使用它,你应该尽可能地限制设置的范围,当然不要在全局级别设置它(即肯定不在 /etc/ansible/ansible.cfg 中)

我现在在全局范围内使用什么来解决这类问题:

  1. 为每个主机/组/任何仅包含特定信息的变量定义变量。在你的情况下为你主持
    ---
    pihole_host:
      network:
        ipv4: "192.168.2.4/24"
    
  2. 在某处定义这些设置的默认值。在您的情况下,您的团队。
    ---
    pihole_defaults:
      dns: 
        - "185.228.168.10"
        - "185.228.169.11"
      network:
        interface: eth0
    
    (请注意,您可以利用上述变量的优先顺序在不同级别定义这些默认值)
  3. 在全局级别(我通常将其放在 group_vars/all.yml 中),定义您的 var,它将是 default 和 specific 的组合,确保它始终默认为空
    ---
    # Calculate pihole from group defaults and host specific
    pihole: >-
      {{
        (pihole_defaults | default({}))
        | combine((pihole_host | default({})), recursive=true)
      }}
    

关于Ansible - 在 hosts.yml 和 group_vars 之间拆分 YAML 格式的变量列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62566312/

相关文章:

azure-devops - 使用来自多个存储库的 YAML 模板

Ansible,如何在主机 list 中定义列表?

python - [可靠];使用多个字典

ssh - Ansible 配置错误!无法使用 SSH 密码代替 key

ansible - 如何将var类型更改为整数?

ansible - 使用名称启动 EC2 实例

Azure-devops:共享运行各自作业的不同代理的输出

ansible - 如何避免使用ansible跳过致命的任务错误?

ubuntu - 使用 Ansible 配置 Ubuntu 16.04 Vagrant 在 chown 上失败

python - 如何在Python中的YAML文件中设置logging.handlers.SysLogHandler的输出