FinCodeCow · Глава XVI

Развёртывание событийно-управляемых микросервисов

Стратегии, шаблоны и подводные камни: от CI/CD до blue-green в мире потоков событий

Когда в организации насчитываются десятки, а тем более сотни микросервисов, хаотичный подход к их выпуску в продакшен быстро превращается в источник постоянных инцидентов. Событийно-управляемая архитектура (EDA) добавляет к классическим сложностям развёртывания целый пласт специфических проблем: перестройка материализованных состояний, повторная обработка потоков, совместимость схем и влияние на нижестоящих потребителей.

В этой главе мы разберём фундаментальные принципы, архитектурные компоненты и конкретные шаблоны развёртывания, которые помогут выпускать обновления предсказуемо и безопасно.

Это шестнадцатая глава цикла. Она опирается на главу I (Team Topologies, distributed monolith), главу III (schema evolution), главу IV (Data Liberation), главу V (state stores, rebalance), главу VI (reprocessing), главу VII (state store migration), главу VIII (Saga, human-in-the-loop), главу XII (Kafka Streams), главу XIV (CI/CD, tooling) и главу XV (testing infrastructure). Здесь мы замыкаем цикл: от паттернов и качества — к безопасной доставке в production.

• • •

IПринципы развёртывания EDA

Прежде чем говорить о конкретных шаблонах, нужно зафиксировать набор правил, которые делают процесс управляемым на любом масштабе.

Автономия команд

Владельцы микросервиса самостоятельно запускают, тестируют и откатывают релизы, не дожидаясь «окна» от инфраструктурного отдела. Это устраняет узкие места и ускоряет цикл обратной связи.

Единый стандарт

Каждый новый микросервис рождается с готовым конвейером развёртывания. Если команда каждый раз изобретает процесс с нуля, организация тонет в дублировании.

Вспомогательные инструменты

Сброс смещений, очистка state, проверка версий схем, удаление internal topics — всё через self-service portal, а не через ручные скрипты администраторов.

Учёт повторной обработки

Перестройка state из входных потоков может генерировать миллионы выходных событий. Это пиковая нагрузка на брокер и downstream. Не забывайте про побочные эффекты — повторная рассылка уведомлений клиентам.

SLA — это не только про доступность

Соглашения об уровне обслуживания охватывают также время перестройки состояния, допустимую задержку потоков и объём выходных событий. Убедитесь, что ваш план развёртывания не нарушает контракты с зависимыми командами.

Два принципа про взаимодействие сервисов:

  1. Минимизируйте зависимые изменения. Если развёртывание сервиса А требует синхронного обновления API или модели данных в Б, это сигнал о размытых границах bounded contexts.
  2. Обсуждайте критические изменения заранее. Когда breaking change неизбежен, все downstream-потребители должны получить план миграции до начала развёртывания.
Если развёртывание микросервиса А невозможно без одновременного развёртывания микросервиса Б, перед вами не два микросервиса, а один монолит, разрезанный по ошибке. — Distributed Monolith Anti-Pattern
• • •

IICI vs CD vs Continuous Deployment

Эти три понятия часто путают, хотя между ними принципиальная разница:

Этап Суть Роль человека
CI (интеграция) Автосборка, unit + integration тесты, проверка стиля и совместимости схем при каждом слиянии. Результат — готовый контейнер. Не требуется
CD (доставка) Контейнер прошёл все проверки, но финальный «пуск» в продакшен делается вручную владельцем сервиса. Нажатие кнопки
CD (развёртывание) Полностью автоматический путь от коммита до продакшена. Изменение кода попадает к пользователям без ручного вмешательства. Не требуется

На практике сквозное непрерывное развёртывание для stateful EDA реализуется крайне редко: обновление может потребовать полного перестроения state и повторного прогона входных потоков, что занимает часы и создаёт колоссальную нагрузку. Большинство команд останавливаются на непрерывной доставке (CD-delivery), оставляя за собой право выбирать момент запуска.

Связь с главой XIV

CI/CD/CD — часть golden path из главы XIV. Каждый новый сервис получает готовый pipeline с schema check, contract tests, integration tests (Testcontainers) и опционально — canary analysis.

• • •

IIIKubernetes operators: управление EDA-инфраструктурой

