Короткий ответ
Через Ingress-контроллер или service mesh (например, Istio VirtualService с weighted-роутингом) трафик делят между стабильной и canary-версией с постепенным шагом (5% → 25% → 50% → 100%); решение о продолжении принимают по сравнению error rate, latency (p95/p99) и бизнес-метрик canary-версии со стабильной на каждом шаге, с автоматическим или ручным откатом при превышении порогов.
Как это работает подробнее
оба набора подов (stable и canary) работают одновременно за одним сервисом/VirtualService, и правило маршрутизации определяет пропорцию запросов на каждую версию. На каждом шаге пайплайн делает паузу (bake time), собирает метрики из Prometheus (или аналога) отдельно по версии (через label `version=canary`/`version=stable`) и сравнивает их.
Пример кода
example.yaml
apiVersion: flagger.app/v1beta1
kind: Canary
spec:
progressDeadlineSeconds: 600
analysis:
interval: 1m
threshold: 5
stepWeight: 10
maxWeight: 50
metrics:
- name: request-success-rate
thresholdRange: {min: 99}
interval: 1m
- name: request-duration
thresholdRange: {max: 500}
interval: 1mЧто использовать на практике
- На практике. критично использовать относительные метрики (разница между canary и stable), а не абсолютные пороги — это учитывает текущую нагрузку и внешние факторы. Автоматизировать анализ удобно инструментами прогрессивной доставки (Flagger, Argo Rollouts), которые сами делают промоушен/откат по заданным Prometheus-запросам.
- Пример. Ожидаемое поведение: Flagger увеличивает вес canary на 10% каждую минуту, пока success rate ≥ 99% и p99 latency ≤ 500ms; при пятикратном подряд нарушении порога (`threshold: 5`) Flagger автоматически откатывает вес canary к 0%.
Подводные камни
- Частые ошибки. сравнивают метрики canary с историческими средними без учёта текущей нагрузки на момент теста, получая ложные срабатывания; дают слишком маленький bake time (например, 30 секунд), не успевая поймать деградацию, которая проявляется только под устойчивой нагрузкой.