Canary Deployment — это подход «давайте не будем сразу выкатывать всё всем». Сначала новая версия приложения получает только часть трафика, остальное продолжает идти на стабильную. Если по метрикам всё хорошо — увеличиваем долю новой версии, пока она не станет основной. Если нет — откатываемся, и пострадала только небольшая часть пользователей.
Название взято из старой практики с канарейками в шахтах: птицу брали с собой, и если она начинала дохнуть от газа — это был сигнал, что пора валить. Здесь canary-версия — такой же ранний индикатор проблем.
Зачем вообще заморачиваться с canary #
- Аккуратно включать новую функциональность, а не сразу «всем и сразу»;
- Ловить регрессии и баги до массового выката;
- Снизить риск: если что-то сломается, сломается только у небольшой аудитории;
- Делать A/B-тесты без отдельного зоопарка окружений;
- Иметь возможность автоматического/ручного отката по метрикам.
Как это реализуется в Kubernetes #
В Kubernetes всё сводится к тому, чтобы иметь две версии приложения и как-то делить между ними трафик:
- Отдельные
Deployment/ReplicaSet с разными метками, типаversion: v1иversion: v2; - Service или Ingress, которые направляют трафик по правилам/весам;
- На уровне L7 — Service Mesh или Ingress-контроллер (Istio, Linkerd, Traefik, NGINX Ingress) для тонкой маршрутизации;
- Для полной автоматики — Argo Rollouts или Flagger, которые следят за метриками и сами двигают веса.
Пример с Istio VirtualService #
http:
- route:
- destination:
host: app
subset: stable
weight: 80
- destination:
host: app
subset: canary
weight: 20
В таком виде 80% запросов уезжают на старую версию, 20% — на новую. Потом можно менять веса: 30/70, 50/50 и так далее.
Отличие от Blue-Green #
| Подход | Переключение | Плюсы | Типичные сценарии |
|---|---|---|---|
| Canary | Постепенное, через веса | Гибкость, меньше рисков, тесная работа с метриками | Частые релизы, эксперименты, A/B-тесты |
| Blue-Green | Резко, одним махом | Простая модель, быстрый rollback | Прод с жёсткими SLA, когда меньше вариантов — лучше |
Интеграция с CI/CD #
Canary можно делать руками, а можно полностью автоматизировать:
- Ручной режим — сами меняем веса (в VirtualService, ingress-аннотациях и т.п.), смотрим на метрики, решаем, двигаться дальше или откатываться;
- Автоматический режим — через Argo Rollouts, Flagger, Spinnaker:
- они следят за метриками (5xx, latency, error rate и т.п.);
- если всё в норме — двигают canary дальше, увеличивают долю трафика;
- если нет — инициируют откат и помечают rollout как неуспешный.
Какие инструменты чаще всего используют #
| Инструмент | Что делает | Автооткат | GitOps |
|---|---|---|---|
| Argo Rollouts | Контроллер + CRD для постепенных rollout’ов | Есть | Хорошо дружит |
| Flagger | Оператор, который делает canary поверх Ingress/Mesh | Есть | Тоже можно вписать |
| Istio | VirtualService даёт ручной контроль над весами | Нет встроенного, всё руками/через CI | |
| NGINX Ingress | Аннотации типа canary-weight | Частичная поддержка, остальное — логика вокруг |
В итоге Canary Deployment — один из самых аккуратных способов выкатывать изменения в Kubernetes: можно интегрировать мониторинг, метрики и сделать нормальный автооткат, если новая версия ведёт себя нестабильно.
1. Rollout-манифест для Argo Rollouts #
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
replicas: 4
strategy:
canary:
steps:
- setWeight: 10
- pause: { duration: 5m }
- setWeight: 50
- pause: { duration: 10m }
- setWeight: 100
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: myregistry/my-app:{{ .Values.image.tag }}
ports:
- containerPort: 8080
Здесь Argo сам двигает веса: сначала 10% трафика на новую версию, потом 50%, потом 100%. Между шагами делает паузы — за это время можно смотреть на метрики или подождать алертов.
2. PrometheusRule для отката по метрикам #
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: canary-failures
namespace: monitoring
spec:
groups:
- name: canary-errors
rules:
- alert: Canary5xxSpike
expr: |
increase(http_requests_total{status=~"5..", app="my-app"}[5m]) > 10
for: 2m
labels:
severity: critical
annotations:
summary: "Canary 5xx spike"
description: "5xx errors increased after canary rollout. Rollback recommended."
Дальше это можно связать с webhook’ом, который скажет Argo Rollouts «всё плохо, откатывайся».
3. Настройки Helm в values.yaml #
image:
tag: "v2.1.3"
canary:
enabled: true
weightSteps:
- 10
- 50
- 100
pauseDurations:
- 5m
- 10m
Эти параметры можно подставлять в шаблон Rollout’а, чтобы не переписывать YAML каждый раз руками при смене стратегии.
4. GitOps с Argo CD #
- Файл
rollout.yamlлежит в отдельном gitops-репозитории; - Argo CD следит за ним и тянет изменения в кластер;
- CI (GitLab, GitHub Actions и т.п.) меняет тег образа и/или параметры веса, коммитит это в репозиторий;
- Prometheus даёт алерт → webhook → Argo Rollouts делает откат, всё это остаётся в истории Git.