Для деплоя Kafka Streams, Flink, Kafka Connect нужны operators — Kubernetes-контроллеры, которые знают, как управлять специфическими workloads.

Operator Для чего Что даёт
Strimzi Kafka + Kafka Connect + MirrorMaker Декларативный деплой Kafka-кластера, топиков, ACL, Schema Registry
Flink Kubernetes Operator Flink jobs Session/Application mode, savepoints, upgrade jobs без потери state
Confluent for Kubernetes Confluent stack Managed Kafka, Schema Registry, KSQL, Connect
Kafka Connect operator Коннекторы Управление коннекторами через CRDs
Argo CD GitOps для K8s Синхронизация состояния кластера с git-репозиторием
# Пример CRD для Kafka-топика (Strimzi)
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: orders-raw-stream
  labels:
    strimzi.io/cluster: my-cluster
spec:
  partitions: 12
  replicas: 3
  config:
    retention.ms: 2592000000
    cleanup.policy: delete

---
# Пример CRD для Flink job (Flink K8s Operator)
apiVersion: flink.apache.org/v1beta1
kind: FlinkDeployment
metadata:
  name: order-enrichment
spec:
  image: my-registry/order-enrichment:1.2.0
  flinkVersion: v1_18
  jobManager:
    resource:
      memory: 2048m
      cpu: 1
  taskManager:
    resource:
      memory: 4096m
      cpu: 2
  job:
    jarURI: local:///opt/flink/usrlib/order-enrichment.jar
    parallelism: 4
    upgradeMode: savepoint

Operators дают декларативный подход: вы описываете желаемое состояние в YAML, operator приводит кластер к этому состоянию. Для EDA это критично — вручную управлять Kafka + Schema Registry + Kafka Connect + мониторинг + 100 микросервисов нереально.

• • •

IVStatefulSet и PVC: stateful workloads в Kubernetes

Kafka Streams, Flink TaskManagers и другие stateful EDA-сервисы требуют особого подхода к деплою:

StatefulSet вместо Deployment

Стабильные идентификаторы pod'ов (pod-0, pod-1, pod-2), стабильные сетевые идентификаторы, упорядоченный деплой и scaling.

Persistent Volume Claims (PVC)

RocksDB для Kafka Streams живёт на локальном диске. PVC гарантирует, что state не потеряется при рестарте pod'а.

Pod Disruption Budgets (PDB)

Защита от массового удаления pod'ов. Например, minAvailable: 2 гарантирует, что всегда работают минимум 2 pod'а.

Anti-affinity

Распределение pod'ов по разным физическим node'ам. Если один node упадёт — сервис продолжит работу.

# Пример StatefulSet для Kafka Streams
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: order-processor
spec:
  serviceName: order-processor
  replicas: 3
  selector:
    matchLabels:
      app: order-processor
  template:
    metadata:
      labels:
        app: order-processor
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                app: order-processor
            topologyKey: kubernetes.io/hostname
      containers:
      - name: processor
        image: my-registry/order-processor:1.2.0
        volumeMounts:
        - name: state
          mountPath: /var/lib/kafka-streams
  volumeClaimTemplates:
  - metadata:
      name: state
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 100Gi
• • •

VGitOps и environment promotion

GitOps — декларативный подход, при котором желаемое состояние кластера описано в git, а controller (Argo CD, Flux) синхронизирует реальное состояние с этим описанием.

  1. Dev → Staging → Production. Последовательное продвижение изменений через среды.
  2. Environment parity. Одинаковые конфигурации во всех средах — то, что работает в staging, работает в production.
  3. Configuration management. Helm, Kustomize для параметризации манифестов.
  4. Automated sync. Argo CD сам применяет изменения из git через N секунд после коммита.
  5. Rollback через git revert. Откат = revert коммита в git, controller приводит кластер к предыдущему состоянию.
Преимущество GitOps для EDA

Все изменения инфраструктуры EDA (топики, ACL, коннекторы, deployments) проходят через git — с review, историей, откатом. Это устраняет «дрейф конфигураций» между средами — частую причину production-инцидентов.

• • •

VIDatabase migrations: schema evolution для state stores

В EDA сервисы обычно имеют внешние state stores (PostgreSQL, DynamoDB) помимо Kafka. Как мигрировать схему БД безопасно?

