Rollback стратегии и атомарные релизы
Rollback стратегии и атомарные релизы
1) Зачем нужен быстрый откат
Даже при отличном тестовом покрытии прод не гарантирует безошибочность. Rollback — это управляемое возвращение системы в предыдущее устойчивое состояние по сигналу SLO/бизнес-метрик или инцидента. Цели:- Сократить MTTR до минут.
- Ограничить радиус поражения (минимум затронутых пользователей/транзакций).
- Сохранить целостность данных и совместимость контрактов.
Ключ: строить релизы так, чтобы откат был тривиальным действием, а не мини-проектом.
2) Понятие «атомарного релиза»
Атомарный релиз — когда включение новой версии/поведения можно выполнить (и отменить) одной атомарной операцией без длительных побочных эффектов.
Компоненты атомарности:- Иммутабельный артефакт (подписанный образ/пакет).
- Версионированные конфиги (промоушен версии, а не ручные правки).
- Отделение «доставки» от «включения» (маршрутизация/флаги).
- Совместимая схема данных (обе версии могут жить одновременно).
- Runbook отката: один понятный шаг (смена селектора/веса/флага) + проверка.
3) Инвентарь роллбек-механизмов
3.1 Трафик-уровень (самый быстрый)
Blue-Green: переключить селектор/target group на стабильную версию.
Canary: опустить вес до 0% и заморозить прогрессию.
Gateway/NGINX/Service Mesh: вернуть прежние веса/маршруты.
3.2 Конвейер-уровень
Helm/Argo Rollouts: `abort/rollback` к предыдущему ревизу.
GitOps: revert MR/commit в манифест-репозитории (контроллер сделает остальное).
3.3 Приложение/фичи
Feature-flags / kill-switch: мгновенно выключить рискованный путь.
Toggle конфигов: вернуться к предыдущему конфиг-снапшоту.
3.4 Данные
Roll-forward миграции (предпочтительны) + совместимость.
Point-in-time recovery (PITR) и бэкапы для аварий.
Компенсации (Saga) и idempotency для обратимых действий.
4) Паттерн «expand → migrate → contract» (БД)
Чтобы откат был безопасным, схема данных должна позволять ко-жить старой и новой версиям.
1. Expand — добавить новые поля/индексы (nullable), не ломая старую логику.
2. Migrate — двойная запись/чтение, бэк-филл, фоновые job’ы с idempotency.
3. Contract — удалить старые поля/код после выхода на 100% и выдержанного окна.
5) SLO-гейтинг и авто-откат
Вход в каждую ступень релиза должен «охраняться» метриками.
Технические SLO: p95/p99 латентность, 5xx-rate, saturation (CPU/Memory), error-budget burn.
Бизнес-метрики: CR на депозит/кассаут, отказ в платежах, процент фрода, ошибки KYC.
- 5xx > 0.5% 10 минут → rollback.
- p95 ↑ > 20% от базовой → hold + анализ.
- Ошибка у PSP > 0.3 п.п. → rollback + переключение маршрута платежей.
6) Примеры: Kubernetes/Helm/Argo/NGINX
6.1 Blue-Green (K8s Service selector)
yaml
Service points to "blue"; switch to green - change selector apiVersion: v1 kind: Service metadata: {name: app-svc}
spec:
selector: { app: app, version: blue }
ports: [{ port: 80, targetPort: 8080 }]
Откат = вернуть селектор на `blue` (атомарно, без пересборки).
6.2 Canary (Istio VirtualService веса)
yaml http:
- route:
- destination: { host: app, subset: stable } # 100 weight: 100
- destination: { host: app, subset: canary } # 0 weight: 0
Откат = weight canary → 0, stable → 100.
6.3 Argo Rollouts — abort
yaml kubectl argo rollouts abort app # stop and return to stableService
6.4 Helm — rollback к ревизии
bash helm history app -n prod helm rollback app 17 -n prod # revert to revision 17
6.5 NGINX — upstream веса
nginx upstream app {
server blue:8080 weight=100;
server green: 8080 weight = 0; # rollback - return 100/0
}
7) Feature-flags и kill-switch как «парашют»
Kill-switch для высокорисковых потоков (депозиты/выплаты/бонусы) — обязательный.
Stickiness: назначение пользователям «варианта» через хеш-ключ — предсказуемые сравнения.
Fail-safe: при недоступности сервера флагов — безопасный дефолт.
ts const enabled = flags. bool("new_cashout_flow", false);
if (! enabled) return classicFlow () ;//instant rollback - disable the return newFlow () flag;
8) Контракты API и событий: как не «сломать откат»
Версионируйте контракты (OpenAPI/gRPC/Avro): новая версия добавляет поля, не меняет семантику старых.
Event-versioning: `type=v2`, потребители обязаны игнорировать неизвестные поля.
Outbox + Idempotency: любой повтор события безопасен, потребитель — идемпотентен.
9) Компенсирующие транзакции (Saga)
Когда «жесткого» отката состояния нет (деньги ушли, письмо отправлено), используйте compensation:- Провели списание — компенсация: возврат, сторнирование, корректирующая запись.
- Запись в журнал компенсирующих операций и ретраи до успеха.
- Идемпотентные ключи на каждую операцию.
json
{
"sagaId": "b7d2...",
"action": "withdraw. execute",
"idempotencyKey": "user123:withdraw:7845",
"compensation": "withdraw. refund"
}
10) Конфиги и секреты: откат как версия
Храните конфиги как артефакты с версиями (semver/commit-sha).
Откат = вернуть конфиг к предыдущей версии (GitOps revert), а не «исправить руками».
Секреты — через хранилище (KMS/Vault); ротация и версионирование включены в релиз.
11) Runbook отката (минимальный)
1. Пауза прогрессии (canary/rollouts).
2. Возврат трафика (веса/селектор).
3. Проверка SLO/бизнес-метрик вернулись к базовой линии.
4. Стабилизация фоновых job’ов (остановить миграции/бэк-филл при необходимости).
5. Инцидент и пост-фактум: артефакты (логи/трейсы/метрики), гипотезы, исправление.
6. Чистка: закрыть флаги, убрать оставленный код, вернуть расписания job’ов.
12) Политики автоматической защиты
Запрет `latest` и мутабельных тегов для образов.
Admission-контроль: только подписанные артефакты.
CI-ворота: SAST/SCA/Policy-checks должны быть зелеными для промоушена.
Freeze окна: запрет релизов/веса > X% в риск-периоды.
13) Частые анти-паттерны
«Откатываем» базу DDL-вниз вместо совместимости — долгие блокировки/простой.
Мгновенные миграции «в лоб» без idempotency и бэк-филла.
Смешивание «доставки» и «включения» — нет возможности быстро вернуть трафик.
Ручные правки в прод-конфиге без аудита.
Отсутствие kill-switch на платежах/выводах.
Пересборка артефакта для prod (нарушение «build once — run many»).
Нет единой кнопки отката / не отработанный runbook.
14) Чек-лист внедрения (0–45 дней)
0–10 дней
Включить Blue-Green/Canary на ключевых сервисах.
Запретить `latest`, включить подпись образов и историю Helm/Argo.
Подключить SLO-доски (latency, 5xx, ключевые бизнес-сигналы).
11–25 дней
Реализовать kill-switch для риск-флоу.
Перевести миграции БД на expand-migrate-contract + idempotency.
Добавить авто-стоп/rollback по SLO (Argo AnalysisTemplate/алерты).
26–45 дней
Версионировать конфиги (GitOps), откат через MR-revert.
Обкатать runbook на «game-day» (симуляция инцидента и отката).
Ввести Saga-компенсации там, где откат «вниз» невозможен.
15) Метрики зрелости
MTTR отката: цель < 5 мин.
% релизов, где откат = переключение маршрута/флага (без пересборки) > 90%.
Доля миграций по схеме expand-migrate-contract > 90%.
Покрытие сервисов kill-switch флагами > 95%.
Количество инцидентов из-за несовместимых схем/контрактов → 0.
16) Приложения: мини-шаблоны
Argo AnalysisTemplate: стоп по 5xx
yaml apiVersion: argoproj. io/v1alpha1 kind: AnalysisTemplate metadata: { name: guard-5xx }
spec:
metrics:
- name: http_5xx_rate interval: 1m successCondition: result < 0. 005 provider:
prometheus:
address: http://prometheus. monitoring:9090 query:
sum(rate(http_requests_total{app="app",status=~"5.."}[5m])) /
sum(rate(http_requests_total{app="app"}[5m]))
Kubernetes: быстрый откат Deployment
bash kubectl rollout undo deploy/app -n prod
Helm: атомарный релиз
bash helm upgrade --install app chart/ \
--atomic \
--timeout 5m \
--set image. tag=v1. 9. 3
NGINX: «кран» для канареек
nginx map $cookie_canary $weight {
default 0;
"~ on" 10; # enable 10% by cookie
}
17) Заключение
Надежный откат — это не «пожарная кнопка», а свойство архитектуры: иммутабельные артефакты, разделение доставки и включения, совместимая схема данных, фича-флаги и SLO-гейтинг. Постройте релизы атомарными, отрепетируйте runbook и автоматизируйте защитные ворота — и любой релиз станет обратимым за минуты, без боли для бизнеса и пользователей.