我正在尝试编写一个Ansible playbook,它可以运行一些任务来配置Cisco IOS路由器 . 其中一些任务需要循环遍历主变量文件级别定义的列表变量 . 例如,给定一个或多个接口,在该接口上配置x . 或者,给定一个或多个fvrf,为每个fvrf配置名称服务器 . 接口和fvrfs的数量是动态的 . 在playbook角色中有多个任务具有这样的动态列表值 .
我遇到的问题是每个路由器具有唯一值的主机变量总是被设置为为组中的最后一个路由器定义的值 . 对于作为字符串的变量和作为字符串列表的变量,会发生这种情况 . 换句话说,清单组中最后一个路由器之前的路由器的主机变量总是被为最后一个路由器定义的主机变量覆盖 .
Ansible运行时:
$ ansible --version
ansible 2.7.0
config file = /opt/ansible/ansible.cfg
configured module search path = [u'/home/<redacted>/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /home/<redacted>/mypython/lib/python2.7/site-packages/ansible
executable location = /home/<redacted>/mypython/bin/ansible
python version = 2.7.15 (default, Oct 22 2018, 15:22:25) [GCC 4.4.7 20120313 (Red Hat 4.4.7-18)]
(A) (mypython) <redacted>@<redacted_hostname> /opt/ansible
$ ansible-playbook --version
ansible-playbook 2.7.0
config file = /opt/ansible/ansible.cfg
configured module search path = [u'/home/<redacted>/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /home/<redacted>/mypython/lib/python2.7/site-packages/ansible
executable location = /home/<redacted>/mypython/bin/ansible-playbook
python version = 2.7.15 (default, Oct 22 2018, 15:22:25) [GCC 4.4.7 20120313 (Red Hat 4.4.7-18)]
目录结构:
+-- ansible.cfg
+-- inventory
| +-- lab-g2
| | +-- group_vars
| | | +-- lab-g2-crs-2900
| | | +-- host_vars
| | | | +-- 10.74.0.71.yml
| | | | +-- 10.74.0.73.yml
| | | +-- vars
| | +-- inventory
+-- library
+-- playbooks
| +-- roles -> /opt/ansible/roles
| +-- set-nameservers.yml
+-- README.md
+-- roles
| +-- set-nameservers
| +-- tasks
| +-- main.yml
playbook.yml:
---
- name: CONFIGURE NAMESERVERS ON ROUTER
hosts: all
gather_facts: no
connection: network_cli
roles:
- set-nameservers
库存文件:
[lab-g2-crs-2900]
10.74.0.71
10.74.0.73
[all:children]
lab-g2-crs-2900
组变量文件:
---
ansible_connection: network_cli
ansible_network_os: ios
主机变量文件:
10.74.0.71.yml:
fvrf: ["WAN1", "WAN2"]
umbrella_out: ["GigabitEthernet0/0"]
10.74.0.73.yml:
fvrf: ["WAN3", "WAN4"]
umbrella_out: ["GigabitEthernet0/1"]
角色/设置域名服务器/任务/ main.yml
---
- name: CONFIGURE NAMESERVERS
ios_config:
lines:
- "ip name-server vrf {{ item }} 208.67.220.220 208.67.222.222"
with_items: "{{ fvrf }}"
- name: DEBUG
debug:
msg: "fvrf name is {{ item }}"
with_items: "{{ fvrf }}"
- name: CONFIGURE UMBRELLA OUTBOUND INTERFACE
ios_config:
lines:
- "description Outbound umbrella interface"
parents: interface {{ item }}
with_items: "{{ umbrella_out }}"
- name: DEBUG
debug:
msg: "Outbound Umbrella interface is {{ item }}"
with_items: "{{ umbrella_out }}"
EXPECTED RESULT
PLAY [CONFIGURE NAMESERVERS ON ROUTER] ***************************************************************************************************************************************
TASK [set-nameservers : CONFIGURE NAMESERVERS] *******************************************************************************************************************************
changed: [10.74.0.73] => (item=WAN3)
changed: [10.74.0.71] => (item=WAN1)
changed: [10.74.0.73] => (item=WAN4)
changed: [10.74.0.71] => (item=WAN2)
TASK [set-nameservers : DEBUG] ***********************************************************************************************************************************************
ok: [10.74.0.71] => (item=WAN3) => {
"msg": "fvrf name is WAN1"
}
ok: [10.74.0.71] => (item=WAN4) => {
"msg": "fvrf name is WAN2"
}
ok: [10.74.0.73] => (item=WAN3) => {
"msg": "fvrf name is WAN3"
}
ok: [10.74.0.73] => (item=WAN4) => {
"msg": "fvrf name is WAN4"
}
TASK [set-nameservers : CONFIGURE UMBRELLA OUTBOUND INTERFACE] ***************************************************************************************************************
changed: [10.74.0.73] => (item=GigabitEthernet0/0)
changed: [10.74.0.71] => (item=GigabitEthernet0/1)
TASK [set-nameservers : DEBUG] ***********************************************************************************************************************************************
ok: [10.74.0.71] => (item=GigabitEthernet0/1) => {
"msg": "Outbound Umbrella interface is GigabitEthernet0/0"
}
ok: [10.74.0.73] => (item=GigabitEthernet0/1) => {
"msg": "Outbound Umbrella interface is GigabitEthernet0/1"
}
PLAY RECAP *******************************************************************************************************************************************************************
10.74.0.71 : ok=4 changed=2 unreachable=0 failed=0
10.74.0.73 : ok=4 changed=2 unreachable=0 failed=0
ACTUAL RESULT
PLAY [CONFIGURE NAMESERVERS ON ROUTER] ***************************************************************************************************************************************
TASK [set-nameservers : CONFIGURE NAMESERVERS] *******************************************************************************************************************************
changed: [10.74.0.73] => (item=WAN3)
changed: [10.74.0.71] => (item=WAN3)
changed: [10.74.0.73] => (item=WAN4)
changed: [10.74.0.71] => (item=WAN4)
TASK [set-nameservers : DEBUG] ***********************************************************************************************************************************************
ok: [10.74.0.71] => (item=WAN3) => {
"msg": "fvrf name is WAN3"
}
ok: [10.74.0.71] => (item=WAN4) => {
"msg": "fvrf name is WAN4"
}
ok: [10.74.0.73] => (item=WAN3) => {
"msg": "fvrf name is WAN3"
}
ok: [10.74.0.73] => (item=WAN4) => {
"msg": "fvrf name is WAN4"
}
TASK [set-nameservers : CONFIGURE UMBRELLA OUTBOUND INTERFACE] ***************************************************************************************************************
changed: [10.74.0.73] => (item=GigabitEthernet0/1)
changed: [10.74.0.71] => (item=GigabitEthernet0/1)
TASK [set-nameservers : DEBUG] ***********************************************************************************************************************************************
ok: [10.74.0.71] => (item=GigabitEthernet0/1) => {
"msg": "Outbound Umbrella interface is GigabitEthernet0/1"
}
ok: [10.74.0.73] => (item=GigabitEthernet0/1) => {
"msg": "Outbound Umbrella interface is GigabitEthernet0/1"
}
PLAY RECAP *******************************************************************************************************************************************************************
10.74.0.71 : ok=4 changed=2 unreachable=0 failed=0
10.74.0.73 : ok=4 changed=2 unreachable=0 failed=0
从输出结果中可以看出,主机文件10.74.0.73中的变量正在用于两个主机,即使10.74.0.71在单独的文件中定义了自己唯一的变量值 . 在具有相同结构和16个路由器的单独的剧本中,它显示了相同的行为...使用组中最后一个路由器的主机变量为所有16个路由器(yikes!)
我've been searching the web for a few hours and have looked through the Ansible docs and a lot of discussion here pertaining to loops, variables, and variable precedence. I haven'弄明白问题是什么 . 我认为最可能的罪魁祸首是我误解了 with_items
操作是如何工作的,但我不知道如何修改任务以确保每个主机具有唯一变量列表所需的结果 . 这可能是bug行为吗?
非常感谢您对此问题的任何帮助!
1 回答
感谢您发布目录输出,这是关键 . 这不是
with_items
's causing you the problems, it'是group_vars
中的嵌套host_vars
.如果将
host_vars
拉出group_vars
目录,它将再次开始表现得非常清醒 . 我没有挖掘分配规则以确切地知道它被取代的确切位置,但是tl; dr是顶部存储桶不是特定于主机的,即使底部存储桶是,因此:您只需使用
ansible-inventory --list
并查看_meta
中的hostvars
就可以自行确认而无需运行整个游戏手册