Заметка

Argo Rollouts: canary и blue-green с авто-rollback по метрикам

Стандартный RollingUpdate объявляет успех, когда поды прошли readiness probe. Argo Rollouts делает выкатку проверяемой гипотезой: canary по шагам, blue-green с preview, AnalysisTemplate с PromQL и burn rate SLO как авто-rollback без участия человека.

kubectl rollout status ответил «successfully rolled out» — но что это доказывает? Только то, что новые поды прошли readiness probe. Проба проверяет «процесс поднялся», а не «сервис работает»: регрессию, поднявшую error rate с 0,1 % до 2 %, стандартный RollingUpdate не заметит — он доведёт замену подов до конца и отчитается об успехе. Инцидент начнётся позже, когда 100 % трафика уже на новой версии. Progressive delivery переворачивает модель: релиз — это гипотеза «новая версия не хуже старой», трафик подаётся порциями, метрики проверяют гипотезу, провал откатывает выкатку без участия человека. В CNCF-стеке этот слой закрывает Argo Rollouts.

Rollout вместо Deployment

Argo Rollouts — контроллер (ставится один раз на кластер) и CRD Rollout: замена Deployment с тем же pod template, но с полем strategyblueGreen или canary. В GitOps-цикле ничего не ломается: CI собирает образ и обновляет тег в gitops-репозитории, ArgoCD синкает манифесты, Rollouts решает, как новая версия получает трафик. Разделение ответственности чистое: GitOps отвечает на вопрос «что деплоим», progressive delivery — «как быстро и с какой страховкой».

Blue-green: мгновенный откат за двойную цену

Стратегия blueGreen держит две полные версии одновременно: activeService направляет боевой трафик на stable-поды, previewService — на новые. С autoPromotionEnabled: false промоция становится ручным гейтом: новую версию можно прогнать smoke-тестами по preview-адресу, пока боевой трафик её не видит. Промоция — переключение Service; откат — то же переключение обратно, секунды в обе стороны. Цена — двойная инфраструктура на время релиза и осторожность с миграциями БД: обе версии смотрят в одну схему.

Canary: трафик по шагам, вердикт — по PromQL

Стратегия canary описывает выкатку как последовательность шагов: setWeight: 20 → пауза → 5080 → полная промоция. Решает не пауза, а анализ: блок analysis подключает AnalysisTemplate — набор PromQL-запросов с порогами, которые контроллер выполняет на каждом шаге начиная с указанного. Проваленный анализ — автоматический abort: вес canary снимается, весь трафик возвращается на stable, объект помечается Degraded. Никто не будит on-call ради решения «откатывать или нет» — откат уже произошёл.

Качество гейта решают метрики. Success rate считается только по 5xx: 4xx — ошибки клиента, и включать их в анализ значит откатывать релизы из-за чужих багов. Latency сравнивается по P99, не по среднему: P50 маскирует хвост, а пользователи жалуются именно на хвост. Оба запроса обычно уже есть в кластере — это те же SLI, что питают SLO-алерты.

Burn rate: SLO как предохранитель деплоя

Связка с SLO даёт следующий уровень: анализ смотрит не на сырой error rate, а на скорость сжигания error budget. При SLO 99,9 % месячный бюджет ошибок — 43 минуты; burn rate 10× съедает его за трое суток. Отсюда правило «при 10× — стоп деплоям»: одно PromQL-условие api:burn_rate:ratio_rate1h > 10 в AnalysisTemplate превращает SLO из отчётной метрики в автоматический предохранитель. Плохая выкатка не доедает бюджет до нуля, а здоровая не блокируется из-за перестраховки: пока бюджет цел, минорный рост ошибок — повод для тикета, не для отката.

Выбор стратегии и три грабли

Выбор прагматичный. Blue-green — когда релизы редкие, observability скромная, а мгновенный откат критичен; платите двойной инфраструктурой. Canary — когда релизы частые и метрики зрелые: дешевле, постепеннее, дружелюбнее к миграциям БД. Рабочий паттерн промоушна по средам: dev — blue-green с ручной промоцией, staging и prod — canary с автоматической.

Грабли, о которые спотыкаются первые внедрения. Первое: HPA обязан таргетить Rollout (scaleTargetRef с kind: Rollout), а не Deployment — иначе автоскейлинг и выкатка дерутся за replicas. Второе: при установке через Kustomize+Helm ArgoCD вечно показывает CRD как OutOfSync — API-server мутирует схему после apply; лечится ignoreDifferences на .spec, .status и аннотации. Третье: секреты во время canary живут в двух версиях — canary-поды видят новую, stable — старую, и rollback возвращает старую; при ротации секретов это нужно учитывать в чеклисте, а не открывать во время инцидента.

Прогрессивная доставка — не роскошь платформ гугловского масштаба. Один контроллер, один CRD и один AnalysisTemplate с двумя PromQL-запросами — и выкатка перестаёт быть прыжком веры: метрики, которые вы уже собираете для алертов, начинают защищать каждый релиз до того, как он станет инцидентом.

© 2026 axyi.ru · CC BY 4.0