Теоретические основы и архитектура
Лабораторная работа: построение пайплайна непрерывной интеграции и развёртывания сетевых конфигураций (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 и неверные модули |
| policy | RT клиента из allowlist, уникальность RD, формат ASN:NN | Pydantic/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.
# 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 остаётся реальной защитой на живом оборудовании.