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 і автоматизуйте захисні ворота - і будь-який реліз стане оборотним за хвилини, без болю для бізнесу і користувачів.