我有以下目录结构:
├── 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
中删除了所有 dns
和 interface
行,并将它们放在
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 方式”,或者我正在尝试做什么(本质上是将同一列表的不同部分分成 hosts
和group_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.dns
或 pihole.network.interface
,映射不再存在,ansible 会引发上述错误。
这是 ansible 中的默认行为:按优先顺序用最新的变量替换先前的变量。但是您可以通过设置 hash_behaviour=merge
来更改字典的这种行为。在 ansible.cfg
中。
我对这个设置的个人实验并不十分令人满意:它在我自己的剧本/角色中表现正确,这些剧本/角色是专门为此制作的,但在包含第三方贡献(剧本片段、角色、自定义模块)时开始引发难以追踪的错误....)。所以我绝对不推荐它。而且,这个配置已经deprecated in ansible 2.10因此将在 ansible 2.14 中删除。如果你仍然想使用它,你应该尽可能地限制设置的范围,当然不要在全局级别设置它(即肯定不在 /etc/ansible/ansible.cfg
中)
我现在在全局范围内使用什么来解决这类问题:
- 为每个主机/组/任何仅包含特定信息的变量定义变量。在你的情况下为你主持
--- pihole_host: network: ipv4: "192.168.2.4/24"
- 在某处定义这些设置的默认值。在您的情况下,您的团队。
(请注意,您可以利用上述变量的优先顺序在不同级别定义这些默认值)--- pihole_defaults: dns: - "185.228.168.10" - "185.228.169.11" network: interface: eth0
- 在全局级别(我通常将其放在
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/