Ansible - 在 hosts.yml 和 group_vars 之间拆分 YAML 格式的变量列表
Ansible - splitting YAML-formatted list of vars across hosts.yml and group_vars
我的目录结构如下:
├── 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,一切正常。
现在,我觉得可以通过将 all 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, and found some 上的文档,但发现 none 演示了跨主机使用的 YAML 格式列表,并且 group_vars 以这种方式使用。
编辑:与此问题实际相关的其他 SO 或 Github 问题
https://github.com/ansible/ansible/issues/58120
https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-hash-behaviour
由于您在主机级别的清单中保留了 pihole
var 的定义,因此默认情况下这个变量会赢得游戏并取代之前在组级别的定义。参见variable precedence documentation。因此,如果您稍后尝试访问例如pihole.dns
或 pihole.network.interface
,映射不再存在,ansible 会触发上述错误。
这是 ansible 中的默认行为:按优先顺序用最新的变量替换先前的变量。但是您可以通过在 ansible.cfg
.
中设置 hash_behaviour=merge
来更改字典的这种行为
我个人对此设置的实验并不十分令人满意:它在我自己的 playbooks/roles 中表现正确,但在包含第三方贡献(剧本片段,角色、自定义模块....)。所以我绝对不推荐它。此外,此配置已 deprecated in ansible 2.10 因此将在 ansible 2.14 中删除。如果你仍然想使用它,你应该将设置的范围限制得尽可能小,当然不要在全局级别设置它(即肯定不会在/etc/ansible/ansible.cfg
)
我现在全球使用的解决这类问题的方法:
- 为每个只包含特定信息的 host/group/whatever 定义变量。在你的情况下为你主持
---
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.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,一切正常。
现在,我觉得可以通过将 all 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, and found some
编辑:与此问题实际相关的其他 SO 或 Github 问题
https://github.com/ansible/ansible/issues/58120
https://docs.ansible.com/ansible/latest/reference_appendices/config.html#default-hash-behaviour
由于您在主机级别的清单中保留了 pihole
var 的定义,因此默认情况下这个变量会赢得游戏并取代之前在组级别的定义。参见variable precedence documentation。因此,如果您稍后尝试访问例如pihole.dns
或 pihole.network.interface
,映射不再存在,ansible 会触发上述错误。
这是 ansible 中的默认行为:按优先顺序用最新的变量替换先前的变量。但是您可以通过在 ansible.cfg
.
hash_behaviour=merge
来更改字典的这种行为
我个人对此设置的实验并不十分令人满意:它在我自己的 playbooks/roles 中表现正确,但在包含第三方贡献(剧本片段,角色、自定义模块....)。所以我绝对不推荐它。此外,此配置已 deprecated in ansible 2.10 因此将在 ansible 2.14 中删除。如果你仍然想使用它,你应该将设置的范围限制得尽可能小,当然不要在全局级别设置它(即肯定不会在/etc/ansible/ansible.cfg
)
我现在全球使用的解决这类问题的方法:
- 为每个只包含特定信息的 host/group/whatever 定义变量。在你的情况下为你主持
--- 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) }}