Blue-green и canary через Services и labels
K8s native API не имеет “blue-green deploy” или “canary release” как первоклассные ресурсы. Нет kind: BlueGreenDeployment, нет kind: CanaryRelease. Эти стратегии реализуются вручную через комбинацию двух фундаментальных примитивов: двух Deployments с разными labels и одного Service с selector, который выбирает, какой Deployment получает трафик.
Понять это — значит понять, как K8s sticks to minimal API surface и оставляет complex deployment policies для дополнительных слоёв (Argo Rollouts, Flagger, Istio).
Протоколы ребалансировки Kafka: Eager vs Cooperative
Blue-green deployment
Идея: запустить параллельно две копии — blue (v1, production) и green (v2, new release). Тестировать green изолированно через temp Service. Когда уверен — переключить main Service selector с blue на green одной командой. Rollback — точно так же, в обратную сторону.
Шаг 1. Два Deployments с разными labels
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-blue
spec:
replicas: 3
selector:
matchLabels:
app: web
version: blue
template:
metadata:
labels:
app: web
version: blue
spec:
containers:
- name: app
image: my-app:v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-green
spec:
replicas: 3
selector:
matchLabels:
app: web
version: green
template:
metadata:
labels:
app: web
version: green
spec:
containers:
- name: app
image: my-app:v2
Оба Deployments имеют label app: web, но отличаются по version. Это отдельные RS и Pod-ы.
Шаг 2. Main Service пока на blue
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
version: blue # ← главное: selector matches только blue Pods
ports:
- port: 80
targetPort: 8080
Production-трафик идёт только на blue. Green Pods существуют, но Service их не “видит” — они не в endpoints.
Шаг 3. Тест green через temp Service
apiVersion: v1
kind: Service
metadata:
name: web-canary-test # отдельный временный Service
spec:
selector:
app: web
version: green
ports:
- port: 80
targetPort: 8080
Через этот Service можно тестировать green изолированно — например, прогнать smoke-tests, проверить метрики, выполнить нагрузочное тестирование.
Шаг 4. Switch
kubectl patch svc web -p '{"spec":{"selector":{"app":"web","version":"green"}}}'
Один patch — Service selector изменился. EndpointSlice контроллер пересчитывает endpoints — теперь там только green Pods. Трафик мгновенно переключается на green. Blue Pods остаются работающими, но без трафика.
Rollback и cleanup
# Если что-то пошло не так — обратный patch
kubectl patch svc web -p '{"spec":{"selector":{"app":"web","version":"blue"}}}'
# Трафик мгновенно вернулся на blue
# Если green ok — eventually удалить blue Deployment
kubectl delete deploy web-blue
Blue-green даёт instant rollback: один patch — и трафик вернулся. Это самое большое преимущество над RollingUpdate (где rollback — это новый rolling update). Цена: 2× ресурсов на время сосуществования blue и green.
Canary deployment
Идея: вместо полного switch, отдать новой версии малую часть трафика (10%, 25%). Мониторить метрики canary. Если ok — постепенно увеличивать canary replicas + уменьшать production. Если плохо — scale canary в 0 и rollback мгновенный.
Шаг 1. Production + canary Deployments
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-production
spec:
replicas: 9
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
version: stable
spec:
containers:
- name: app
image: my-app:v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-canary
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
version: canary
spec:
containers:
- name: app
image: my-app:v2
Ключевое отличие от blue-green: оба Deployments имеют label app: web, который соответствует Service selector. Pod template labels включают version=stable или version=canary для observability, но это не часть Service selector.
Шаг 2. Один Service на оба
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web # ← matches и production, и canary
ports:
- port: 80
targetPort: 8080
Service видит endpoints из ВСЕХ Pod-ов обоих Deployments — 9 production + 1 canary = 10 endpoints. kube-proxy балансирует через random/round-robin. Примерно 10% запросов идут на canary.
Шаг 3. Progressive shift
# 10% canary
kubectl scale deploy web-canary --replicas=1
kubectl scale deploy web-production --replicas=9
# 25% canary
kubectl scale deploy web-canary --replicas=3
kubectl scale deploy web-production --replicas=9
# 50% canary
kubectl scale deploy web-canary --replicas=5
kubectl scale deploy web-production --replicas=5
# 100% canary
kubectl scale deploy web-canary --replicas=10
kubectl scale deploy web-production --replicas=0
# Cleanup
kubectl delete deploy web-production
kubectl edit deploy web-canary # rename to web-production for next round
Rollback
kubectl scale deploy web-canary --replicas=0
# Canary endpoints исчезают из Service. 100% трафика на stable. Rollback мгновенный.
Killer момент: ratio precision
kube-proxy не делает precise traffic splitting. Если endpoints = 9 stable + 1 canary:
- iptables mode: random selection через
-m statistic --mode random --probability. Каждый Pod статистически получает ~10% от общего трафика, но любой конкретный запрос — это бросок монетки. На малых RPS отклонение может быть 5-15%. - IPVS mode: round-robin (по умолчанию). Более равномерное распределение, но всё ещё на уровне Pod-ов, не запросов.
Это значит:
- Нельзя сказать “9% canary, ни больше ни меньше”
- Нельзя по-разному маршрутить запросы (например, header-based:
x-user-idmod 10) - Нельзя плавно увеличить с 10% до 11% — нужно менять replicas (целые числа)
Для точного traffic splitting нужен Service Mesh (Istio VirtualService с weight), или Ingress controller с traffic-splitting annotations (NGINX canary-weight), или Argo Rollouts с интеграцией одного из них. Native K8s — это только ratio через replicas.
Service Mesh: precise traffic split
# Istio VirtualService — splits traffic 90/10 точно
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: web
spec:
hosts:
- web
http:
- route:
- destination:
host: web
subset: stable
weight: 90
- destination:
host: web
subset: canary
weight: 10
Istio Envoy sidecar реализует precise weighted routing — 90 из 100 запросов идут на stable, 10 на canary, независимо от количества Pods. Это даёт настоящее canary с любыми percentages.
Argo Rollouts / Flagger: progressive delivery as CRD
Native K8s + service mesh — это всё ещё manual. Чтобы автоматизировать, существуют CRD-based progressive delivery controllers:
- Argo Rollouts — заменяет
kind: Deploymentнаkind: Rolloutс canary/blue-green strategies в spec. Автоматическое progressive shift с pause-ами между шагами, integration с Prometheus для analysis, automated rollback при failed metrics. - Flagger — sidecar контроллер, который работает с обычным Deployment + Istio/Linkerd/AppMesh. Аналогичные возможности.
# Argo Rollouts: declarative canary
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: web
spec:
strategy:
canary:
steps:
- setWeight: 10
- pause: { duration: 5m }
- setWeight: 25
- pause: { duration: 5m }
- setWeight: 50
- analysis:
templates:
- templateName: success-rate
- setWeight: 100
Controller автоматически проходит шаги: setWeight=10 → ждёт 5m → setWeight=25 → … → run analysis (например, проверить error rate в Prometheus) → если ok, setWeight=100. Если analysis fail — automatic rollback.
CKAD scope — знать концепции blue-green и canary, реализовать через Deployments + labels + Services. Argo Rollouts — это уже CKA/SRE territory, но обязательно знать про существование (вопросы в multiple-choice часто).
Killer-моменты
- K8s native API НЕ имеет blue-green/canary — это паттерны на основе двух Deployments и Service selector.
- Blue-green: 2 Deployments с разными labels, switch через
kubectl patch svc. Instant rollback, 2× ресурсов. - Canary: 2 Deployments с одинаковой label, один Service видит оба. Traffic ratio = replicas ratio.
- Ratio precision — kube-proxy не точный, статистически близко к ratio replicas, но не exact. Для exact — Service Mesh.
- Service Mesh (Istio) — weight в VirtualService, Envoy sidecar реализует precise split.
- Argo Rollouts / Flagger — CRD-based progressive delivery с automatic analysis и rollback.