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

Ansible 2.4: network automation для Cisco IOS - переходим на ios_config без expect

Ansible 2.4 закрепил network-модули для Cisco IOS/NX-OS. Разбираем ios_config и ios_command на реальном кейсе: конфигурируем VLAN и ACL без ручного CLI.

Контекст момента

Ansible 2.4 закрепляет network-модули для Cisco IOS/NX-OS - ios_config и ios_command становятся полноценными инструментами управления сетевым оборудованием

Ansible 2.4 вышел осенью, и главное что нас там интересовало - не новые connection-плагины и не улучшенный include_tasks, а network-модули. Конкретно: ios_config, ios_command, ios_facts для Cisco IOS и первые модули под NX-OS. В 2.2 они появились как «вот это есть, попробуйте», в 2.4 стало понятно что команда всерьёз намерена делать из Ansible инструмент управления сетью, а не только серверами. Мы это восприняли с умеренным оптимизмом и пошли проверять на живой инфраструктуре.

Почему вообще это важно

У нас в нескольких клиентских средах есть Cisco - коммутаторы доступа и ядра, в одном месте NX-OS на агрегации. До Ansible 2.2 автоматизация сетевых устройств выглядела примерно так: либо Python с Paramiko и написанным вручную expect-автоматом, либо RANCID с шаблонами, либо просто руками через SSH. Все варианты были отдельным инструментом, отдельной базой знаний, отдельным местом где что-то могло пойти не так независимо от основного Ansible-пайплайна.

В 2017-м мы переписали обёртки под сетевое оборудование на ios_config - убрали три скрипта на expect, которые падали при каждом обновлении прошивки. Но тогда делали осторожно: сложные сценарии по-прежнему руками. 2.4 даёт достаточно уверенности чтобы двигаться дальше.

Что конкретно добавилось в 2.4

Ключевое изменение - network_cli как отдельный connection-плагин. Раньше модули ходили на устройства через local connection, то есть Ansible запускал задачи на control node, а модуль сам открывал SSH. Это создавало проблемы с параллельным запуском и с тем как работал become (вход в enable mode).

С network_cli устройство трактуется как обычный managed host, только вместо Python на другом конце - CLI коммутатора. Плагин знает как разбирать промпты IOS, как входить в enable, как обрабатывать --More-- в длинном выводе. Для инвентаря это означает:

[cisco_switches]
sw-core-01 ansible_host=192.168.1.1
sw-access-02 ansible_host=192.168.1.2

[cisco_switches:vars]
ansible_network_os=ios
ansible_connection=network_cli
ansible_become=yes
ansible_become_method=enable

Credentials - через ansible_user / ansible_password в vault, как обычно.

Реальный кейс: VLAN и ACL через playbook

Конкретная задача: на объекте добавили новый сегмент для IoT-устройств, нужно создать VLAN 150 на четырёх коммутаторах доступа, назначить его на несколько access-портов и добавить ACL на uplink. Раньше это делалось руками по SSH на каждый свич - двадцать минут суеты, высокий шанс опечататься в номере VLAN или забыть один из портов.

Playbook выглядит так:

- name: Configure IoT VLAN
  hosts: cisco_switches
  gather_facts: no

  tasks:
    - name: Create VLAN 150
      ios_config:
        lines:
          - vlan 150
          - name IoT-segment

    - name: Assign access ports to VLAN 150
      ios_config:
        parents: "interface {{ item }}"
        lines:
          - switchport mode access
          - switchport access vlan 150
          - spanning-tree portfast
      loop: "{{ iot_ports }}"

    - name: Apply ACL on uplink
      ios_config:
        parents: "interface GigabitEthernet0/1"
        lines:
          - ip access-group IoT-UPLINK-IN in

Переменная iot_ports - список интерфейсов из host_vars для каждого коммутатора. У каждого свича своё.

ios_config сравнивает желаемое состояние с текущим конфигом через show running-config - если строка уже есть, changed не выставляется. Это и есть та идемпотентность которую раньше нужно было писать руками. Повторный прогон - никаких изменений, только подтверждение что всё на месте.

Где трётся

Идемпотентность работает, но не магически. Несколько мест где нужно знать заранее:

  • Форматирование IOS. show running-config иногда возвращает строки с отступами или в другом порядке чем то что прописано в lines:. Модуль сравнивает текстово, и бывают ложные changed. Лечится через diff_ignore_lines или через match: strict / match: line в зависимости от ситуации. Нужно проверять поведение на конкретном IOS-версии.
  • ACL - отдельная история. Добавить строку в ACL через ios_config просто, удалить сложнее - нет механизма «убрать строку если её нет в desired state». Для ACL лучше использовать ios_config с replace: block и передавать весь блок целиком.
  • NX-OS отличается. Мы попробовали перенести тот же подход на один NX-OS-свич - там свой синтаксис конфигурации, и плагин nxos_config ведёт себя немного иначе. Не критично, но один в один не перенесётся.

ios_command для диагностики

Параллельно с ios_config хорошо работает ios_command - выполняет произвольные show-команды и возвращает их вывод. Используем в двух сценариях.

Первый - сбор инвентаря перед изменениями:

- name: Show current VLAN database
  ios_command:
    commands:
      - show vlan brief
      - show interfaces trunk
  register: vlan_state

Вывод пишем в файл как документацию состояния «до». Потом если что-то пошло не так - есть с чем сравнивать.

Второй - проверка после применения конфига. ios_command с wait_for умеет ждать пока в выводе не появится нужная строка:

- name: Verify VLAN 150 is active
  ios_command:
    commands:
      - show vlan id 150
    wait_for:
      - result[0] contains "active"

Это удобнее чем ручная проверка через SSH после прогона.

Куда двигаемся

На managed-инфраструктуре сетевое оборудование у клиентов - это обычно несколько свичей доступа и один-два коммутатора уровня ядра. Не гигантская сеть, но достаточно чтобы ручные изменения регулярно давали мелкие расхождения между устройствами. Ansible с network_cli закрывает именно это: один playbook, все устройства, идемпотентный прогон, история в Git.

Пока не автоматизируем: изменения топологии (trunk-порты, etherchannel), работу с routing на IOS. Это сложнее и требует более тщательного тестирования на стенде прежде чем трогать продакшн. BGP-конфигурацию через Ansible мы видели в документации, но это отдельная история с отдельными рисками.

Сейчас примерно половина сетевых изменений на обслуживаемых объектах идёт через playbooks, половина - ещё руками. Хотим перевернуть это соотношение к середине года.

Контакт

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

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