Инструмент Модель Когда выбирать
Flyway Versioned SQL migrations Simple, plain SQL, полный контроль
Liquibase Changelog-based Multi-DB, XML/YAML/SQL, rollback
Atlas Declarative schema Schema-as-code, diff-based
Expand-Migrate-Contract Pattern Zero-downtime migration

Expand-Migrate-Contract для БД

  1. Expand: добавить новое поле рядом со старым. Оба заполняются.
  2. Migrate: обновить код читать новое поле. Двойная запись.
  3. Contract: удалить старое поле после миграции всех потребителей.

Это тот же паттерн, что и для схем событий (глава III). Единый подход к evolution схем — событий и БД — снижает когнитивную нагрузку на команду.

• • •

VIIБазовый шаблон: полная остановка и перезапуск

Самый простой и универсальный подход. Служит основой для всех остальных шаблонов и подходит, когда допустимо кратковременное прекращение обработки.

  1. Фиксация кода. Разработчик сливает изменения в основную ветку, запускается CI.
  2. Автотесты. Unit + integration тесты с изолированными средами (Testcontainers, глава XV).
  3. Предварительные проверки. Входные/выходные потоки существуют, ACL выданы, новые схемы совместимы (глава III).
  4. Остановка, очистка, запуск. Старые экземпляры останавливаются. При необходимости сбрасываются state stores, offsets, internal topics. Разворачивается новый контейнер. Если запуск провалился — откат.
  5. Пост-проверки. Consumer lag вернулся к норме, в логах нет аномалий, endpoints отвечают.
Совет

Если перестройка state дорога, можно не удалять state и internal topics при остановке, а развернуть новый экземпляр «поверх» старых данных. Это позволяет быстро откатиться, если что-то пойдёт не так. Но помните: state должен быть совместим с новой версией кода.

• • •

VIIIRolling Update: непрерывное обновление

Вместо одновременной остановки всех экземпляров система обновляет их по одному. В каждый момент часть инстансов работает на старой версии, часть — на новой. Это обеспечивает нулевой простой обработки в реальном времени.

Когда это работает

  • Добавлены новые поля во входные события, бизнес-логика научилась их обрабатывать.
  • Подключены новые входные потоки.
  • Исправлены ошибки, не требующие reprocessing.

Когда это опасно

Критическое ограничение

Rolling update неприменим, если изменилась внутренняя топология микросервиса, структура state store или внутренние схемы событий. Любое из этих изменений требует полного сброса приложения. Самая частая ошибка — непреднамеренная модификация топологии, которую разработчик не заметил, но которая делает rolling update невозможным.

Продвинутые CI/CD-пайплайны автоматически запускают тест совместимости выпуска (release compatibility test), который проверяет, действительно ли обновление может пройти «на лету». Ручная оценка рисков крайне ненадёжна.

• • •

IXCanary deployment: 1% трафика

Canary — промежуточный подход между rolling update и blue-green. Новая версия обрабатывает небольшую долю трафика (обычно 1–5%), метрики сравниваются, и только при соответствии — процент увеличивается.

Этап Доля трафика Длительность
Canary 1% 30 минут
Ramp-up 10% → 50% → 100% каждые 30 минут
Full rollout 100% постоянно

Метрики для canary analysis

  • Error rate. Должна быть не выше, чем у старой версии.
  • Consumer lag. Новая версия не должна отставать.
  • Throughput. Не должна упасть.
  • Processing time p99. Должна быть в пределах SLA.
  • DLQ rate. Не должна расти.
Автоматический rollback

Если метрики canary хуже старой версии — автоматический откат. Инструменты: Argo Rollouts, Flagger, Spinnaker. Не полагайтесь на ручное решение — метрики решают.

• • •

XBlue-green deployment: где работает и где ломается

Классический приём из мира синхронных микросервисов: рядом со старой («зелёной») разворачивается полная копия новой («синей»). У «синей» — собственный state store, собственная consumer group, собственные сетевые адреса. Она догоняет «зелёную», после чего маршрутизатор плавно переключает трафик.

