Back to Blog
DevOps

Kubernetes Deployment Strategies: Rolling, Canary, and Blue-Green

February 2, 202613 min read

Zero downtime is non-negotiable. Compare rolling updates, canary releases, and blue-green deployments in Kubernetes — with real YAML manifests and decision criteria for each.

Kubernetes Deployment Strategies: Rolling, Canary, and Blue-Green

Introduction

Deploying to production is the moment of maximum risk. The wrong strategy can mean downtime, degraded performance, or a frantic rollback at 2am. Kubernetes gives you three primary deployment strategies, each with different risk profiles, rollback speeds, and resource costs.


Strategy 1: Rolling Update (Default)

Gradually replaces old pods with new ones. Zero downtime. Low resource overhead.

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
spec:
  replicas: 6
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2        # At most 8 pods running during update
      maxUnavailable: 1  # At most 1 pod unavailable at any time
  selector:
    matchLabels:
      app: api-server
  template:
    metadata:
      labels:
        app: api-server
    spec:
      containers:
        - name: api
          image: ghcr.io/myorg/api:v2.1.0
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 5
            failureThreshold: 3
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 30
            periodSeconds: 10

The readinessProbe is critical — Kubernetes won't route traffic to new pods until they pass, preventing downtime from slow-starting containers.

Rollback:

kubectl rollout undo deployment/api-server
kubectl rollout status deployment/api-server

Strategy 2: Blue-Green Deployment

Run two identical environments — blue (current) and green (new). Switch traffic instantly.

# Blue deployment (currently serving traffic)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-blue
spec:
  replicas: 4
  selector:
    matchLabels:
      app: api
      version: blue
  template:
    metadata:
      labels:
        app: api
        version: blue
    spec:
      containers:
        - name: api
          image: ghcr.io/myorg/api:v1.9.0
---
# Green deployment (new version, not yet live)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-green
spec:
  replicas: 4
  selector:
    matchLabels:
      app: api
      version: green
  template:
    metadata:
      labels:
        app: api
        version: green
    spec:
      containers:
        - name: api
          image: ghcr.io/myorg/api:v2.0.0
---
# Service — switch version label to flip traffic
apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  selector:
    app: api
    version: blue  # Change to 'green' to flip
  ports:
    - port: 80
      targetPort: 3000
# Run smoke tests on green
kubectl port-forward deployment/api-green 3000:3000

# Flip traffic (instant, zero downtime)
kubectl patch service api-service -p '{"spec":{"selector":{"version":"green"}}}'

# If something goes wrong — instant rollback (seconds, not minutes)
kubectl patch service api-service -p '{"spec":{"selector":{"version":"blue"}}}'

Cost: Double the resources while both environments run.


Strategy 3: Canary Release

Send a small percentage of real traffic to the new version. Observe metrics. Gradually increase.

# Stable deployment: 9 pods = ~90% of traffic
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-stable
spec:
  replicas: 9
  template:
    metadata:
      labels:
        app: api
        track: stable
    spec:
      containers:
        - name: api
          image: ghcr.io/myorg/api:v1.9.0
---
# Canary deployment: 1 pod = ~10% of traffic
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-canary
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: api
        track: canary
    spec:
      containers:
        - name: api
          image: ghcr.io/myorg/api:v2.0.0
---
# Single service routes to both — traffic split is proportional to replica count
apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  selector:
    app: api  # Matches both stable and canary pods

With Argo Rollouts you can automate the canary progression based on Prometheus metrics:

apiVersion: argoproj.io/v1alpha1
kind: Rollout
spec:
  strategy:
    canary:
      steps:
        - setWeight: 10
        - pause: { duration: 10m }  # Observe metrics
        - setWeight: 30
        - pause: { duration: 10m }
        - setWeight: 60
        - pause: { duration: 10m }
        - setWeight: 100
      analysis:
        templates:
          - templateName: error-rate
        args:
          - name: service-name
            value: api-service

Decision Matrix

StrategyRiskRollback SpeedResource CostBest For
RollingMedium~5 min1xMost deployments
Blue-GreenLowInstant2xBreaking changes, DB migrations
CanaryVery LowInstant1.1xHigh-traffic, risky changes

Conclusion

Use rolling updates for routine deployments, blue-green when you have database migrations or breaking API changes, and canary when you want real-traffic validation before full rollout. The readinessProbe is the single most important thing to get right — without it, all three strategies can cause downtime.

Tags

KubernetesDevOpsDeploymentCI/CDCanaryBlue-Green