ADG Оставить заявку
Блог Автоматизация 6 мин чтения

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 умеет читать конфиг с устройства, можно это делать по расписанию и хранить историю.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.