Где это работает

  • Микросервисы, обслуживающие синхронные запросы (REST API), где критически важен нулевой простой.
  • Сценарии, где события генерируются исключительно из request-response (конвертация CRUD-операций в события, глава XIII).

Где это ломается

Не работает для потоковых производителей

Если микросервис генерирует выходные события в ответ на входные потоки, «синяя» и «зелёная» версии будут одновременно писать в один и тот же выходной поток. Для сущностных событий это приведёт к перезаписи данных, для обычных — к дублированию. В таких случаях используйте rolling update или полную остановку.

Если вы всё же применяете blue-green, убедитесь, что мониторинг, alerting и autoscaling учитывают наличие двух consumer groups. После переключения «зелёные» экземпляры можно либо сразу отключить, либо оставить в standby для быстрого отката.

• • •

XIBreaking schema changes: миграция без боли

Рано или поздно бизнес-модель меняется настолько, что старую схему невозможно эволюционировать инкрементально. Сущность «Клиент» превращается в «Аккаунт», поля переименовываются, типы меняются. В этом случае развёртывание затрагивает не только производителя, но и всех потребителей потока.

Продолженная миграция (два потока)

Производитель пишет события одновременно в старый и новый потоки. Старый помечается как deprecated. Потребители мигрируют в своём темпе.

Плюс: каждый выбирает время перехода.

Риск: миграция может затянуться; новые сервисы по ошибке подписываются на устаревший поток.

Синхронизированная миграция (один поток)

Производитель переключается на новый формат и полностью прекращает запись в старый. Все потребители обновляются одновременно.

Плюс: чистота данных, нет дублирования.

Риск: если потребитель не успел мигрировать — теряет данные и не может вернуться к старому источнику.

Для сущностных событий (бесконечно хранимых, материализуемых в таблицы) синхронизированная миграция почти всегда требует полного пересоздания потока: производитель заново прогоняет исходные данные через новую логику. Для несущностных событий (с TTL) проще — потребители начинают читать новый поток, а старый со временем очистится сам.

Обязательно

Используйте тегирование метаданными, чтобы помечать устаревшие потоки. Это предотвратит случайные подписки новых сервисов на потоки, которые вот-вот будут удалены (глава XIV).

• • •

XIIFeature flags: отделить деплой от релиза

Feature flags позволяют деплоить код, но не включать новое поведение. Это отделяет deployment (техническое событие) от release (бизнес-событие).

LaunchDarkly

Managed feature flags. SDK для всех языков, A/B testing, metrics.

Unleash

Open-source альтернатива. Self-hosted, гибкие стратегии, audit log.

Split.io

Feature delivery + experimentation. Managed, продвинутая аналитика.

Kill switch

Мгновенное отключение функциональности без деплоя. Критично для EDA, где откат state дорог.

// Пример: feature flag для нового формата события
if (featureFlags.isEnabled("use-new-order-format", userId)) {
    producer.send("orders-v2", newOrderEvent);
} else {
    producer.send("orders", legacyOrderEvent);
}
• • •

XIIIRollback strategies: что делать, когда что-то пошло не так

Тип отката Что делает Когда применять
Instant rollback Вернуть старую версию образа Bugs, не связанные с state
State rollback Восстановить state из changelog/снапшота Новая версия испортила state
Offset rollback Перемотать offsets на предыдущую позицию Обработали события с ошибкой
Schema rollback Вернуть предыдущую версию схемы Breaking change не сработал
Full reset Сброс state + offsets + internal topics Катастрофический сбой
Правило

Любой деплой должен иметь план отката до его начала. Если вы не знаете, как откатить — не деплойте. Особенно это касается stateful изменений.

• • •

XIVSaga и graceful shutdown

Если у вас есть активные Saga (глава VIII), деплой может их прервать. Что делать?

  1. Graceful shutdown. Дать текущим Saga завершиться перед остановкой.
  2. Draining mode. Перестать принимать новые Saga, дождаться завершения старых.
  3. Saga versioning. Новая версия для новых Saga, старая для активных (глава VIII).
  4. Timeout policy. Что делать, если Saga висит слишком долго? Принудительно компенсировать или продлить?
// Graceful shutdown с drain
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    running = false;
    // Дождаться завершения активных Saga (до N секунд)
    sagaManager.drain(Duration.ofMinutes(5));
    consumer.close(Duration.ofSeconds(10));
}));
• • •

