7. Оркестрация#
Команда сетевых инженеров сделала всё правильно. У них был надёжный Источник истины, хорошо протестированные плейбуки для каждой операции и чёткая инструкция по их выполнению. На бумаге развёртывание нового VLAN-сервиса было полностью автоматизировано. На практике это занимало полдня и требовало участия одного конкретного инженера.
Этот инженер знал последовательность. Сначала проверить полноту данных SoT. Затем запустить плейбук предварительной проверки. Затем просмотреть вывод, найти устройства с ошибками и решить, продолжать ли. Затем запустить плейбук развёртывания. Затем ждать. Затем запустить плейбук валидации. Затем вручную обновить тикет ServiceNow. Если какое-то устройство дало сбой на полпути — откатить его до того, как остальные это заметят. Всё это было в инструкции, шаг за шагом, в общем документе, который никто другой полностью не усвоил.
Когда она ушла в отпуск, развёртывания остановились. Когда младший инженер попробовал выполнить последовательность и перепутал порядок, сеть оставалась в частичном состоянии шесть часов. Автоматизация существовала. Координация по-прежнему оставалась ручной.
Вот проблему, которую решает эта глава. Оркестрация — это строительный блок, превращающий набор инструментов автоматизации в систему, ведущую себя как единое целое. Она координирует другие блоки, решает, когда они должны действовать, корректно обрабатывает сбои, отслеживает каждое решение и делает всё это без инженера, вручную управляющего потоком посередине.
7.1. Основы#
7.1.1. Контекст#
Каждый рассмотренный нами строительный блок хорошо делает одно дело. Источник истины хранит намерение. Исполнитель применяет его. Сборщик получает состояние. Наблюдаемость осмысливает это состояние. Каждый — специалист, а специалистам нужен соединитель: кто-то, решающий, когда каждому действовать, что делать с результатом и как восстанавливаться при сбоях.
Этим соединителем является Orchestrator.
В Главе 3 мы поместили его в центр фреймворка NAF как блок, координирующий все остальные. Глава 5 показала, как Исполнитель применяет изменения конфигурации; Глава 6 показала, как Наблюдаемость валидирует результаты. Эта глава показывает, как Оркестратор упорядочивает и то, и другое, и обрабатывает всё, что может пойти не так между ними.
Без оркестрации вы не запускаете автоматизацию. Вы запускаете скрипты, которые кто-то должен вызывать в правильном порядке, в правильное время и правильно интерпретировать. Это автоматизация только по названию.
7.1.2. Цели#
Оркестратору необходимо выполнять пять целей:
Координировать многоблочные рабочие процессы от начала до конца. Развёртывание — это не одно действие; это последовательность: проверить намерение в SoT, выполнить предварительные проверки, применить конфигурацию, проверить результат, уведомить заинтересованные стороны. Оркестратор удерживает всю последовательность вместе.
Реагировать на события автоматически, с инициированием человеком или без него. Утверждение в ServiceNow, оповещение Наблюдаемости, запланированное сканирование соответствия: всё это должно запускать рабочий процесс без того, чтобы человек вручную его стартовал.
Устойчивое и масштабируемое выполнение. Рабочий процесс, затрагивающий 800 коммутаторов параллельно, должен надёжно завершаться. Он должен переживать перезапуск. Он должен обрабатывать частичные сбои, не теряя работу, выполненную на успешных устройствах.
Обеспечивать видимость, защищённую от фальсификации. Операторы должны видеть, что работает прямо сейчас. Аудиторы должны видеть, что запускалось в прошлом месяце, кто это запустил, какая версия рабочего процесса выполнялась и что произвёл каждый шаг. Оба требования должны удовлетворяться из одной системы.
Управлять определениями рабочих процессов как производственным ПО. Рабочий процесс, настраивающий 800 производственных коммутаторов, не может меняться небрежно. Логика сама по себе должна быть сохранена, версионирована, протестирована и продвинута в продакшен с той же дисциплиной, что применяется к любому коду, работающему в продакшене.
7.1.3. Столпы#
Пять столпов поддерживают эти цели:
- Движок рабочих процессов: определять, запускать и отслеживать многошаговые процессы
- Уровень инициирования: ручной, по расписанию, событийно-управляемый, webhook
- Устойчивое выполнение: рабочий процесс переживает перезапуск; поддерживает повторные попытки, откат и параллельные операции на сотнях устройств без узких мест на устройство
- Аудит и наблюдаемость: каждый шаг залогирован, каждое решение прослеживаемо
- Управление конвейерами: безопасное сохранение, версионирование и продвижение определений рабочих процессов в продакшене
7.1.4. Область применения#
Оркестратор координирует. Он не действует.
В области применения:
- Координация других строительных блоков
- Определение логики рабочих процессов и зависимостей шагов
- Обработка инициирования из нескольких источников
- Отслеживание состояния выполнения и создание аудиторских следов
- Управление решениями об откате при сбое шагов
За пределами области применения:
- Выполнение изменений на устройствах (это Executor)
- Хранение операционного состояния сети (это Observability)
- Хранение сетевого намерения (это Источник истины)
Распространённая ошибка — построение Оркестратора, дублирующего обязанности по выполнению или хранению своих соседних блоков. Интерфейс между блоками должен оставаться чистым.
Оркестратор, также хранящий учётные данные, управляющий инвентарём устройств или запускающий собственный движок конфигурации, превратился в нечто иное. Если ваш инструмент оркестрации начинает поглощать ответственности других блоков — у вас проблема архитектурной связанности, которую будет дорого распутать позже.
7.2. Функциональные возможности#
Пять целей и столпов реализуются через пять основных функциональных возможностей. Каждая напрямую соответствует одной цели и её поддерживающему столпу:
- Движок рабочих процессов: как структурируются рабочие процессы и как координируются шаги
- Инициирование: как и когда запускаются рабочие процессы и что получает вызывающая сторона
- Устойчивость и масштаб: как рабочие процессы надёжно завершаются при сбоях и больших объёмах
- Состояние и прослеживаемость: отслеживание состояния выполнения и создание защищённых от фальсификации аудиторских записей
- Управление конвейерами: безопасное хранение и управление определениями рабочих процессов в продакшене
graph LR
subgraph Goals
direction TB
A1[Coordinate multi-block workflows end-to-end]
A2[React to events automatically]
A3[Resilient and scalable execution]
A4[Tamper-evident visibility and audit]
A5[Safe changes to production pipelines]
end
subgraph Pillars
direction TB
B1[Workflow engine: define, run, track]
B2[Triggering layer: manual, scheduled, event-driven]
B3[Resilient execution: durable, retry, rollback at scale]
B4[Audit and observability: every step logged]
B5[Pipeline management: persist, version, promote safely]
end
subgraph Functionalities
direction TB
C1[Workflow Engine]
C2[Triggering]
C3[Resilience and Scale]
C4[State and Traceability]
C5[Pipeline Management]
end
A1 --> B1 --> C1
A2 --> B2 --> C2
A3 --> B3 --> C3
A4 --> B4 --> C4
A5 --> B5 --> C5
classDef row1 fill:#eef7ff,stroke:#4a90e2,stroke-width:1px;
classDef row2 fill:#ddeeff,stroke:#4a90e2,stroke-width:1px;
classDef row3 fill:#cce5ff,stroke:#4a90e2,stroke-width:1px;
classDef row4 fill:#b3d8ff,stroke:#4a90e2,stroke-width:1px;
classDef row5 fill:#99ccff,stroke:#4a90e2,stroke-width:1px;
class A1,B1,C1 row1;
class A2,B2,C2 row2;
class A3,B3,C3 row3;
class A4,B4,C4 row4;
class A5,B5,C5 row5;
7.2.1. Движок рабочих процессов#
Движок рабочих процессов — это сердце Оркестратора. Он определяет многошаговые процессы, выполняет их, отслеживает их состояние и управляет взаимосвязями между шагами.
Прежде чем переходить к паттернам, стоит назвать четыре фундаментальных подхода к координации, поскольку этот выбор определяет всё остальное.
7.2.1.1. Подходы к координации#
Монолит (императивная программа): единый Python-скрипт последовательно вызывает каждый шаг, ожидает каждого результата и решает, что делать дальше. Просто написать, и многие команды начинают здесь. Проблема — долговечность: если скрипт падает на шаге 5 из 10, вы начинаете сначала. Между запусками нет постоянного состояния. Параллелизм шагов также невозможен без написания собственной логики потоков. Работает для небольших, быстрых операций; ломается под нагрузкой и ненадёжной инфраструктурой. На практике это то, что блок Исполнителя уже предоставляет: скрипт, вызываемый оператором. Называть это оркестрацией — щедро.
Рабочий процесс (на основе DAG): здесь оркестрация действительно начинается. Шаги определяются как ориентированный ациклический граф, где каждый узел — задача, а рёбра выражают зависимости. Движок отслеживает состояние на узел: при перезапуске после сбоя повторно выполняются только неудавшиеся или незавершённые шаги. Параллелизм встроен: независимые ветви выполняются параллельно. Это доминирующий подход для продакшен-оркестрации и наиболее проверенный для сетевой автоматизации. Инструменты в этой категории включают Prefect, Temporal и шаблоны рабочих процессов AWX.
Хореография (событийно-управляемая, без центрального координатора): Оркестратора нет. Каждый компонент реагирует на события, опубликованные другими: Исполнитель публикует «развёртывание завершено», система Наблюдаемости потребляет это и запускает валидацию, система уведомлений потребляет результат валидации. Связанность между компонентами слабая, что упрощает добавление новых потребителей. Недостаток: нет единого места для понимания полного состояния рабочего процесса. Отладка сбоев между сервисами требует корреляции событий из нескольких систем. Этот подход работает для простых реактивных паттернов, но плохо масштабируется по сложности.
Агентный (цикл восприятие-логика-действие): Large Language Model (LLM) или ИИ-система выступает логическим уровнем. Агент наблюдает текущее состояние из блоков Наблюдаемости или SoT, рассуждает о том, какое действие устраняет разрыв, вызывает Исполнитель и повторно наблюдает для проверки результата. Вместо следования предопределённому графу рабочего процесса он принимает решения динамически во время выполнения. Это подход, обменивающий детерминизм на гибкость и образующий архитектурную основу для автономных сетей. Раздел 7.2.7 рассматривает его подробно; Глава 17 расширяет его до полной автономии.
Большинство команд начинают с подхода Монолита и переходят к рабочему процессу (на основе DAG) по мере взросления автоматизации. Хореография редко является правильным выбором для сетевых операций, поскольку требования к аудиту и прослеживаемости делают центральный координатор ценным. Агентные подходы реальны, но пока не являются стандартом для производственных сетевых операций.
7.2.1.2. Паттерны рабочих процессов#
В рамках подхода на основе DAG четыре паттерна охватывают большинство реальных рабочих процессов сетевой автоматизации:
Последовательный: шаги выполняются один за другим; каждый зависит от успешного завершения предыдущего. Уместен при строгой необходимости порядка: проверить намерение, затем предварительно проверить, затем выполнить, затем верифицировать.
Параллельный (расширение/сужение, fan-out/fan-in): несколько независимых шагов выполняются параллельно. Шаг расширения запускает множество параллельных задач (по одной на устройство или на здание); шаг сужения ждёт завершения всех них перед продолжением. Необходим для операций на сотнях устройств: без расширения 10-секундная операция на устройство для 800 устройств занимает последовательно более двух часов.
Условное ветвление: путь зависит от состояния во время выполнения. Предварительная проверка прошла? Переходим к выполнению. Не прошла? Переходим к прерыванию и уведомлению. Определение рабочего процесса включает узлы решений, оценивающие результаты и выбирающие следующий шаг.
Паттерн Saga: для длительных рабочих процессов паттерн Saga добавляет компенсирующие транзакции к каждому шагу. Если рабочий процесс успешен до шага N, а затем даёт сбой — он выполняет компенсирующие действия для шагов N-1 по 1 в обратном порядке, возвращая систему в известное исправное состояние. Именно так работает откат на уровне оркестрации: не путём повторного запуска всего рабочего процесса, а путём выполнения обратного каждого успешного шага.
flowchart TD
subgraph Sequential
S1[Step A] --> S2[Step B] --> S3[Step C]
end
subgraph FanOut["Fan-out and Fan-in"]
F0[Start] --> F1[Device 1]
F0 --> F2[Device 2]
F0 --> F3[Device N]
F1 --> FJ[Fan-in]
F2 --> FJ
F3 --> FJ
end
subgraph Saga["Saga - rollback on failure"]
P1[Step 1] --> P2[Step 2] --> P3[Step 3]
P3 -- fail --> R3[Rollback 3]
R3 --> R2[Rollback 2]
R2 --> R1[Rollback 1]
end
Паттерн Saga также является структурной основой для поэтапных выкатываний: развёртывания сетевых изменений волнами, а не сразу. Волна 1 охватывает небольшую тестовую выборку; в случае успеха рабочий процесс расширяется на Волну 2, затем Волну N. При сбое любой волны компенсация откатывает только эту волну. Это сетевой эквивалент канареечного развёртывания: та же дисциплина контролируемого продвижения, которую программные команды применяют к выпускам кода, применённая к сетевым изменениям.
7.2.1.3. Управление зависимостями#
Шаги рабочего процесса редко существуют изолированно. Движку необходимо выражать и обеспечивать три вида зависимостей:
Зависимости данных: задача B не может начаться до тех пор, пока задача A не завершится и не произведёт результат, который B потребляет. Движок передаёт выходные данные между шагами в виде структурированных данных. На практике это означает, что шаг предварительной проверки передаёт список доступных устройств шагу выполнения, а не повторно запрашивает с нуля.
Зависимости с несколькими входами (fan-in): шаг ждёт нескольких параллельных ветвей перед продолжением. Движок хранит состояние для каждой ветви и запускает шаг объединения только при выполнении настроенной политики завершения: все завершены, или N из M, или первый успех.
Внешние зависимости: иногда шаг не может продолжаться, пока что-то вне системы не произойдёт. Открывается окно изменений. Человек утверждает. Устройство становится доступным после перезагрузки. Движок должен поддерживать состояния ожидания с настраиваемыми тайм-аутами и определёнными путями эскалации для ситуаций, когда ожидание никогда не разрешается.
7.2.2. Инициирование#
Рабочий процесс должен как-то начинаться. Инициирование отвечает на два вопроса: что вызывает запуск рабочего процесса и что вызывающая сторона получает после этого.
Чем инициирование отличается от Главы 5: в Главе 5 инициирование означало, как оператор или система вызывает движок исполнения напрямую: API-вызов к AWX, запуск шаблона из Command Line Interface (CLI). Это инициирование на уровне исполнения. Здесь инициирование описывает, что заставляет Оркестратор начать рабочий процесс, который может в свою очередь вызывать Исполнителя как один из нескольких шагов. Оркестратор получает триггер и решает, какой полный рабочий процесс выполнять. Исполнитель просто выполняет то, что ему говорит Оркестратор.
7.2.2.1. Режимы инициирования#
Четыре режима охватывают весь спектр от человека до полной автоматизации:
API-вызов: Оркестратор предоставляет HTTP-конечную точку. Оператор вызывает её вручную, кнопка в UI вызывает её, или внешняя система (ServiceNow, Nautobot, CI/CD конвейер) вызывает её при наступлении события. Это один и тот же механизм: разница в том, кто инициирует вызов и несёт ли он структурированные данные события. Подходит для любого изменения, которое нужно начать сейчас, независимо от того, является ли инициатором человек или система.
По расписанию: расписание, подобное cron, запускает рабочий процесс в настроенное время. Ночные сканирования соответствия, еженедельные аудиты прошивок, ежемесячные отчёты о ёмкости. Большинство оркестраторов поддерживают это нативно; некоторые команды используют внешний планировщик и вызывают API оркестратора.
Очередь сообщений: Оркестратор потребляет сообщения из очереди (Kafka, NATS, RabbitMQ) и запускает рабочий процесс на каждое сообщение. Это разделяет производителя событий от оркестратора: производитель публикует и продолжает работу; оркестратор обрабатывает в своём темпе. Подходит для высокообъёмных потоков событий, где гарантий «не более одной доставки» от прямых API-вызовов недостаточно.
Выбор между push (API-вызов) и pull (очередь сообщений, расписание) зависит от объёма и допустимой связанности. API-вызовы проще, но требуют, чтобы отправитель знал конечную точку оркестратора. Очереди сообщений лучше масштабируются для высокообъёмных потоков, но добавляют инфраструктуру для эксплуатации.
7.2.2.2. Контракт ответа#
После запуска рабочего процесса вызывающая сторона должна знать, что ожидать:
Синхронный: вызывающая сторона ждёт завершения рабочего процесса и получает результат напрямую. Подходит для коротких операций (до 30 секунд), где результат нужен для продолжения. Большинство интерактивных вариантов использования начинают здесь и обнаруживают, что переросли это, когда пытаются запустить 10-минутное развёртывание и у API-клиента истекает тайм-аут.
Асинхронный: вызывающая сторона немедленно получает ID запуска рабочего процесса и опрашивает статус или регистрирует URL обратного вызова для получения результата по завершении. Требуется для любого рабочего процесса, затрагивающего более нескольких устройств. Это имеет прямые последствия для того, как система предоставляет статус: уровень Представления (Глава 8) должен предоставлять конечные точки статуса и push-уведомления, поскольку пользователи запустили рабочие процессы откуда-то и им нужен способ отслеживать их без удержания открытого HTTP-соединения.
Гибридный: рабочий процесс запускается асинхронно, но вызывающая сторона при необходимости может опционально блокироваться на конечной точке синхронного ожидания. Удобный паттерн, избавляющий вызывающих от необходимости выбирать заранее.
Идемпотентность в событийно-управляемых рабочих процессах: когда Наблюдаемость генерирует оповещение или событие изменения SoT, несколько систем могут реагировать одновременно. Одно и то же оповещение может сработать дважды; очередь сообщений может доставить одно сообщение несколько раз. Каждый событийно-управляемый рабочий процесс должен быть идемпотентным: двойной запуск с одинаковыми входными данными должен давать тот же результат, что и однократный. На уровне оркестрации это обычно требует ключа дедупликации: уникального идентификатора, который оркестратор проверяет перед запуском нового выполнения. Если выполнение с таким ключом уже существует и ещё выполняется — отклоните или поставьте дубликат в очередь. Это звучит просто и удивительно легко ошибиться на практике.
Паттерн замкнутого цикла: Наблюдаемость обнаруживает условие дрейфа (конфигурация устройства отклонилась от намерения). Она генерирует оповещение для Оркестратора через описанные выше механизмы инициирования. Оркестратор запускает рабочий процесс исправления: запрашивает SoT для получения ожидаемого состояния, вызывает Исполнитель для корректировки устройства, а затем повторно запускает проверку Наблюдаемости для подтверждения исправления. Если проверка проходит — цикл замыкается. Если нет — Оркестратор эскалирует. Этот паттерн является основой самовосстанавливающейся автоматизации и подробно рассматривается в Главе 15. Цикл работает только если Оркестратор, Наблюдаемость и Исполнитель достаточно разделены, чтобы каждый мог играть свою роль независимо.
7.2.3. Устойчивость и масштаб#
Именно это отделяет оркестратор, с которым прототипируют, от того, которому доверяют в 3 часа ночи в продакшене. Рабочий процесс, надёжно работающий в идеальных условиях, ничего не говорит о том, переживёт ли он перезапуск координатора посреди выполнения, справится ли с 40 из 800 устройств, не прошедших предварительные проверки, или деградирует ли корректно, когда зависимость так и не разрешается. В следующий раз, когда ваш оркестратор будет испытан, это будет не в демо.
Устойчивость на уровне исполнения, рассмотренная в Главе 5, адресует идемпотентность и повторные попытки на уровне отдельного устройства: если плейбук даёт сбой на одном устройстве — повторить попытку. Что Глава 5 не рассматривает — это долговечность на уровне рабочего процесса: что происходит, когда сам Оркестратор перезапускается посреди выполнения, когда 40 из 800 устройств не проходят предварительные проверки, или когда зависимость так и не разрешается и рабочий процесс зависает. Масштабирование самого оркестратора, включая высокую доступность, горизонтальные воркеры и нагрузку на базу данных при параллельных выполнениях, — это инфраструктурная задача, рассматриваемая в Главе 11.
7.2.3.1. Долговременное состояние#
Движок рабочих процессов, хранящий состояние выполнения в памяти, теряет всё при перезапуске. Это допустимо для скриптов и недопустимо для продакшен-оркестрации. Долговременное состояние означает, что прогресс рабочего процесса переживает сбой оркестратора: какие шаги завершены, что они произвели, какие ещё ожидают. Когда оркестратор снова выходит в онлайн — он возобновляет с места остановки.
Temporal полностью построен вокруг этой гарантии: он воспроизводит функцию рабочего процесса из истории событий при перезапуске, делая выполняемое состояние устойчивым к сбоям. AWX хранит состояние заданий в своей базе данных. Скрипты ничего не хранят.
7.2.3.2. Стратегии повторных попыток#
Не все сбои одинаковы. Устройство, которое было кратковременно недоступно во время перезагрузки прошивки, следует повторить. Устройство, вернувшее постоянную ошибку авторизации, — нет: повтор не поможет и может вызвать политики блокировки.
Конфигурация повторных попыток должна различать:
- Временные сбои: сетевые сбои, тайм-ауты API, временная конкуренция за ресурсы. Повторить с экспоненциальной задержкой.
- Постоянные сбои: неверные учётные данные, устройство в режиме обслуживания, конфигурация, неприменимая к этому типу устройств. Прервать и эскалировать.
Определение рабочего процесса должно задавать политику повторных попыток для каждого шага. Шаг предварительной проверки и шаг применения конфигурации имеют разную семантику сбоев и не должны разделять одинаковые настройки повторных попыток.
7.2.3.3. Откат и компенсация#
Когда рабочий процесс развёртывания даёт сбой на полпути, есть три варианта: оставить частичное состояние, исправить вручную или откатить автоматически. В большинстве сетевых операций частичное состояние опасно: устройства, получившие новую конфигурацию, будут вести себя иначе, чем те, что не получили.
Паттерн Saga решает это, определяя компенсирующую транзакцию для каждого шага. Если рабочий процесс успешен до шага N и затем даёт сбой — он выполняет компенсирующие действия для шагов N-1 по 1 в обратном порядке. При развёртывании VLAN: если применение конфигурации успешно на 30 устройствах и даёт сбой на 31-м, saga откатывает 30 успешных применений перед сообщением об ошибке.
Паттерн Saga требует, чтобы компенсирующие транзакции были определены заранее, на этапе разработки рабочего процесса. Это дополнительная работа заранее. Альтернатива — обнаружить в 2 часа ночи, что сеть находится в состоянии, которое не описывает ни одна инструкция.
7.2.3.4. Управление параллелизмом#
Расширение (fan-out) на 800 устройств одновременно перегрузит большинство уровней исполнения. Управление параллелизмом на уровне оркестрации означает:
- Пакетирование: запуск N устройств параллельно, ожидание завершения пакета, затем запуск следующих N. Это контролирует радиус поражения: если плохая конфигурация выявляет проблему — ещё не затронуты все 800 устройств.
- Ограничение частоты: у уровня исполнения есть ограничения; оркестратор должен их соблюдать. Не позволяйте очереди AWX заполняться 800 одновременными заданиями.
- Пороги частичного успеха: определите, что означает успех в масштабе. 798 из 800 правильно настроенных устройств может быть достаточно для продолжения; 600 из 800 должны остановить рабочий процесс и эскалировать.
7.2.3.5. Тайм-аут и прерыватель схемы#
Рабочие процессы, ждущие вечно, — это проблема надёжности. Каждый шаг, который может блокировать, нуждается в настроенном тайм-ауте. При истечении тайм-аута рабочий процесс нуждается в определённом действии: эскалировать, пропустить или прервать.
Паттерн Circuit Breaker расширяет это до повторных сбоев: если шаг даёт сбой более N раз в окне — прекратить попытки и создать оповещение. Это предотвращает удержание рабочего процесса одним недоступным устройством открытым часами.
7.2.3.6. Устойчивость через границы блоков#
Пять паттернов выше адресуют сбои внутри собственного выполнения Оркестратора: долговременное состояние, повторные попытки, откат, параллелизм, тайм-ауты. Но рабочие процессы также дают сбой на границах между блоками, и эти сбои требуют другой обработки.
Когда Оркестратор вызывает API SoT и получает тайм-аут, правильная реакция отличается от случая, когда Исполнитель возвращает сбой устройства. Тайм-аут SoT означает, что Оркестратор не может убедиться в актуальности намерения, которое собирается развернуть. Продолжение с кэшированными данными рискует применить устаревшую конфигурацию. Правильная реакция — обычно прервать и повторить, а не продолжать с неопределённостью. Событие уровня Представления, которое никогда не приходит (webhook утверждения от ServiceNow), может означать, что запрос был отклонён, интеграция сломана или сообщение потеряно. Это требует разных путей восстановления: отсутствующее утверждение — не временный сбой, который следует бесконечно повторять.
Сбои на границах блоков должны явно классифицироваться в определении рабочего процесса:
- Зависимость недоступна (SoT, Наблюдаемость): рабочий процесс не может безопасно продолжаться. Завершить чисто, сгенерировать диагностическое событие и не повторять с устаревшими данными.
- Зависимость деградирована (частичное чтение SoT, запаздывающая Наблюдаемость): рабочий процесс может продолжаться с явным признанием того, что работает с пониженной уверенностью. Логировать деградированное состояние; не продолжать молча.
- Нижестоящий блок дал сбой (Исполнитель вернул ошибку, Сборщик не вернул данные): применить паттерны повторных попыток и отката выше, но точно классифицировать источник сбоя, чтобы оповещение и аудиторская запись называли правильный блок.
Рабочий процесс, обрабатывающий все сбои как повторяемые ошибки устройств, будет повторять сломанную интеграцию SoT до исчерпания бюджета повторных попыток и разбудит дежурного инженера с неправильным диагнозом. Классификация сбоев на границах блоков — разница между рабочим процессом, дающим быстрый сбой, и тем, что даёт запутанный сбой.
7.2.4. Состояние и прослеживаемость#
Когда что-то идёт не так в 3 часа ночи, нужны немедленные ответы на два вопроса: каково текущее состояние рабочего процесса и кто его запустил?
Когда команда аудиторов задаёт вопросы три месяца спустя, та же запись должна отвечать: что выполнялось, какая версия определения рабочего процесса выполнялась, что каждый шаг получил на входе, что он произвёл на выходе и каким был конечный результат.
Это разные вопросы с разной срочностью, но они исходят из одного источника: состояния выполнения рабочего процесса и его аудиторской записи.
Прослеживаемость — это сквозная задача платформы автоматизации: Источник истины фиксирует каждое изменение намерения; Наблюдаемость фиксирует каждое изменение состояния сети. Но ни одна из этих записей не говорит вам, кто инициировал рабочий процесс, какие шаги выполнялись последовательно и что вызвало результат. Только аудиторская запись Оркестратора закрывает этот пробел. Поскольку Оркестратор координирует все другие блоки, его трасса является авторитетным представлением всего, что произошло в полной системе автоматизации для данного события.
7.2.4.1. Состояние — это не состояние сети#
Это различие легко упустить. В Главе 6 «состояние» означало операционное состояние сети: счётчики интерфейсов, BGP-сессии, CPU устройств. В Главе 5 «состояние» означало желаемое намерение конфигурации, хранящееся в SoT. Здесь состояние означает состояние выполнения самого рабочего процесса: какие шаги выполнились, какие выполняются, какие дали сбой и что они произвели.
Эти понятия связаны (шаг рабочего процесса производит изменения состояния сети, которые Наблюдаемость затем валидирует), но хранятся по-разному, запрашиваются по-разному и служат разным целям. Не смешивайте их.
7.2.4.2. Машина состояний рабочего процесса#
Каждое выполнение рабочего процесса проходит через определённую машину состояний:
- Ожидание: получен, но ещё не запущен
- Выполнение: активно выполняет шаги
- Успех: все обязательные шаги успешно завершены
- Сбой: шаг дал сбой и рабочий процесс не смог продолжить
- Отмена: остановлен человеком или внешним сигналом
Каждый шаг внутри рабочего процесса имеет своё собственное состояние. Частично успешное выполнение с расширением должно показывать именно, какие устройства успешны, какие дали сбой и какие пропущены. «Рабочий процесс завершился с ошибкой» бесполезно без разбивки по устройствам.
7.2.4.3. Требования к журналу аудита#
Каждая запись о выполнении рабочего процесса должна содержать как минимум:
- Кто или что запустило выполнение: идентификатор человека, имя системы, ID запускающего события
- Когда началось и когда завершилось
- Какая версия определения рабочего процесса выполнялась
- Полные входные данные, полученные рабочим процессом
- Вывод каждого шага
- Конечный результат
Эта запись должна быть защищена от фальсификации: она не может быть отредактирована постфактум. В регулируемых средах журнал аудита Оркестратора является записью управления изменениями. Если эта запись может быть изменена — система управления изменениями ненадёжна.
Большинство инструментов оркестрации записывают журналы аудита в базу данных, которой они также владеют. Достаточно ли этого — зависит от ваших требований к соответствию. Некоторые организации экспортируют журналы аудита оркестрации во внешнюю систему только для добавления (SIEM, хранилище журналов с однократной записью) для предотвращения фальсификации кем-либо с доступом к базе данных, включая тех, кто может выполнять запросы к собственной базе данных оркестратора.
7.2.5. Управление конвейерами#
Рабочий процесс, настраивающий 800 производственных коммутаторов, является, с архитектурной точки зрения, производственным ПО. Центральная задача — не просто версионирование: это то, как вы храните, валидируете и продвигаете определения рабочих процессов, чтобы сама логика была столь же надёжна, как инфраструктура, которой она управляет.
Определение рабочего процесса кодирует решения: какие предварительные проверки выполнять, что делать при недоступности устройства, что считается успехом. Небрежное изменение меняет то, что произойдёт с каждым устройством, которое затрагивает этот рабочий процесс при следующем запуске.
Я видел команды, незаметно ломавшие производственные рабочие процессы, редактируя определение напрямую в UI инструмента оркестрации. Никто не замечал, пока следующий запуск не затрагивал тип устройства, который изменённый шаг не обрабатывал корректно. Редактирование в UI не имело ни проверки, ни теста, ни пути отката.
7.2.5.1. Стратегии#
Определения на основе Git: хранить определения рабочих процессов в системе контроля версий. Инструмент оркестрации получает данные из Git при развёртывании, а не из локальных правок в UI. Это даёт историю, процесс проверки и возможность вернуться к любой предыдущей версии.
Версии конвейера blue/green: поддерживать две версии рабочего процесса в продакшене: текущую стабильную версию, обрабатывающую все активные рабочие процессы, и новую, получающую новые запуски после периода валидации. Трафик переключается только когда новая версия доказала стабильность.
Канареечное выкатывание: новая версия рабочего процесса сначала обрабатывает небольшое количество запусков. Рабочий процесс обновления прошивки может применять новую версию к 10 устройствам перед продвижением на весь парк. Проблемы обнаруживаются на 10 устройствах, а не на 800.
7.2.5.2. Тестирование изменений оркестрации#
Определения рабочих процессов можно тестировать до продакшена:
- Режим пробного запуска: запустить рабочий процесс против реальных входных данных, но пропустить шаги, модифицирующие сеть. Убедиться, что логика производит ожидаемую последовательность действий.
- Staging-среда: подмножество устройств, выделенных для тестирования изменений рабочих процессов до их запуска против продакшена.
- Теневое выполнение: запускать новую версию параллельно с текущей, но игнорировать её результаты. Сравнивать выводы для обнаружения расхождений до переключения.
Два разных отката: откат выполнения рабочего процесса означает отмену сетевых изменений, сделанных конкретным выполнением (обрабатывается паттерном Saga в разделе 7.2.3). Откат определения рабочего процесса означает возврат логики рабочего процесса к предыдущей версии: переключить ссылку Git, переразвернуть определение, и следующий запуск использует предыдущую версию. Это ортогональные операции. Путаница в них — способ, которым команды откатывают не то, что нужно.
7.2.6. Ландшафт решений#
Отказ от ответственности: перечисленные здесь инструменты приведены в качестве примеров для пояснительных целей, а не как рекомендации. Каждый имеет разную архитектуру и профиль компромиссов. Оценивайте их в соответствии с возможностями вашей команды, существующим инструментарием и операционными ограничениями.
Рынок инструментов оркестрации охватывает широкий спектр моделей: от сетевых платформ до движков рабочих процессов общего назначения. Вопрос редко звучит как «какой лучший» и почти всегда как «какой подходит под наш способ работы».
| Инструмент | Модель исполнения | Архитектурное отличие | Применимость для сетевой автоматизации |
|---|---|---|---|
| AWX / Ansible AAP | Шаблоны рабочих процессов YAML, UI-first | Оркестратор и Исполнитель — одна система: задания Ansible являются объектами первого класса, нет трансляционного уровня. RBAC, учётные данные и инвентарь унифицированы. | Команды, уже использующие Ansible для исполнения; прямой путь, когда Ansible уже является уровнем исполнения |
| Itential | Визуальный конструктор low-code/no-code, сетевой | Создан специально для сетевых операций: готовые адаптеры для ITSM, IPAM и многовендорных устройств. Конструктор рабочих процессов доступен не-разработчикам. | Корпоративные сетевые команды, нуждающиеся в многовендорной, многосистемной интеграции без пользовательского кода |
| Prefect | Python как DAG, developer-first | Рабочие процессы — это Python-функции с декораторами. Конвейер — это ПО: тестируется, версионируется и наблюдается как код приложения. Сильная нативная наблюдаемость самого конвейера. | Команды, знакомые с Python, желающие обращаться с оркестрацией как с инженерной дисциплиной |
| Temporal | Движок долговременного исполнения, код-определённый | Переживает сбои посреди рабочего процесса: любой шаг воспроизводится с последней контрольной точки. Saga и компенсация — объекты первого класса, не надстройки. | Длительные рабочие процессы (обновления прошивок, крупные выкатывания), где частичное выполнение и откат должны быть надёжными |
| Windmill | Script-first, лёгкий, open-source | Каждый узел в рабочем процессе — независимый скрипт (любой язык). Низкие операционные накладные расходы; легко развернуть самостоятельно и настроить без сложности корпоративных платформ. | Небольшие команды или организации, желающие гибкой логики без веса платформы |
Один архитектурный вопрос касается всех: выполняет ли ваш инструмент оркестрации также роль движка исполнения, или они разделены? AWX/AAP объединяет оба. Prefect, Temporal и Windmill — оркестраторы, вызывающие отдельные инструменты исполнения (Ansible, пользовательские скрипты, API). Объединённая модель проще в эксплуатации; разделённая даёт больше гибкости для независимой замены движков исполнения. Глава 3 представила этот компромисс в контексте минимальной связанности.
Строка AWX/AAP в таблице заслуживает уточняющей заметки для команд, рассматривающих его как основную платформу. Шаблоны рабочих процессов AWX — это Оркестратор; отдельные шаблоны заданий Ansible — это Исполнитель. Архитектурная граница между ними существует, даже несмотря на то что они работают в одной платформе. Команда, помещающая всю логику в шаблоны заданий (Исполнитель) и использующая шаблоны рабочих процессов только для их цепочки, по сути построила Оркестратор из примитивов исполнения, что ограничивает видимость, конфигурацию повторных попыток и опции отката. И наоборот, команда, помещающая бизнес-логику в шаблоны рабочих процессов (условное ветвление на основе внешних данных, динамический выбор инвентаря), использует AWX как настоящий оркестратор. Различие важно, потому что аудиторский след AWX, ворота утверждения и хуки уведомлений — это функции уровня рабочего процесса. Если вся ваша логика живёт в шаблонах заданий — вы не можете использовать эти функции без реструктуризации. Это не ограничение AWX; это следствие неразличения Оркестрации от Исполнения в проектировании.
Эти инструменты значительно перекрываются: Python работает как в Prefect, так и в Windmill; как Prefect, так и Temporal могут вызывать Ansible. Грубая отправная точка: если ваша команда Ansible-first и хочет минимум новых компонентов — шаблоны рабочих процессов AWX являются естественным вариантом; если вы хотите тестируемые, code-first конвейеры с дисциплиной программной инженерии — Prefect и Windmill работают с разными операционными моделями; если долговечность при частичном сбое является основным ограничением — модель воспроизведения Temporal создана специально для этого. Рассматривайте это как отправную точку для оценки, а не как окончательный ответ.
7.2.7. Агентный Оркестратор#
Агентный подход к координации, представленный в разделе 7.2.1, вводит другую модель исполнения: вместо следования предопределённому DAG Large Language Model (LLM) получает цель и определяет последовательность действий во время выполнения. Агент наблюдает текущее состояние из блоков Наблюдаемости и SoT, рассуждает о том, какое действие устраняет разрыв, вызывает Исполнитель и повторно наблюдает для проверки результата. Если результат не соответствует ожиданиям — он рассуждает снова. Логика решений не закодирована в определении рабочего процесса; она живёт в рассуждениях модели.
Что делает это возможным для всей платформы автоматизации — это Model Context Protocol (MCP) (Model Context Protocol). Каждый строительный блок предоставляет MCP-сервер: определённый набор инструментов, которые агент может вызывать в своём цикле рассуждений. Сервер SoT предоставляет запросы к устройствам и поиск намерения; сервер Наблюдаемости предоставляет запросы состояния и проверки соответствия; сервер Исполнителя предоставляет запуск заданий и опрос статуса. Агент вызывает эти инструменты в любой последовательности, требуемой ситуацией, без необходимости заранее кодировать каждую возможную комбинацию.
Архитектурное следствие состоит в том, что блоки не должны знать друг о друге или об агенте. Интерфейс MCP — это контракт. Тот же SoT, который сегодня отвечает на REST-вызовы из рабочего процесса на основе DAG, будет отвечать на MCP-вызовы инструментов от ИИ-агента без модификации. Чистые границы блоков окупаются здесь так, как тесная связанность никогда бы не окупилась.
Рабочие процессы на основе DAG и агентная оркестрация не являются взаимоисключающими. На практике рабочие процессы на основе DAG — правильный выбор для рутинных, хорошо определённых операций: развёртывание VLAN, сканирование соответствия, обновление прошивок. Они высокочастотны, требуют предсказуемых аудиторских следов и не должны зависеть от рассуждений LLM. Агентный уровень обрабатывает нестандартное: устранение инцидентов, расследование аномалий, ситуации, где правильная последовательность действий не может быть определена без понимания текущего состояния. Оба подхода могут сосуществовать в одной платформе, при этом DAG маршрутизирует к агентному рабочему процессу, когда ситуация не соответствует ни одному известному паттерну.
Этот раздел представляет паттерн. Полное архитектурное рассмотрение, включая то, как агентная оркестрация масштабируется до непрерывной автономной работы по всей сети, находится в Главе 17.
7.3. Пример реализации#
7.3.1. Оркестрация жизненного цикла VLAN-сервиса кампуса#
На протяжении Части 2 мы следовали за одной и той же сетью кампуса. В Главе 4 мы сохранили запрос на VLAN-сервис в Nautobot: ID VLAN, подсеть, целевые коммутаторы и вендор-специфичные шаблоны конфигурации. В Главе 5 мы использовали Ansible через AWX для применения этой конфигурации к кампусным коммутаторам. В Главе 6 мы проверили развёртывание и начали мониторинг сервиса.
Что мы так и не рассмотрели — кто координирует всё это. В каждой главе было неявное допущение: инженер выполнял каждый шаг вручную. Здесь мы делаем это явным и заменяем инженера рабочим процессом.
Сценарий
Команда разработки приложений подала запрос на новый сегмент приложения: VLAN app-payments, подсеть 10.22.14.0/24, развёрнутая на все коммутаторы доступа в building-b на стеках Cisco и Arista. Запрос был подан через ServiceNow и только что получил окончательное утверждение.
Это утверждение генерирует webhook. Оркестратор получает его и запускает рабочий процесс развёртывания VLAN-сервиса.
Рабочий процесс
Мы реализуем это как шаблон рабочего процесса AWX, совместимый с уже имеющимся уровнем исполнения. AWX поддерживает шаблоны рабочих процессов, связывающие шаблоны заданий с условным ветвлением и воротами утверждения, чего достаточно для данного сценария.
flowchart TD
A[ServiceNow webhook\nVLAN request approved] --> B[Step 1: Validate SoT\nQuery Nautobot for device records\nand VLAN definition completeness]
B --> C{SoT data complete?}
C -- No --> Z1[Abort: notify engineer\nand update ServiceNow ticket]
C -- Yes --> D[Step 2: Fan-out pre-checks\nReachability and VLAN state\nacross all target switches]
D --> E{Pre-checks passed?}
E -- Failures --> Z2[Abort: report per-device\nfailures to ServiceNow]
E -- Passed --> F[Step 3: Approval gate\nOptional human sign-off\nbefore production execution]
F --> G[Step 4: Execute deployment\nAnsible playbook via AWX]
G --> H[Step 5: Fan-out validation\nObservability check per switch]
H --> I{All devices validated?}
I -- Full success --> J[Step 6: Notify\nUpdate ServiceNow ticket\npost to Slack]
I -- Partial failure --> K[Step 6a: Saga compensation\nRollback failed scope only]
K --> J
Шаг 1: Валидация SoT
Оркестратор запрашивает Nautobot для подтверждения полноты записей устройств и определения VLAN перед тем, как что-либо затронет сеть. Этот защитный шаг — ответственность Оркестратора, а не Исполнителя: Исполнитель должен получать корректные входные данные, а не обнаруживать плохие данные посреди применения. При сбое любой проверки рабочий процесс прерывается и обновляет тикет ServiceNow с указанием конкретного пробела. (Структурирование валидации SoT рассмотрено в Главе 4.)
Шаг 2: Предварительные проверки на целевых коммутаторах (расширение)
Рабочий процесс разворачивается параллельно на все целевые коммутаторы. Каждая ветвь выполняет лёгкую предварительную проверку: доступность, состояние таблицы VLAN, доступная ёмкость. Шаг сужения классифицирует результаты и ветвится; порог сбоя настраивается. С точки зрения оркестрации важно, что это паттерн расширения/сужения с условным ветвлением, а не последовательный опрос. (Паттерны выполнения предварительных проверок — в Главе 5.)
Шаг 3: Ворота утверждения
Опциональный знак одобрения человеком перед применением в продакшен. У инженера есть 30 минут на утверждение или отклонение; при тайм-ауте продолжается автоматически с фиксацией. Оркестратор удерживает рабочий процесс в состоянии ожидания с внешней зависимостью до получения утверждения или истечения окна.
Ворота утверждения — политическое решение, а не архитектурное. Зрелые команды часто убирают их и заменяют ручное утверждение автоматизированными порогами уверенности, полученными из результатов предварительных проверок: если покрытие предварительных проверок превышает 95% и нет критических сбоев — продолжать автоматически. Команды, ещё выстраивающие доверие, сохраняют ворота. Оба выбора допустимы на разных точках спектра зрелости автоматизации, обсуждаемого в Главе 1.
Шаг 4: Выполнение развёртывания
Оркестратор запускает шаблон задания AWX из Главы 5, передаёт параметры из шага валидации SoT и ждёт результата. Исполнитель обрабатывает остальное. Это разделение ответственностей на практике: Оркестратор решает действовать, Исполнитель действует.
Шаг 5: Валидация Наблюдаемостью (расширение)
После развёртывания второе расширение запускает задание валидации для каждого целевого коммутатора: отображается ли VLAN в таблице VLAN, находятся ли интерфейсы в ожидаемом состоянии? Сужение классифицирует результаты: полный успех, частичный успех или сбой. (Что валидирует уровень Наблюдаемости и как — рассмотрено в Главе 6.)
Шаг 6: Маршрутизация результата
Полный успех закрывает рабочий процесс: тикет ServiceNow обновляется и сводка публикуется в Slack. Частичный сбой запускает компенсацию Saga: плейбук отката выполняется только для устройств, не прошедших валидацию; устройства, прошедшие успешно, сохраняют конфигурацию. Тикет ServiceNow фиксирует результат по каждому устройству.
Возвращение к инженеру из вступления
Этот рабочий процесс демонстрирует все семь строительных блоков фреймворка NAF из Главы 3, работающие вместе: Nautobot (Источник истины) предоставил намерение, AWX (Исполнитель) применил его, Prometheus (Наблюдаемость) подтвердил результат, шаблон рабочего процесса AWX (Оркестратор) координировал полную последовательность, а webhook ServiceNow (Представление, рассматриваемое в Главе 8) инициировал весь поток из запроса команды разработки.
Инженер из вступительной истории всё ещё здесь. Она та, кто проверяет ворота утверждения, когда они срабатывают. Она та, кто расследует частичный сбой, который паттерн Saga отметил, но не смог полностью устранить. Она всё ещё эксперт. То, что взял у неё Оркестратор, — не экспертиза, а бремя удержания последовательности в голове, её пошагового повторения и статус единственного человека, который мог это делать. Вот что реально стоит координация без автоматизации.
7.4. Резюме#
Эта глава установила, что Orchestrator — строительный блок, превращающий набор работающих инструментов автоматизации в систему, ведущую себя как единое целое. Без него координация остаётся ручной, сбои требуют вмешательства человека, а масштаб сети становится ограничением на то, сколько автоматизации реально возможно.
В основе оркестрации лежит движок рабочих процессов, определяющий структуру и исполнение многошаговых процессов. Выбор между монолитом, DAG, хореографией и агентной координацией — архитектурное решение, а не предпочтение в инструментах. Модель DAG с именованными паттернами (последовательный, расширение, условный, Saga) — производственный стандарт для сетевой автоматизации. Агентный паттерн, представленный в разделе 7.2.7 с Model Context Protocol (MCP) в качестве интерфейсного уровня, представляет другой компромисс и получает полное рассмотрение в Главе 17.
Инициирование определяет, как внешний мир достигает оркестратора. Различие между инициированием на уровне исполнения (Глава 5) и на уровне оркестрации важно архитектурно: одно управляет одним изменением устройства, другое управляет координированным многосистемным рабочим процессом. Событийно-управляемая автоматизация и паттерн замкнутого цикла наследуют обязательные свойства идемпотентности и дедупликации именно потому, что автоматические триггеры срабатывают без проверки человеком.
Устойчивость и масштаб отделяют автоматизацию, работающую в демо, от той, что работает в 3 часа ночи. Долговременное состояние, стратегии повторных попыток, различающие временные и постоянные сбои, паттерн Saga для компенсации при частичном сбое и управление параллелизмом для больших парков устройств — не опциональные функции для добавления позже. Они определяют, можно ли доверять оркестратору в неидеальных условиях.
Состояние и прослеживаемость обеспечивают запись о том, что выполнялось, кто это запустил и что произвёл каждый шаг. Эта запись отличается от операционного состояния сети (Глава 6) и сетевого намерения (Глава 4). Журналы аудита, защищённые от фальсификации, — требование соответствия, а не послесловие. Управление конвейерами замыкает цикл: определения рабочих процессов — это производственное ПО и должны версионироваться, тестироваться и продвигаться с той же дисциплиной, что и любой другой код на платформе автоматизации.
Сценарий с VLAN-сервисом кампуса объединил все пять функциональных возможностей: десятишаговый рабочий процесс, запущенный webhook’ом ServiceNow, координирующий валидацию SoT, предварительные проверки, выполнение, валидацию Наблюдаемостью и компенсацию Saga — без инженера в координационном цикле. Следующий естественный вопрос: кто видит этот выполняющийся рабочий процесс и как команда разработки, запустившая его, отслеживает прогресс. Это уровень Представления, рассматриваемый в Главе 8.
💬 Found something to improve? Send feedback for this chapter