Canary и Progressive Delivery: как выкатывать изменения без страха

Представьте, что вы шеф-повар и придумали новое блюдо. Вы не выносите его сразу в большой зал всем посетителям. Сначала пробуете сами. Потом даёте попробовать коллеге. Потом ставите в меню как специальное предложение на один день. И только если все в восторге — вводите в постоянное меню.

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

Почему это важно для SRE?

Большинство инцидентов вызвано изменениями (см. главу «Почему большинство инцидентов вызвано изменениями?»). Чем быстрее и шире вы катите изменение, тем больше blast radius. Progressive Delivery — это про то, чтобы сделать blast radius управляемым.

Но есть и второй, не менее важный эффект: Progressive Delivery снижает MTTR до нуля для большинства проблем. Если вы заметили проблему на 1% трафика — MTTR считается в секундах (просто откатили канарейку). Если вы заметили её на 100% — MTTR считается в часах (деплой предыдущей версии, перезапуск всех инстансов, проверка).

Спектр стратегий

Progressive Delivery — это зонтичный термин. Под ним прячутся несколько стратегий, которые можно комбинировать:

1. Ramped Deployment (постепенная раскатка)

Классика. Новая версия замещает старую порциями: 10% → 25% → 50% → 100%.

Старая версия: ████████████████████████████████████████
Новая версия:  ░░░░░░░░░░
Шаг 1 (10%):   ██████████████████████████████████████████░░░░░░░░░░
...
Шаг N (100%):  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

Когда использовать: обычные релизы, где нет жёстких требований к мгновенному переключению. Просто, надёжно, работает.

Риск: на каждом шаге есть небольшой период, когда обе версии работают одновременно. Нужно убедиться, что они совместимы (нет проблем с обратной совместимостью API, миграциями БД и т.д.).

2. Canary Deployment

Вы поднимаете отдельный пул инстансов с новой версией и направляете на него малый процент трафика.

Канареечный пул (2%):  ░░░░
Старый пул (98%):      ████████████████████████████████████████

Canary-деплой был описан в главе «Постепенное снижение риска». Ключевое отличие от ramped — вы держите канареечный пул изолированно и можете мгновенно снять с него трафик, оставив старые инстансы нетронутыми.

Когда использовать: критичные сервисы, где откат рампом слишком долог. Сервисы с реальным пользовательским трафиком, где важно проверить поведение под нагрузкой.

Что измерять на канарейке: - Латентность (p50, p95, p99) — не просела ли? - Коды ответов — не вырос ли процент 5xx? - Потребление ресурсов (CPU, RAM) — не утекло ли что-то? - Бизнес-метрики (конверсия, заказы) — не упала ли? — это уже A/B-тест, не всегда обязателен

3. Blue-Green Deployment

Два идентичных окружения (Blue и Green). В один направлен весь трафик, во втором — новая версия. Переключение мгновенное:

  • Blue — текущий продакшен
  • Green — подготовленная новая версия
  • Переключили балансировщик — и всё.

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

Цена: нужно вдвое больше ресурсов. В Kubernetes это означает два полных набора подов, что дорого. Blue-Green часто используют для баз данных или stateful-сервисов, где ramped-деплой невозможен.

4. A/B-тестирование (эксперименты)

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

Группа A (50%): ████████████████████████████████████████  старая версия
Группа B (50%): ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  новая версия

Отличие от canary: canary проверяет «не сломалось ли». A/B-тест проверяет «стало ли лучше». Для canary достаточно технических метрик. Для A/B нужна бизнес-аналитика, статзначимость и разделение пользователей по ID.

5. Feature Flags (флаги функций)

Это отдельный инструмент, который позволяет включать и выключать функциональность без деплоя. Feature flags можно комбинировать с любой из стратегий выше. Подробно разобрано в главе «Feature Flags: рубильники безопасности для продакшена».

Сводная таблица

Стратегия Blast radius Скорость отката Сложность Ресурсы
Ramped Средний Средняя Низкая N
Canary Низкий Высокая Средняя N + canary
Blue-Green Полный Мгновенная Средняя 2N
A/B-тест Зависит Средняя Высокая N + аналитика
Feature Flags Минимальный Секунды Средняя N + сервис флагов

Какую стратегию выбрать?

Зависит от контекста:

  • Если у вас 10 микросервисов и одна команда — ramped + feature flags решают 90% задач.
  • Если у вас high-load, критичный сервис — canary как обязательный стандарт, поверх — feature flags.
  • Если в сервисе состояние (stateful, БД) — blue-green или сложные паттерны миграций.
  • Если бизнес хочет данные — A/B-тесты поверх любой технической стратегии.

Progressive Delivery и SLO

Progressive Delivery становится ещё мощнее в связке с SLO. Идея: автоматически приостанавливать раскатку, если SLO начал нарушаться.

# Псевдокод: пайплайн progressive delivery с проверкой SLO
steps:
  - canary: 2%
    duration: 5m
    check: SLO_green?  # Все SLI в норме?
  - ramp: 25%
    duration: 10m
    check: SLO_green?
  - ramp: 50%
    duration: 10m
    check: SLO_green?
  - ramp: 100%
    duration: 0

Если на любом шаге SLO просел — пайплайн останавливается, автоматический откат, нотификация в чат.

Автоматический откат по SLO

Это самый зрелый уровень. Система сама решает, катить дальше или нет:

  1. Выкатили канарейку на 2%.
  2. Система мониторит SLI (латентность, ошибки).
  3. Если SLI выходят за SLO — пайплайн сам отзывает canary и шлёт уведомление.
  4. Если всё зелёное — пайплайн раскатывает дальше.

Человек участвует только в анализе причины остановки. Принятие решения «катить или нет» делегировано автоматике. Подробнее — в главе «SLO как код».

Технические сложности

Progressive Delivery прекрасен в теории, но на практике есть подводные камни:

  • Совместимость данных. Если новая версия меняет схему БД, то ramped-деплой может сломать старые инстансы, которые пишут по-старому, а читают по-новому. Решение: миграции БД вперёд-назад (forward/backward compatible), разделение деплоя кода и миграции схемы.
  • Сессии пользователей. Если пользователь попал на новую версию, а при следующем запросе — на старую, он может увидеть глюки. Решение: sticky sessions (привязка к инстансу) или stateless-архитектура.
  • Метрики и мониторинг. Нужно уметь разделять метрики по версиям. Без этого вы не поймёте, зеленая канарейка или нет. В Prometheus это решается лейблами version и deployment=canary. Подробнее — в главе «Метрики и проклятие cardinality».
  • Кэши и CDN. Если вы катите новую версию фронтенда через CDN, старая версия может кешироваться у пользователей на дни. Решение: versioning в URL, короткий TTL для критичных ресурсов.

Итог

Progressive Delivery — это не про «как быстро выкатить фичу». Это про «как выкатить фичу так, чтобы в случае проблем никто не пострадал». Это превращает релиз из события (стресс, ночные деплои, молитвы) в процесс (рутинный, автоматизированный, безопасный).

SRE-подход: каждая стратегия хороша в своём контексте. Начинайте с ramped + feature flags. Для критичных сервисов добавляйте canary с автоматической проверкой SLO. И никогда не выкатывайте новую версию сразу на 100% трафика — даже если вы уверены на 200%.