Представь: ты полночи деплоишь обновление, говоришь команде «готово», идёшь спать — а утром узнаёшь, что корзина в магазине сломалась и полтысячи заказов потеряно. Знакомо? Именно от этого сценария и спасает canary deployment.

Что это вообще такое

Canary deployment — это когда ты выкатываешь новую версию не сразу всем, а сначала маленькой доле пользователей. Скажем, 1–5%. Смотришь, как оно себя ведёт, следишь за метриками. Если всё хорошо — постепенно расширяешь аудиторию. Если что-то пошло не так — откатываешь, пока большинство пользователей ничего не заметило.

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

Чем canary отличается от blue-green и rolling

Часто эти три подхода путают, поэтому давай расставим по местам.

Blue-green deployment — у тебя две идентичные среды: синяя (текущая) и зелёная (новая). Ты переключаешь трафик целиком с одной на другую. Быстро, чисто, но дорого: нужно держать две полных копии инфраструктуры. И если что-то сломалось — 100% пользователей уже на новой версии до того, как ты это заметил.

Rolling deployment — постепенно заменяешь старые инстансы новыми. Kubernetes делает это по умолчанию. Но здесь нет контроля над тем, кто именно получает новую версию — просто часть запросов идёт на новые поды, часть на старые.

Canary — ты явно управляешь распределением трафика. Говоришь: «1% запросов — на новую версию, 99% — на старую». Можешь таргетировать конкретных пользователей: бета-тестеров, пользователей из определённого региона, тех, у кого флаг early_access = true. Это самый гибкий и безопасный вариант.

Как это устроено технически

Есть несколько уровней, на которых можно реализовать canary.

На уровне балансировщика

Samый простой способ — настроить Nginx или HAProxy так, чтобы часть запросов шла на новые инстансы. В Nginx это выглядит примерно так:

upstream backend {
    server old-app:8080 weight=99;
    server new-app:8080 weight=1;
}

Это даёт тебе грубое управление: 1% трафика на новую версию. Но никакой гранулярности — один и тот же пользователь может попасть то на старую версию, то на новую в разных запросах. Для stateless-сервисов это нормально, для stateful — может быть проблемой.

На уровне Kubernetes

Если работаешь с k8s, можно держать два Deployment: app-stable и app-canary. Управляешь соотношением через количество реплик:

# stable: 9 реплик
# canary: 1 реплика
# итого 10% на canary

Но это грубо. Для точного управления трафиком лучше использовать service mesh — Istio или Linkerd. Istio позволяет прописать правила типа:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
spec:
  http:
  - match:
    - headers:
        x-canary-user:
          exact: "true"
    route:
    - destination:
        host: app-canary
  - route:
    - destination:
        host: app-stable
      weight: 95
    - destination:
        host: app-canary
      weight: 5

Теперь ты можешь отправлять на canary конкретных пользователей (по заголовку) плюс 5% случайных.

Feature flags как canary

Ещё один подход — выкатить новый код всем, но скрыть его за флагом. Функциональность включается не для всех, а для выбранной группы. Это популярно в больших командах: LaunchDarkly, Unleash, самописные решения на Redis.

Плюс — код един, нет двух параллельных версий на инфраструктуре. Минус — технический долг растёт, если флаги не убирать вовремя.

Метрики: что смотреть во время canary

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

Ошибки (error rate). Базовый показатель. Если на stable 0.1% ошибок, а на canary вдруг 2% — стоп, откат.

Latency (p50, p95, p99). Новая версия может работать корректно, но медленнее. Пользователи это почувствуют. Следи не только за средним временем ответа, но и за хвостами распределения.

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

Saturation. Потребление CPU, памяти, дискового I/O. Иногда новая версия работает нормально под малой нагрузкой, но течёт по памяти — и ты увидишь это только при постепенном росте.

Всё это должно быть в дашборде рядом с кнопкой «расширить canary» и «откатить». Grafana + Prometheus — стандартный выбор. DataDog, New Relic — если бюджет позволяет.

Автоматизация: когда робот решает за тебя

Ручной canary — это когда ты сам смотришь на графики и принимаешь решение. Это нормально для небольших команд.

Автоматизированный canary — система сама сравнивает метрики canary и stable, и либо продвигает деплой дальше, либо откатывает. Это называется progressive delivery.

Flagger — опенсорсный инструмент для k8s, который делает именно это. Ты описываешь политику:

apiVersion: flagger.app/v1beta1
kind: Canary
spec:
  analysis:
    interval: 1m
    threshold: 5        # максимум 5 неудачных проверок
    maxWeight: 50       # максимум 50% на canary
    stepWeight: 10      # шаг 10%
    metrics:
    - name: request-success-rate
      min: 99           # минимум 99% успешных запросов
    - name: request-duration
      max: 500          # максимум 500ms на p99

