Я пытаюсь написать Ansible playbook, который выполняет несколько задач по настройке маршрутизаторов Cisco IOS.Некоторые из этих задач должны циклически перебирать переменные списка, которые определены на уровне файла переменных хоста.Например, для одного или нескольких интерфейсов настройте x на этом интерфейсе.Или, учитывая один или несколько fvrfs, настройте серверы имен для каждого fvrf.Количество интерфейсов и fvrfs являются динамическими.Есть несколько задач, которые имеют значения динамического списка, подобные этому, в роли playbook.
Проблема, с которой я сталкиваюсь, состоит в том, что переменные хоста с уникальными значениями для каждого маршрутизатора всегда устанавливаются в значения, определенные для последнегороутер в группе.Это происходит для переменных, которые являются строкой, и переменных, которые представляют собой список строк.Другими словами, hostvars маршрутизаторов, предшествующих последнему маршрутизатору в группе инвентаризации, всегда перезаписываются hostvars, определенными для последнего маршрутизатора.
Ansible Runtime:
$ 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"]
role / set-nameservers / tasks / 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 }}"
ОЖИДАЕМЫЙ РЕЗУЛЬТАТ
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
АКТУАЛЬНЫЙ РЕЗУЛЬТАТ
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 маршрутизаторами она показывала то же поведение ... используя hostvars последнего маршрутизатора в группе для всех 16 маршрутизаторов (yikes!)
Я искалв течение нескольких часов просматривал веб-страницы Ansible и много обсуждений, касающихся циклов, переменных и приоритета переменных.Я не понял, в чем проблема.Я думаю, что наиболее вероятный виновник в том, что я неправильно понимаю, как работает операция with_items
, но я не знаю, как изменить задачи, чтобы обеспечить желаемый результат, когда у каждого хоста есть уникальные списки переменных.Может ли это быть ошибкой в поведении?
Любая помощь в этом вопросе приветствуется!