XVDeployment monitoring: что смотреть во время деплоя

Метрика Что показывает Порог алерта
consumer_lag Отставание от хвоста Растёт во время деплоя
error_rate Доля ошибок > baseline × 1.5
throughput Скорость обработки Падение > 30%
commit_latency_p99 99-й перцентиль времени commit > SLA
rebalance_count Число rebalance > 2 в час
dlq_rate Доля событий в DLQ > 0.1%

Инструменты: Prometheus + Grafana, Argo Rollouts dashboards, Confluent Control Center, Datadog APM.

• • •

XVICost of deployment: сколько стоит выкатить новую версию

Статья Что включает Как оптимизировать
State rebuild Повторное проигрывание changelog Snapshot перед деплоем, standby replicas
Reprocessing Прогон входных потоков Batching, off-peak windows
Blue-green × 2 Двойное использование ресурсов Короткое окно overlap, autoscaling
Canary × 1.05 +5% ресурсов на canary Короткие рампы, только для критичных сервисов
Managed K8s Оплата за час Spot instances, scale to zero где возможно
Managed Kafka Оплата за throughput Правильные retention, tiered storage
Правило cost-aware deployment

Каждый деплой имеет стоимость. Для 100 микросервисов, деплоящихся 10 раз в день, суммарная стоимость перестройки state может быть сравнима с месячной инфраструктурой. Оптимизируйте: snapshot перед деплоем, standby replicas для hot recovery, off-peak windows для reprocessing.

• • •

XVIIЧеклисты и связь с циклом

Связь с предыдущими главами

Глава Фокус Связь с текущей главой
I. Среда формирует архитектуру Team Topologies, distributed monolith Автономия команд, anti-pattern синхронного деплоя
III. Идеальное событие Schema evolution Schema rollback, breaking change migration
V. Потоковая обработка State stores, rebalance StatefulSet, PVC, graceful shutdown
VI. Время в потоках Reprocessing Cost of state rebuild
VII. Память микросервисов State store migration Rolling update, blue-green, state rollback
VIII. Saga Long-running процессы Graceful shutdown, draining mode
XII. Лёгкие фреймворки Kafka Streams internal topics StatefulSet, PVC, Strimzi operator
XIV. Налог на микросервисы CI/CD, tooling, platform Golden path, self-service, GitOps
XV. Тестирование Testing infrastructure Pre-flight checks, canary analysis
XVI. Развёртывание Deployment strategies Production delivery perspective

Чеклист развёртывания EDA

  • CI/CD pipeline настроен и проходит автоматически
  • Schema compatibility check в CI (Backward / Forward / Full)
  • Contract testing в CI (Pact, schema validation)
  • Testcontainers для integration tests
  • Kubernetes operator установлен (Strimzi, Flink K8s Operator)
  • StatefulSet + PVC для stateful workloads
  • Pod Disruption Budget настроен
  • Anti-affinity для распределения по node'ам
  • GitOps (Argo CD, Flux) для декларативного деплоя
  • Database migrations через Flyway / Liquibase / Expand-Migrate-Contract
  • Выбран шаблон: full stop, rolling, canary, blue-green
  • Feature flags для отделения деплоя от релиза
  • Rollback strategy определена (instant, state, offset, schema, full)
  • Graceful shutdown для Saga
  • Deployment monitoring настроен (lag, error rate, throughput)
  • Cost of deployment оценён и оптимизирован
  • SLA учитывает время перестройки state и downstream impact
  • Команда-владелец самостоятельно запускает и откатывает релизы

