Ansible 2.6 и network-модули: плейбук вместо трёх часов на коммутаторах Cisco
Ansible 2.6 расширил поддержку сетевых устройств. Написали network-плейбук и прогнали конфигурацию VLAN на тридцати Cisco-свитчах - вместо ручной работы через консоль.
Ansible 2.6 выпустил расширенный набор network-модулей для Cisco IOS, Juniper JunOS и других сетевых платформ, включая ios_vlan, ios_interface, junos_config и ресурсные модули с идемпотентной логикой
Долгое время у нас в голове сидело чёткое разграничение: Ansible - это для серверов, а коммутаторы и маршрутизаторы настраиваются через консоль или NMS своей вендора. Network-инженер заходит по SSH, набирает команды, сохраняет конфиг. Automation-инженер пишет плейбуки для линукс-хостов. Два мира, почти не пересекаются.
Ansible 2.6 этот барьер как минимум сильно подвинул.
Что появилось в 2.6 по сетевой части
Модули для сетевых устройств в Ansible существовали и раньше, начиная примерно с 2.1-2.2. Но там была в основном возможность запускать команды через raw или ios_command и парсить вывод - полезно, но не идемпотентно. С 2.6 появились ресурсные модули с нормальной логикой «желаемое состояние»:
ios_vlan- объявить список VLAN на Cisco IOS, модуль сам разберётся что добавить, что не трогать.ios_interface- параметры интерфейса: speed, duplex, description, shutdown/no shutdown.ios_l2_interface- назначение портов в access или trunk VLAN.ios_config- низкоуровневый модуль для произвольных конфигурационных строк с идемпотентной проверкой черезparents.junos_configиjunos_command- аналоги для JunOS с поддержкой commit/rollback.
Ключевое отличие от старых модулей - check_mode работает честно: Ansible сравнивает текущее состояние устройства с желаемым и показывает что изменится, не применяя ничего. На серверах это давно норма, на сетевом оборудовании раньше приходилось верить на слово.
Задача: VLAN на тридцати коммутаторах
Проект с которым мы пришли к этому: managed-инфраструктура клиента с парком из трёх десятков коммутаторов доступа Cisco Catalyst. Клиент открывал новый офисный блок, плюс параллельно шла небольшая реструктуризация сегментов - несколько VLAN надо было добавить на все свитчи стека, пересмотреть trunk-порты между уровнями.
До этого момента такие задачи делались руками: network-инженер садился, открывал список, заходил на каждый свитч по SSH и прогонял последовательность команд. Час-полтора на тридцать устройств, если не отвлекаться. Плюс неизбежно где-то описка в имени VLAN, где-то забытый порт - потом ловишь на следующей неделе.
Как выглядел плейбук
Инвентарь собрали в отдельную группу, connection выставили network_cli, platform - ios:
[cisco_access]
sw-floor-01 ansible_host=10.0.1.1
sw-floor-02 ansible_host=10.0.1.2
# ... и так для всех тридцати
[cisco_access:vars]
ansible_connection=network_cli
ansible_network_os=ios
ansible_user=ansible_svc
ansible_ssh_pass="{{ vault_ios_password }}"
Плейбук для VLAN-задачи получился компактным - всё состояние описано один раз в переменных:
- name: Конфигурация VLAN на коммутаторах доступа
hosts: cisco_access
gather_facts: no
vars:
required_vlans:
- { vlan_id: 110, name: CORP_USERS }
- { vlan_id: 120, name: CORP_VOIP }
- { vlan_id: 130, name: CORP_PRINTERS }
- { vlan_id: 200, name: MGMT }
- { vlan_id: 300, name: GUEST_WIFI }
tasks:
- name: Создать VLAN
ios_vlan:
vlan_id: "{{ item.vlan_id }}"
name: "{{ item.name }}"
state: present
loop: "{{ required_vlans }}"
- name: Trunk-порт к распределению
ios_l2_interface:
name: GigabitEthernet0/1
mode: trunk
trunk_vlans: "110,120,130,200,300"
state: present
Первый прогон в --check режиме показал что на большинстве свитчей VLAN 110 уже есть (старый, с другим именем), 300 нигде нет, на части устройств trunk не включён. Ansible аккуратно отобразил что изменится на каждом хосте - до применения.
Реальный прогон занял несколько минут на все тридцать устройств. Network-модули работают последовательно по умолчанию - параллельности через forks здесь меньше смысла чем на серверах, потому что каждое сетевое устройство это отдельная SSH-сессия с её connect-overhead. Но даже последовательно - несравнимо быстрее ручного обхода.
Что удивило и что напрягло
Идемпотентность на ios_vlan работает. Запустили плейбук повторно на следующий день для проверки - все таски зелёные, changed: 0. VLAN уже есть с правильным именем, модуль это видит и не трогает конфиг. Именно это и отличает resource module от ios_command с raw-командами.
ios_config с parents требует внимания. Для конфигурации, которая не ложится в готовый модуль, используем ios_config с параметром parents для контекста. Там идемпотентность работает через буквальное сравнение строк: если в конфиге написано switchport trunk allowed vlan 110,120 а у вас в плейбуке 110, 120 с пробелом - модуль считает что конфиг не применён и применяет снова. Нюанс неприятный, поймали его на stage-прогоне.
Пароли только через vault. Это не сюрприз, но важно проговорить: ansible_ssh_pass для сетевых устройств в открытую в инвентаре - это плохая идея вдвойне, потому что к сетевому оборудованию обычно нет SSH-ключей как на серверах. Ansible Vault или передача через переменную окружения - обязательно.
JunOS отдельная история. На клиентском проекте из Juniper есть только один MX на периметре. Мы его в этот плейбук не включали - решили сначала обкатать на Cisco. Модули junos_config и junos_facts выглядят зрелее чем ios-аналоги, там конфигурация через нативный Junos XML/set, и commit confirmed поддерживается. Но это отдельная задача.
Что изменилось в процессе
Прежде всего - у плейбука теперь есть --check режим. Это звучит банально, но раньше перед правками на коммутаторах проверка была только в голове инженера: «кажется, всё правильно, применяю». Теперь можно показать клиенту что именно изменится, до изменения. На сетевом оборудовании это особенно ценно - один неверный trunk-порт может уронить сегмент.
Второе - конфигурация стала артефактом в Git. VLAN-список версионируется, изменения проходят через pull request, в истории видно кто и когда добавил гостевой сегмент. На серверах это давно обычная практика, для сетевых конфигов у клиента до этого была таблица в Confluence.
Третье - повторяемость. Когда откроется следующий блок и понадобится добавить ещё десяток свитчей - берём тот же плейбук, добавляем хосты в инвентарь, запускаем. Три часа ручной работы превращаются в пятнадцать минут с проверкой.
Где мы сейчас
Один проект - не статистика, но направление понятно. Network automation через Ansible выглядит работающим для типовых задач: VLAN, интерфейсы, базовая конфигурация. Для сложных вещей - BGP-политики, многоуровневые QoS-конфиги, изменения с зависимостями - пока смотрим осторожно, там нужно больше проверок на реальных кейсах.
Следующий шаг у нас - добавить в этот же пайплайн сбор ios_facts и складывать состояние устройств в отдельный репозиторий как backup конфигурации. Это пока не готово, но идея простая: раз уж Ansible умеет читать конфиг с устройства, можно это делать по расписанию и хранить историю.