Elke deployment is een risico. De vraag is niet óf er iets fout gaat — maar hoeveel schade het veroorzaakt wanneer het gebeurt.
Traditionele Kubernetes deployments zijn alles-of-niets. Je pusht een nieuwe versie, en binnen seconden raakt 100% van je traffic de nieuwe code. Als er een bug is, ziet iedereen het. Als de service crasht, zijn alle gebruikers getroffen.
Progressive delivery verandert deze vergelijking. In plaats van naar iedereen tegelijk te deployen, verschuif je geleidelijk traffic naar de nieuwe versie, en valideer je bij elke stap. Als er iets misgaat, is slechts een fractie van de gebruikers getroffen.
Argo Rollouts brengt progressive delivery naar Kubernetes als drop-in vervanging voor Deployments.
Waarom Progressive Delivery?
Overweeg wat er gebeurt met een standaard Deployment tijdens een bug release:
Tijd 0:00 - Deploy nieuwe versie
Tijd 0:02 - Alle pods draaien nieuwe versie
Tijd 0:05 - Errors beginnen te verschijnen
Tijd 0:08 - Alerts gaan af
Tijd 0:15 - Engineer onderzoekt
Tijd 0:25 - Rollback gestart
Tijd 0:27 - Alle pods terug naar oude versie
Blast radius: 100% van gebruikers voor ~25 minuten
Met progressive delivery:
Tijd 0:00 - Deploy nieuwe versie (5% traffic)
Tijd 0:05 - Geautomatiseerde analyse detecteert errors
Tijd 0:06 - Automatische rollback
Blast radius: 5% van gebruikers voor ~6 minuten
Dit is resilience. Niet failures voorkomen, maar hun impact beperken.
Twee Strategieën: Canary vs Blue-Green
Argo Rollouts ondersteunt meerdere strategieën. De twee meest voorkomende:
Canary
Traffic verschuift geleidelijk van oude naar nieuwe versie:
Stap 1: 5% nieuw, 95% oud (test the waters)
Stap 2: 20% nieuw, 80% oud (uitbreiden als gezond)
Stap 3: 50% nieuw, 50% oud (halverwege)
Stap 4: 100% nieuw, 0% oud (volledige rollout)
Best voor: Stateless services, high-traffic applicaties waar je geleidelijke validatie wilt.
Blue-Green
Twee complete omgevingen, directe switch:
Voor: 100% blue (oud) 0% green (nieuw)
Deploy: 100% blue green klaar, ontvangt geen traffic
Switch: 0% blue 100% green
Best voor: Services die directe rollback vereisen, database migraties, wanneer je beide versies simultaan wilt draaien voor testen.
Argo Rollouts Installeren
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
Voor GitOps met ArgoCD, voeg het toe als Application:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: argo-rollouts
namespace: argocd
spec:
project: default
source:
repoURL: https://argoproj.github.io/argo-helm
chart: argo-rollouts
targetRevision: 2.35.1
helm:
values: |
dashboard:
enabled: true
destination:
server: https://kubernetes.default.svc
namespace: argo-rollouts
syncPolicy:
automated:
prune: true
selfHeal: true
Canary Rollout Voorbeeld
Vervang je Deployment door een Rollout:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
replicas: 10
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app:v2.0.0
ports:
- containerPort: 8080
strategy:
canary:
steps:
- setWeight: 5
- pause: { duration: 5m }
- setWeight: 20
- pause: { duration: 5m }
- setWeight: 50
- pause: { duration: 5m }
- setWeight: 100
Dit creëert een geleidelijke rollout van 20 minuten:
- Stuur 5% van traffic naar nieuwe versie, wacht 5 minuten
- Als gezond, verhoog naar 20%, wacht 5 minuten
- Als gezond, verhoog naar 50%, wacht 5 minuten
- Voltooi rollout naar 100%
Op elk moment, als je rollback doet, keert traffic direct terug naar de oude versie.
Traffic Management
Standaard gebruikt Argo Rollouts replica count om traffic weight te benaderen. Voor precieze traffic controle, integreer met je ingress:
Met Traefik
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
strategy:
canary:
canaryService: my-app-canary
stableService: my-app-stable
trafficRouting:
traefik:
weightedTraefikServiceName: my-app-weighted
steps:
- setWeight: 10
- pause: { duration: 2m }
- setWeight: 50
- pause: { duration: 2m }
Met ondersteunende TraefikService:
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: my-app-weighted
spec:
weighted:
services:
- name: my-app-stable
port: 80
weight: 100 # Beheerd door Argo Rollouts
- name: my-app-canary
port: 80
weight: 0 # Beheerd door Argo Rollouts
Met Nginx Ingress
apiVersion: argoproj.io/v1alpha1
kind: Rollout
spec:
strategy:
canary:
canaryService: my-app-canary
stableService: my-app-stable
trafficRouting:
nginx:
stableIngress: my-app-ingress
Met Istio
apiVersion: argoproj.io/v1alpha1
kind: Rollout
spec:
strategy:
canary:
trafficRouting:
istio:
virtualService:
name: my-app-vsvc
routes:
- primary
Blue-Green Rollout
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
replicas: 5
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app:v2.0.0
strategy:
blueGreen:
activeService: my-app-active
previewService: my-app-preview
autoPromotionEnabled: false
prePromotionAnalysis:
templates:
- templateName: smoke-tests
postPromotionAnalysis:
templates:
- templateName: load-test
Dit creëert:
my-app-active: Wijst naar huidige productie versiemy-app-preview: Wijst naar nieuwe versie voor testen
De nieuwe versie wordt gedeployed maar ontvangt geen productie traffic totdat je promoot.
Geautomatiseerde Analyse
De echte kracht van progressive delivery is geautomatiseerde rollback. Argo Rollouts kan metrics analyseren tijdens rollout en afbreken als er iets misgaat.
Analysis Template
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 1m
successCondition: result[0] >= 0.95
failureLimit: 3
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{service="{{args.service-name}}",status=~"2.."}[5m])) /
sum(rate(http_requests_total{service="{{args.service-name}}"}[5m]))
Deze template:
- Queryt Prometheus elke minuut
- Checkt of success rate >= 95% is
- Faalt de rollout na 3 opeenvolgende failures
Analysis Gebruiken in Rollout
apiVersion: argoproj.io/v1alpha1
kind: Rollout
spec:
strategy:
canary:
steps:
- setWeight: 5
- pause: { duration: 2m }
- analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: my-app
- setWeight: 50
- pause: { duration: 5m }
- analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: my-app
Nu doet de rollout:
- Verschuift 5% traffic
- Wacht 2 minuten
- Draait analyse — als het faalt, automatische rollback
- Als analyse slaagt, verschuift naar 50%
- Draait analyse opnieuw
- Voltooit rollout
Meerdere Analysis Metrics
Combineer meerdere checks:
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: comprehensive-check
spec:
args:
- name: service-name
metrics:
# HTTP success rate
- name: success-rate
interval: 1m
successCondition: result[0] >= 0.95
failureLimit: 3
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{service="{{args.service-name}}",status=~"2.."}[5m])) /
sum(rate(http_requests_total{service="{{args.service-name}}"}[5m]))
# P99 latency
- name: latency-p99
interval: 1m
successCondition: result[0] < 0.5
failureLimit: 3
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service="{{args.service-name}}"}[5m])) by (le))
# Error rate
- name: error-rate
interval: 1m
successCondition: result[0] < 0.01
failureLimit: 2
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{service="{{args.service-name}}",status=~"5.."}[5m])) /
sum(rate(http_requests_total{service="{{args.service-name}}"}[5m]))
Web-Based Job Analyse
Voor niet-Prometheus checks (smoke tests, integratie tests):
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: smoke-test
spec:
metrics:
- name: smoke-test
provider:
job:
spec:
backoffLimit: 1
template:
spec:
containers:
- name: smoke
image: curlimages/curl
command:
- /bin/sh
- -c
- |
curl -f http://my-app-canary/health || exit 1
curl -f http://my-app-canary/api/status || exit 1
restartPolicy: Never
Dashboard en CLI
Monitor rollouts met de Argo Rollouts kubectl plugin:
# Installeer plugin
curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-darwin-amd64
chmod +x kubectl-argo-rollouts-darwin-amd64
mv kubectl-argo-rollouts-darwin-amd64 /usr/local/bin/kubectl-argo-rollouts
# Watch rollout progress
kubectl argo rollouts get rollout my-app -w
# Handmatig promoten (als autoPromotion disabled is)
kubectl argo rollouts promote my-app
# Afbreken en rollback
kubectl argo rollouts abort my-app
# View dashboard
kubectl argo rollouts dashboard
Het dashboard toont real-time traffic distributie en analyse status.
Integratie met GitOps
Bij gebruik van ArgoCD werken Rollouts naadloos. Update de image tag in Git, ArgoCD synct, en de progressive rollout begint.
# In je GitOps repo
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: app
image: my-app:v2.1.0 # Update deze regel
De semantic versioning pipeline maakt de tag, die een update triggert naar de GitOps repo, die ArgoCD synct, die de Rollout start.
Notificaties
Word genotificeerd over rollout events:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
annotations:
notifications.argoproj.io/subscribe.on-rollout-completed.slack: my-channel
notifications.argoproj.io/subscribe.on-rollout-aborted.slack: my-channel
Configureer de notification controller separaat (deelt configuratie met ArgoCD notifications).
Mijn Productie Setup
Hier is mijn daadwerkelijke Rollout configuratie:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: api
spec:
replicas: 5
revisionHistoryLimit: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: registry.example.com/api:v1.0.0
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
strategy:
canary:
canaryService: api-canary
stableService: api-stable
trafficRouting:
traefik:
weightedTraefikServiceName: api-weighted
steps:
# Fase 1: Smoke test
- setWeight: 5
- pause: { duration: 2m }
- analysis:
templates:
- templateName: smoke-test
# Fase 2: Beperkte blootstelling
- setWeight: 25
- pause: { duration: 5m }
- analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: api
# Fase 3: Meerderheid traffic
- setWeight: 75
- pause: { duration: 10m }
- analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: api
# Fase 4: Volledige rollout
- setWeight: 100
rollbackWindow:
revisions: 2
Belangrijke beslissingen:
- Meerdere analyse fases — Vroege smoke test, dan metric-gebaseerde validatie
- Toenemende pause duren — Meer tijd bij hogere traffic percentages
- Rollback window — Kan snel terug naar laatste 2 versies
Wanneer Geen Progressive Delivery
Progressive delivery voegt complexiteit toe. Sla het over wanneer:
- Breaking database schema changes — Je hebt de hele app op één versie nodig
- Single-user applicaties — Geen zinvolle traffic om te splitsen
- Simpele interne tools — De overhead is het niet waard
- Tight coupling tussen services — Wanneer services samen moeten upgraden
Voor de meeste productie services die echte gebruikers bedienen, is progressive delivery de investering waard.
Waarom Dit Ertoe Doet
Elke deployment is een gecontroleerd experiment. Je test de hypothese dat je nieuwe code werkt in productie.
Progressive delivery maakt dat experiment veiliger:
- Kleinere blast radius — Problemen raken minder gebruikers
- Snellere detectie — Geautomatiseerde analyse vangt issues vroeg
- Directe recovery — Één commando keert terug naar bekende-goede staat
Dit is resilience in de praktijk. Niet hopen dat deployments slagen, maar systemen ontwerpen die graceful omgaan met wanneer ze dat niet doen.
De beste deployment strategie is niet degene die nooit faalt — het is degene die schade minimaliseert wanneer failure gebeurt. Progressive delivery beperkt je blast radius en geeft je tijd om te reageren.