Flagger каждую минуту проверяет метрики. Если всё хорошо — добавляет 10% к canary. Если метрики падают ниже порога 5 раз подряд — автоматически откатывает и уведомляет в Slack.

Argo Rollouts — альтернатива от команды Argo, тоже популярна в k8s-экосистеме.

Типичные ошибки

Слишком маленькая выборка. Если на canary идёт 0.1% трафика при 100 запросах в сутки — это 0.1 запроса. Ты ничего не увидишь. Canary нужна статистически значимая нагрузка. Для нагруженных сервисов 1% может быть достаточно; для маленьких — возможно, нужно 10–20%.

Слишком быстрое продвижение. «Десять минут на каждый шаг» — звучит разумно, пока не выяснится, что баг проявляется только через час работы сессии. Интервал наблюдения должен соответствовать паттернам использования.

Нет rollback-плана. Canary хороша именно тем, что откат быстрый. Но «быстрый» значит «заранее проверенный». Ты должен знать точно: как откатить, сколько времени займёт, нужна ли миграция базы.

Несовместимые миграции базы данных. Canary предполагает, что два варианта кода работают одновременно. Если новая версия добавляет поле в БД и делает его обязательным — старая версия начнёт падать. Правило простое: любая миграция базы должна быть обратно совместимой с предыдущей версией кода. Сначала добавляешь поле как nullable, потом деплоишь новый код, потом делаешь поле обязательным.

Игнорирование бизнес-метрик. Технические метрики в порядке, а конверсия упала на 15% — и ты этого не заметил, потому что не смотрел. Договорись с продуктом заранее, что именно мерить.

Когда canary не нужен

Не каждый деплой требует canary. Это инструмент с накладными расходами: нужна инфраструктура, мониторинг, дисциплина команды.

Canary оправдан, когда:

  • сервис критичный (платежи, авторизация, заказы)
  • аудитория большая, цена ошибки высокая
  • изменение нетривиальное — новый алгоритм, рефакторинг ядра

Можно обойтись без canary:

  • правишь опечатку в тексте
  • меняешь конфиг, который легко откатить
  • сервис внутренний, нагрузка маленькая, пользователи терпимы к авариям

Веб-студия REEXY при разработке корпоративных сайтов и интернет-магазинов всегда обсуждает с клиентом стратегию деплоя: для простых визиток достаточно прямого обновления, для нагруженного e-commerce — продуманный staging и поэтапный выкат.

Практический чеклист перед canary

Прежде чем нажать кнопку, пройдись по списку:

  • Метрики настроены и разбиты по версиям (stable vs canary)
  • Определены пороги: что считается «плохо» для error rate, latency, бизнес-метрик
  • Есть алерты с коротким временем реакции (не 1 час, а 5 минут)
  • Rollback-процедура задокументирована и проверена
  • Миграции БД обратно совместимы
  • Команда знает, кто принимает решение о продвижении или откате
  • Время деплоя выбрано с умом — не пятница вечер, не пиковый час нагрузки

Инструменты, которые стоит знать

Flagger — автоматизированный canary для k8s, работает с Istio, Linkerd, Nginx, Traefik.

Argo Rollouts — расширяет k8s Deployment canary и blue-green стратегиями, хорошая интеграция с Argo CD.

Spinnaker — тяжёлая платформа continuous delivery от Netflix, canary analysis встроен.

LaunchDarkly / Unleash — feature flags, если хочешь управлять canary на уровне кода, а не инфраструктуры.

Grafana + Prometheus — база для метрик и дашбордов.

Для тех, кто только начинает и хочет простое решение: настрой два Deployment в k8s с разным количеством реплик, сделай дашборд в Grafana и назначь человека, который раз в 15 минут смотрит на графики во время деплоя. Это уже canary — пусть и ручной.

Как это выглядит в реальном деплое

Вот пример последовательности для e-commerce:

  1. Выкатываем canary на 2% трафика. Ждём 30 минут.
  2. Error rate в норме (0.08% против 0.07% на stable). Latency не изменилась. Добавления в корзину — в пределах нормального разброса.
  3. Расширяем до 10%. Ждём час — это покрывает один цикл пика активности.
  4. Всё хорошо. Расширяем до 50%, смотрим ещё 30 минут.
  5. Деплоим на 100%, убираем canary-инстанс.

Весь процесс занял около двух часов. Если бы на шаге 2 error rate вырос до 1% — откат занял бы 30 секунд, и 98% пользователей ничего бы не заметили.

При правильно выстроенной инфраструктуре заказать интернет-магазин с профессиональной стратегией деплоя у той же REEXY можно от 10 000 ₽, и вопросы надёжности выкатки обновлений будут частью обсуждения с самого начала.

Canary deployment — это не серебряная пуля. Но это один из немногих инструментов, который позволяет выкатывать изменения с реально управляемым риском. Начни с малого: два Deployment, базовый мониторинг, фиксированный процент. Остальное придёт с практикой.