Kubernetes Deployment Strategies
A comprehensive guide to Kubernetes deployment strategies covering rolling updates, blue-green, canary, A/B testing, feature flags, and progressive delivery with detailed explanations, practical examples, and best practices for zero-downtime deployments.
Deployment strategies define how new versions of applications are rolled out to production. The right strategy ensures zero downtime, reduces risk, enables fast rollbacks, and allows for testing in production. In modern cloud-native environments, deployment strategies are critical for maintaining reliability and user experience.
Kubernetes provides native support for rolling updates and, with additional tools like Argo Rollouts, Istio, and Flagger, enables advanced deployment patterns like canary, blue-green, and A/B testing.
- Zero Downtime: Users should not experience interruptions during deployments
- Risk Reduction: Minimize the blast radius of failed deployments
- Fast Rollback: Ability to quickly revert to previous versions
- Validation: Test new versions with real traffic before full rollout
Rolling Update
Blue-Green
Canary Deployment
A/B Testing
Feature Flags
Shadow Deployment
Kubernetes Deployments use rolling updates by default. This strategy gradually replaces old pods with new ones while ensuring a minimum number of pods remain available.
# Rolling Update Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Max pods above desired count
maxUnavailable: 0 # Max unavailable pods during update
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
version: v2
spec:
containers:
- name: nginx
image: nginx:1.25 # New version
# Update image (triggers rolling update)
kubectl set image deployment/nginx nginx=nginx:1.26
# Check rollout status
kubectl rollout status deployment/nginx
# Pause rollout (for testing)
kubectl rollout pause deployment/nginx
# Resume rollout
kubectl rollout resume deployment/nginx
# Rollback if needed
kubectl rollout undo deployment/nginx
# View rollout history
kubectl rollout history deployment/nginx
- Set
maxSurgeandmaxUnavailablebased on your workload requirements - Use
maxUnavailable: 0for zero-downtime deployments - Implement health checks (readiness probes) to prevent routing traffic to unhealthy pods
- Use
kubectl rollout pausefor manual validation before completing the rollout
Blue-Green deployment uses two identical environments. The "blue" environment is the current production version, and the "green" environment is the new version. After validation, traffic is switched from blue to green in one operation.
# Blue Deployment (current)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-blue
labels:
app: nginx
version: blue
spec:
replicas: 3
selector:
matchLabels:
app: nginx
version: blue
template:
metadata:
labels:
app: nginx
version: blue
spec:
containers:
- name: nginx
image: nginx:1.24
---
# Green Deployment (new)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-green
labels:
app: nginx
version: green
spec:
replicas: 3
selector:
matchLabels:
app: nginx
version: green
template:
metadata:
labels:
app: nginx
version: green
spec:
containers:
- name: nginx
image: nginx:1.25
---
# Service pointing to blue
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
version: blue # Switch to green when ready
ports:
- port: 80
targetPort: 80
# Switch traffic from blue to green
kubectl patch service nginx-service -p '{"spec":{"selector":{"version":"green"}}}'
# After validation, scale down blue
kubectl scale deployment nginx-blue --replicas=0
Canary deployments roll out new versions to a small subset of users first, monitor for issues, and gradually increase traffic. This strategy minimizes the blast radius of failures and enables real-world validation before full rollout.
# Using Argo Rollouts for Canary
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: nginx-canary
spec:
replicas: 5
strategy:
canary:
maxSurge: 1
maxUnavailable: 0
steps:
- setWeight: 10 # Start with 10% traffic
- pause: {duration: 30s}
- setWeight: 25
- pause: {duration: 1m}
- setWeight: 50
- pause: {duration: 2m}
- setWeight: 100 # Full rollout
trafficRouting:
istio:
virtualService:
name: nginx-vs
routes:
- primary
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
---
# Istio VirtualService for canary
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: nginx-vs
spec:
hosts:
- nginx-service
http:
- route:
- destination:
host: nginx-canary-primary
subset: stable
weight: 90
- destination:
host: nginx-canary-canary
subset: canary
weight: 10
---
# Flagger Canary Configuration
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: nginx-canary
spec:
provider: istio
targetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx
progressDeadlineSeconds: 60
service:
port: 80
analysis:
interval: 30s
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
threshold: 99
interval: 1m
- name: request-duration
threshold: 500
interval: 1m
webhooks:
- name: acceptance-test
url: http://flagger-loadtester.test/acceptance
timeout: 5s
- name: load-test
url: http://flagger-loadtester.test/load
timeout: 5s
- Start with very low traffic (1-5%) for high-risk changes
- Monitor key metrics (error rate, latency) during canary phases
- Use automated rollback on metric threshold breaches
- Implement analysis phases with real user traffic
- Use tools like Argo Rollouts, Flagger, or Istio for automation
A/B testing routes users to different versions based on request attributes (headers, cookies, user ID). This enables data-driven feature validation and user experience testing.
# Istio A/B Testing
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: app-ab
spec:
hosts:
- app-service
http:
- match:
- headers:
user-agent:
regex: "^.*Mobile.*$"
route:
- destination:
host: app-service
subset: v2
weight: 100
- match:
- headers:
x-test-group:
exact: "A"
route:
- destination:
host: app-service
subset: v1
weight: 100
- match:
- headers:
x-test-group:
exact: "B"
route:
- destination:
host: app-service
subset: v2
weight: 100
- route:
- destination:
host: app-service
subset: v1
weight: 80
- destination:
host: app-service
subset: v2
weight: 20
---
# DestinationRule for subsets
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: app-dr
spec:
host: app-service
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
# NGINX Ingress A/B Testing
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ab-ingress
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "x-test-group"
nginx.ingress.kubernetes.io/canary-by-header-value: "B"
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-v2
port:
number: 80
- Use consistent hashing (based on user ID or session) to maintain user experience
- Define clear success metrics for each test group
- Monitor both technical metrics (latency, errors) and business metrics (conversion)
- Set a time limit for tests to avoid stale configurations
- Collect and analyze data before making decisions
Feature flags enable you to toggle features on and off without deploying new code. This enables dark launches, gradual rollouts, and instant rollback of features.
# LaunchDarkly Feature Flag Example
# application code
from launchdarkly import LDClient
client = LDClient("sdk-xxx")
# Check feature flag
if client.variation("new-checkout-flow", user, False):
# New checkout flow
show_new_checkout()
else:
# Old checkout flow
show_old_checkout()
# Flagsmith Self-Hosted Feature Flags
apiVersion: v1
kind: ConfigMap
metadata:
name: flagsmith-config
data:
flagsmith.json: |
{
"features": [
{
"name": "new-checkout-flow",
"enabled": false,
"environments": {
"production": false,
"staging": true
},
"segments": [
{
"name": "beta-users",
"condition": "user.email contains @example.com",
"enabled": true
}
]
},
{
"name": "dark-mode",
"enabled": false,
"gradual_rollout": {
"percentage": 10,
"increment": 5,
"schedule": "daily"
}
}
]
}
# Kubernetes ConfigMap for feature flags
apiVersion: v1
kind: ConfigMap
metadata:
name: feature-flags
data:
new-feature-enabled: "false"
beta-feature-enabled: "true"
maintenance-mode: "false"
# Use in pod
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: myapp:latest
env:
- name: NEW_FEATURE_ENABLED
valueFrom:
configMapKeyRef:
name: feature-flags
key: new-feature-enabled
- Use feature flag management tools (LaunchDarkly, Flagsmith, Split)
- Implement a clean-up process for old feature flags
- Monitor performance impact of feature flag evaluation
- Use feature flags for dark launches (release to internal users first)
- Combine with canary deployment for progressive delivery
| Strategy | Zero Downtime | Risk Level | Rollback Speed | Infrastructure Cost | Complexity |
|---|---|---|---|---|---|
| Rolling Update | Yes | Medium | Medium | Low | Low |
| Blue-Green | Yes | Low | Instant | High (2x) | Medium |
| Canary | Yes | Very Low | Fast | Low-Medium | High |
| A/B Testing | Yes | Low | Fast | Low-Medium | High |
| Feature Flags | Yes | Very Low | Instant | Low | Medium |
| Shadow | Yes | Very Low | N/A | High (2x) | High |
Progressive Delivery is the evolution of continuous delivery that combines multiple strategies (canary, A/B testing, feature flags) with automated analysis to gradually roll out changes with minimal risk.
Automated Analysis
Observability Integration
Automated Rollback
# Flagger Progressive Delivery
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: app-canary
namespace: production
spec:
provider: istio
targetRef:
apiVersion: apps/v1
kind: Deployment
name: app
progressDeadlineSeconds: 60
service:
port: 80
targetPort: 8080
analysis:
interval: 30s
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
thresholdRange:
min: 99
interval: 1m
- name: request-duration
thresholdRange:
max: 500
interval: 1m
webhooks:
- name: acceptance-test
url: http://flagger-loadtester.test/acceptance
timeout: 5s
- name: load-test
url: http://flagger-loadtester.test/load
timeout: 5s
rollback:
retries: 3
wait: 30s
Choosing the right deployment strategy is critical for maintaining reliability and reducing risk. Start with rolling updates, then adopt canary and progressive delivery as your maturity grows.