Теоретические основы и архитектура

Лабораторная работа: построение пайплайна непрерывной интеграции и развёртывания сетевых конфигураций (NetDevOps / CI/CD) с использованием Git, GitLab CI / GitHub Actions и виртуальных тестовых стендов (Containerlab / EVE-NG). Традиционный ручной подход к изменению конфигураций в CLI заменяется автоматизированным конвейером: 1. Инженер вносит изменения в репозиторий Git (например, добавляет нового клиента в файл customers.yml) и создаёт Merge Request. 2. Линтинг и валидация (Linting & Schema Validation): CI-раннер автоматически проверяет YAML-файл по схеме JSON Schema, проверяет корректность номеров RD/RT и отсутствие дубликатов IP-адресов. 3. Автоматическое тестирование в виртуальной среде: CI запускает тестовый стенд на Containerlab, генерирует конфигурации через Jinja2, заливает их на тестовые виртуальные маршрутизаторы и выполняет автотесты (PyATS, Robot Framework: проверка поднятия BGP, связности L3VPN, отсутствия утечки маршрутов). 4. Деплой (Canary Deployment): только после успешного прохождения всех тестов изменения раскатываются на продуктовые маршрутизаторы с возможностью автоматического отката (Automatic Rollback) при обнаружении аномалий.

Pipeline как контракт изменений

Конфигурация PE меняется не человеком на устройстве, а коммитом в Git, который проходит набор проверок. Pipeline решает три задачи: не пропустить заведомо неверное намерение (данные, политика), показать, что именно изменится (render и diff), и доставить изменение так, чтобы его можно было остановить и откатить (canary, подтверждение, rollback). Каждая стадия должна падать громко и до того, как будет затронуто следующее устройство.

СтадияЧто проверяетИнструментыЧто блокирует
lintсинтаксис YAML, стиль playbook, стабильность рендераyamllint, ansible-lint, flake8, ansible-playbook --syntax-checkбитый YAML и неверные модули
policyRT клиента из allowlist, уникальность RD, формат ASN:NNPydantic/JSON Schema, pytestутечку маршрутов между клиентами
renderдетерминированная отрисовка четырёх вендорных шаблоновJinja2 со StrictUndefinedпустые значения в конфиге
diffчто изменится относительно эталона в Git и на устройствеgit diff, --check --diff, compare_configнеожиданные удаления
staticанализ отрисованных конфигурацийBatfish (Cisco, Junos), собственные тесты на Huawei и RouterOSпетли и пересечения политик
twinживой тест в виртуальной топологииcontainerlab, vrnetlab (если есть образы)то, что статически не видно
canaryодин PE с таймером отката и пост-проверкойAnsible serial, commit confirmedмассовое повреждение
rolloutостальные PE после ручного подтвержденияwhen: manual, resource_groupгонки между пайплайнами

Данные и политика важнее синтаксиса

Синтаксические ошибки устройство отвергает само: % Invalid input видно сразу. Опасны корректные, но неверные по смыслу изменения: RT клиента A, равный RT клиента B, пересекающиеся RD, VRF, привязанный к чужому интерфейсу. Устройство примет такой конфиг без возражений, а последствия проявятся утечкой маршрутов. Поэтому главный гейт CI - политика над данными: allowlist RT по клиентам, уникальность RD на PE, запрет на import чужого RT. Отрицательный тест обязателен: коммит с RT 65000:200 для A должен ронять pipeline. Если такого теста нет, вы не знаете, работает ли гейт.

Render в Git и diff для ревью

Эффективная практика: коммитить не только данные, но и отрисованные конфигурации в rendered/<pe>.cfg. Тогда ревьюер видит в merge request настоящий diff для каждого устройства, а не абстрактное изменение YAML. Проверка идемпотентности сводится к тому, что повторный render на неизменных данных не меняет ни одного файла, а --check --diff на устройстве возвращает changed=0.

bash
# idempotency gate: second run must not change anything
python render.py --out build/
git diff --exit-code build/ rendered/
ansible-playbook pe_vrf.yml --check --diff | grep -q "changed=0"

Canary, подтверждение и откат

  • Junos: commit check, затем commit confirmed N: если финальный commit не пришёл за N минут, конфигурация откатывается сама. Это защита от потери управления.
  • IOS-XE: перед изменением сохраняется эталон (copy running-config flash:pre-change.cfg); откат через configure replace flash:pre-change.cfg. Режим configure replace ... time N запускает таймер, который нужно подтвердить командой configure confirm.
  • Huawei VRP: в VRPv8 конфигурация применяется командой commit, а история доступна через display configuration commit list; откат делают к сохранённому состоянию. Точные команды зависят от версии, их проверяют на стенде.
  • RouterOS: нет транзакций. Перед изменением делают /system/backup/save и /export; восстановление из бэкапа (/system/backup/load) перезагружает маршрутизатор, поэтому на RouterOS стратегия строится на малых идемпотентных изменениях и ручном подтверждении.

Canary - это не только один PE, но и время ожидания: пост-проверка читает состояние (RT на месте, префиксы клиента видны на втором PE, сессия с RR Established), затем срабатывает подтверждение, а при ошибке запускается откат. Откат конфигурации и возврат состояния сети - разные вещи: после отката нужен clear BGP soft, иначе таблицы не пересчитаются.

Конкуренция и дрейф

Два пайплайна, меняющих один PE одновременно, дают гонку: побеждает последний, даже если его ветка устарела. Защита: resource_group в GitLab (или concurrency в GitHub Actions), выкатка только из защищённой основной ветки, требование актуальной базы merge request, метка rendered from <sha> в конфигурации. Плановый pipeline по расписанию запускает check mode и ищет дрейф: ручную правку на устройстве, которую никто не закоммитил. Любой ненулевой diff - инцидент или задача на исправление данных.

Секреты, права и аудит

Секреты не лежат в репозитории: CI-переменные с маской и защитой, Vault, короткоживущие токены. Учётная запись автоматизации имеет минимальную роль, источник ограничен адресом runner. Журнал изменения складывается из merge request, логов pipeline, артефактов diff и записей на устройстве (show system commit на Junos, %SYS-5-CONFIG_I на IOS-XE). Требуется два утверждающих на изменения политики RT и обязательный ручной шаг перед rollout. Логи заданий не должны печатать значения секретов (no_log: true, отключённый set -x).

Виртуальный стенд как последний фильтр

Статический анализ видит только конфигурации. Containerlab с образами виртуальных маршрутизаторов проверяет реальное поведение: поднимает PE и RR, применяет сгенерированные конфигурации, проверяет vpnv4-сессии и пинг между сайтами клиента. Образы вендоров лицензируются отдельно, поэтому такой этап есть не у всех; без него canary остаётся реальной защитой на живом оборудовании.

Схема архитектуры и топология