Ключевые выводы главы

  1. Развёртывание EDA — это не «залить контейнер». Перестройка state, reprocessing, schema evolution, downstream impact.
  2. Принципы: автономия команд, единый стандарт, self-service, учёт reprocessing.
  3. CI/CD/CD — три этапа, но для stateful EDA часто останавливаются на CD-delivery.
  4. Kubernetes operators — Strimzi, Flink K8s Operator, Confluent for Kubernetes.
  5. StatefulSet + PVC — stateful workloads в K8s.
  6. GitOps — декларативный деплой, environment promotion через git.
  7. Database migrations — Flyway, Liquibase, Expand-Migrate-Contract.
  8. Полная остановка — базовый шаблон, работает всегда.
  9. Rolling Update — нулевой простой, но не для изменений топологии или state.
  10. Canary — 1% → 10% → 50% → 100%, автоматический rollback по метрикам.
  11. Blue-green — для синхронных API, не для потоковых производителей.
  12. Breaking schema — продолженная (два потока) vs синхронизированная (один поток).
  13. Feature flags — отделить деплой от релиза, kill switch.
  14. Rollback strategies — instant, state, offset, schema, full.
  15. Saga и graceful shutdown — дождаться завершения активных Saga.
  16. Deployment monitoring — lag, error rate, throughput, DLQ rate.
  17. Cost of deployment — state rebuild, reprocessing, blue-green × 2.
Финальный тезис

Развёртывание событийно-управляемых микросервисов — это комплексный процесс, который должен учитывать перестройку state, повторную обработку потоков, совместимость схем и влияние на всю цепочку downstream. Инвестиции в стандартизированные pipeline, self-service tools и чёткие SLA окупаются многократно по мере роста числа микросервисов. Делегируйте ответственность командам-владельцам, но обеспечьте их надёжными автоматизированными механизмами. И всегда тестируйте план развёртывания в изолированной среде, максимально приближённой к production.

Глава XVI цикла «Событийно-управляемая архитектура». Источники: Kubernetes, Strimzi, Flink Kubernetes Operator, Confluent for Kubernetes, Argo CD, Argo Rollouts, Flagger, Flyway, Liquibase, LaunchDarkly, Unleash, Temporal, Prometheus, практические кейсы production-систем, FinCodeCow experience.

FinCodeCow · Chapter XVI

Deploying Event-Driven Microservices

Strategies, patterns, and pitfalls: from CI/CD to blue-green in the world of event streams

When an organization has dozens or hundreds of microservices, a chaotic approach to releasing them to production quickly becomes a source of constant incidents. Event-Driven Architecture (EDA) adds a whole layer of specific problems to classic deployment complexity: rebuilding materialized state, reprocessing streams, schema compatibility, and impact on downstream consumers.

In this chapter, we'll explore the fundamental principles, architectural components, and specific deployment patterns that help release updates predictably and safely.

This is the sixteenth chapter of the series. It builds on Chapter I (Team Topologies, distributed monolith), Chapter III (schema evolution), Chapter IV (Data Liberation), Chapter V (state stores, rebalance), Chapter VI (reprocessing), Chapter VII (state store migration), Chapter VIII (Saga, human-in-the-loop), Chapter XII (Kafka Streams), Chapter XIV (CI/CD, tooling), and Chapter XV (testing infrastructure). Here we close the cycle: from patterns and quality to safe production delivery.

• • •

IEDA Deployment Principles

Team Autonomy

Service owners independently launch, test, and roll back releases without waiting for a maintenance window. This eliminates bottlenecks and speeds up feedback loops.

Unified Standard

Every new microservice is born with a ready deployment pipeline. If a team reinvents the process each time, the organization drowns in duplication.

Supporting Tools

Offset reset, state cleanup, schema version check, internal topic deletion — all via self-service portal, not manual admin scripts.

Reprocessing Accounting

Rebuilding state from input streams can generate millions of output events. This is a spike on the broker and downstream. Don't forget side effects — e.g., re-sending notifications to customers.

SLA Is Not Only About Availability

Service Level Agreements also cover state rebuild time, allowed stream lag, and output event volume. Ensure your deployment plan does not violate contracts with dependent teams.

If deploying microservice A is impossible without simultaneously deploying microservice B, you have not two microservices, but one monolith cut by mistake. — Distributed Monolith Anti-Pattern
• • •

IICI vs CD vs Continuous Deployment

Stage Essence Human Role
CI (Integration) Auto-build, unit + integration tests, style and schema compatibility check on every merge. Result — a ready container. Not required
CD (Delivery) Container passed all checks, but the final "launch" into production is manual by the service owner. Button press
CD (Deployment) Fully automated path from commit to production. Code changes reach users without manual intervention. Not required
• • •

IIIKubernetes Operators: Managing EDA Infrastructure

Operator For What It Provides
Strimzi Kafka + Kafka Connect + MirrorMaker Declarative deployment of Kafka cluster, topics, ACL, Schema Registry
Flink Kubernetes Operator Flink jobs Session/Application mode, savepoints, upgrade jobs without state loss
Confluent for Kubernetes Confluent stack Managed Kafka, Schema Registry, KSQL, Connect
Kafka Connect Operator Connectors Connector management via CRDs
Argo CD GitOps for K8s Cluster state synchronization with git repository
# Example CRD for Kafka topic (Strimzi)
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: orders-raw-stream
  labels:
    strimzi.io/cluster: my-cluster
spec:
  partitions: 12
  replicas: 3
  config:
    retention.ms: 2592000000
    cleanup.policy: delete
• • •

IVStatefulSet and PVC: Stateful Workloads in Kubernetes

StatefulSet Instead of Deployment

Stable pod identifiers (pod-0, pod-1, pod-2), stable network identifiers, ordered deployment and scaling.

Persistent Volume Claims (PVC)

RocksDB for Kafka Streams lives on local disk. PVC guarantees state is not lost on pod restart.

Pod Disruption Budgets (PDB)

Protection from mass pod deletion. For example, minAvailable: 2 guarantees at least 2 pods always running.

Anti-affinity

Distribution of pods across different physical nodes. If one node fails — the service continues to work.

• • •

VGitOps and Environment Promotion

  1. Dev → Staging → Production. Sequential promotion of changes through environments.
  2. Environment parity. Same configurations across all environments — what works in staging works in production.
  3. Configuration management. Helm, Kustomize for parameterizing manifests.
  4. Automated sync. Argo CD applies git changes within N seconds after commit.
  5. Rollback via git revert. Rollback = revert commit in git, controller brings cluster to previous state.
• • •

VIDatabase Migrations: Schema Evolution for State Stores

Tool Model When to Choose
FlywayVersioned SQL migrationsSimple, plain SQL, full control
LiquibaseChangelog-basedMulti-DB, XML/YAML/SQL, rollback
AtlasDeclarative schemaSchema-as-code, diff-based
Expand-Migrate-ContractPatternZero-downtime migration
• • •

VIIFull Stop and Restart

  1. Code commit. Developer merges changes to main, CI starts.
  2. Auto-tests. Unit + integration tests with isolated environments (Testcontainers).
  3. Pre-flight checks. Input/output streams exist, ACL granted, new schemas compatible.
  4. Stop, cleanup, start. Old instances stopped. State stores, offsets, internal topics reset. New container deployed. Rollback if failed.
  5. Post-checks. Consumer lag back to normal, no anomalies in logs, endpoints respond.
• • •

VIIIRolling Update

Critical Limitation

Rolling update is not applicable if the internal topology of the microservice, state store structure, or internal event schemas changed. Any of these changes requires a full application reset.

• • •

IXCanary Deployment: 1% of Traffic

Stage Traffic Share Duration
Canary1%30 minutes
Ramp-up10% → 50% → 100%every 30 minutes
Full rollout100%permanent
Automatic Rollback

If canary metrics are worse than the old version — automatic rollback. Tools: Argo Rollouts, Flagger, Spinnaker. Don't rely on manual decision — metrics decide.

• • •

XBlue-Green Deployment

Doesn't Work for Stream Producers

If a microservice generates output events in response to input streams, the "blue" and "green" versions will simultaneously write to the same output stream. For entity events, this leads to overwrites; for regular events, to duplicates.

• • •

XIBreaking Schema Changes

Continued Migration (Two Streams)

Producer writes to both old and new streams. Old is marked as deprecated. Consumers migrate at their own pace.

Synchronized Migration (One Stream)

Producer switches to new format and completely stops writing to the old stream. All consumers must update simultaneously.

• • •

XIIFeature Flags: Separate Deploy from Release

LaunchDarkly

Managed feature flags. SDK for all languages, A/B testing, metrics.

Unleash

Open-source alternative. Self-hosted, flexible strategies, audit log.

Split.io

Feature delivery + experimentation. Managed, advanced analytics.

Kill switch

Instant feature disable without deploy. Critical for EDA where state rollback is expensive.

• • •

XIIIRollback Strategies

Rollback Type What It Does When to Apply
Instant rollbackReturn old image versionBugs not related to state
State rollbackRestore state from changelog/snapshotNew version corrupted state
Offset rollbackRewind offsets to previous positionProcessed events with error
Schema rollbackReturn previous schema versionBreaking change didn't work
Full resetReset state + offsets + internal topicsCatastrophic failure
• • •

XIVSaga and Graceful Shutdown

// Graceful shutdown with drain
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    running = false;
    sagaManager.drain(Duration.ofMinutes(5));
    consumer.close(Duration.ofSeconds(10));
}));
• • •

XVDeployment Monitoring

Metric What It Shows Alert Threshold
consumer_lagLag from stream tailGrowing during deploy
error_rateError share> baseline × 1.5
throughputProcessing speedDrop > 30%
commit_latency_p9999th percentile commit time> SLA
rebalance_countRebalances per hour> 2 per hour
dlq_rateEvents sent to DLQ> 0.1%
• • •

XVICost of Deployment

Item What It Includes Optimization
State rebuildReplaying changelogSnapshot before deploy, standby replicas
ReprocessingReplaying input streamsBatching, off-peak windows
Blue-green × 2Double resource usageShort overlap window, autoscaling
Canary × 1.05+5% resources for canaryShort ramps, only for critical services
Managed K8sHourly paymentSpot instances, scale to zero
Managed KafkaThroughput paymentCorrect retention, tiered storage
• • •

XVIIChecklists and Link to the Series

Link to Previous Chapters

Chapter Focus Link to This Chapter
I. The Medium Shapes the ArchitectureTeam Topologies, distributed monolithTeam autonomy, anti-pattern of synchronized deploy
III. The Anatomy of an Ideal EventSchema evolutionSchema rollback, breaking change migration
V. The Mechanics of Stream ProcessingState stores, rebalanceStatefulSet, PVC, graceful shutdown
VI. Time in StreamsReprocessingCost of state rebuild
VII. The Memory of MicroservicesState store migrationRolling update, blue-green, state rollback
VIII. The Mechanics of Business ProcessesLong-running processesGraceful shutdown, draining mode
XII. Anatomy of Lightweight FrameworksKafka Streams internal topicsStatefulSet, PVC, Strimzi operator
XIV. The Microservices TaxCI/CD, tooling, platformGolden path, self-service, GitOps
XV. How to Test the UnobservableTesting infrastructurePre-flight checks, canary analysis
XVI. Deploying Event-Driven MicroservicesDeployment strategiesProduction delivery perspective

EDA Deployment Checklist

  • CI/CD pipeline configured and runs automatically
  • Schema compatibility check in CI (Backward / Forward / Full)
  • Contract testing in CI (Pact, schema validation)
  • Testcontainers for integration tests
  • Kubernetes operator installed (Strimzi, Flink K8s Operator)
  • StatefulSet + PVC for stateful workloads
  • Pod Disruption Budget configured
  • Anti-affinity for distribution across nodes
  • GitOps (Argo CD, Flux) for declarative deployment
  • Database migrations via Flyway / Liquibase / Expand-Migrate-Contract
  • Deployment template chosen: full stop, rolling, canary, blue-green
  • Feature flags to separate deploy from release
  • Rollback strategy defined (instant, state, offset, schema, full)
  • Graceful shutdown for Saga
  • Deployment monitoring configured (lag, error rate, throughput)
  • Cost of deployment evaluated and optimized
  • SLA accounts for state rebuild time and downstream impact
  • Service owner independently launches and rolls back releases
Final Thesis

Deploying event-driven microservices is a complex process that must account for state rebuild, stream reprocessing, schema compatibility, and impact on the entire downstream chain. Investments in standardized pipelines, self-service tools, and clear SLAs pay off many times over as the number of microservices grows. Delegate responsibility to owning teams but provide them with reliable automated mechanisms. And always test your deployment plan in an isolated environment as close to production as possible.

Chapter XVI of the "Event-Driven Architecture" series. Sources: Kubernetes, Strimzi, Flink Kubernetes Operator, Confluent for Kubernetes, Argo CD, Argo Rollouts, Flagger, Flyway, Liquibase, LaunchDarkly, Unleash, Temporal, Prometheus, production system case studies, FinCodeCow experience.