Skip to content
Codeloom
CI/CD

CI/CD Deployment Strategies: Blue-Green, Canary, Rolling

Learn the most popular CI/CD deployment strategies including blue-green, canary, and rolling deployments with practical examples and configuration.

·9 min read · By Codeloom
Intermediate 12 min read

What you'll learn

  • Understand blue-green, canary, and rolling deployment patterns
  • Configure each strategy in Kubernetes manifests
  • Choose the right strategy for your application
  • Implement automated rollbacks for failed deployments

Prerequisites

  • Basic Kubernetes knowledge
  • Familiarity with CI/CD pipeline concepts

Deploying new code to production is one of the highest-risk activities in software delivery. A bad deployment can take down your entire application, frustrate users, and cost your business real money. Deployment strategies exist to reduce that risk by controlling how new versions of your application reach users.

In this guide, we will walk through the three most widely used deployment strategies: blue-green, canary, and rolling deployments. You will learn how each one works, when to use it, and how to configure it in a real Kubernetes environment.

Why Deployment Strategies Matter

The simplest deployment approach is to stop the old version and start the new one. This “big bang” method has an obvious problem: downtime. During the switch, your application is unavailable. If the new version has a bug, every single user is affected immediately.

Modern deployment strategies solve these problems by introducing the new version gradually, keeping the old version available as a fallback, or both. The right strategy depends on your application’s architecture, your tolerance for risk, and how quickly you need to roll back if something goes wrong.

Blue-Green Deployments

Blue-green deployment maintains two identical production environments. One environment (blue) serves live traffic while the other (green) sits idle or runs the new version. When you are ready to deploy, you switch traffic from blue to green.

How It Works

  1. The blue environment runs the current production version.
  2. You deploy the new version to the green environment.
  3. You run smoke tests and health checks against green.
  4. You switch the load balancer or router to point at green.
  5. Green is now live. Blue becomes idle and serves as your rollback target.

Kubernetes Configuration

You can implement blue-green deployments in Kubernetes using two Deployments and a Service that switches between them:

# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-blue
  labels:
    app: myapp
    version: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: blue
  template:
    metadata:
      labels:
        app: myapp
        version: blue
    spec:
      containers:
        - name: myapp
          image: myapp:1.0.0
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
# green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-green
  labels:
    app: myapp
    version: green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: green
  template:
    metadata:
      labels:
        app: myapp
        version: green
    spec:
      containers:
        - name: myapp
          image: myapp:2.0.0
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
# service.yaml - switch by changing the version selector
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  selector:
    app: myapp
    version: blue  # Change to "green" to switch traffic
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

To switch traffic, update the Service selector:

kubectl patch service myapp-service \
  -p '{"spec":{"selector":{"version":"green"}}}'

To roll back, switch back to blue:

kubectl patch service myapp-service \
  -p '{"spec":{"selector":{"version":"blue"}}}'

When to Use Blue-Green

Blue-green deployments are ideal when you need instant rollback capability and can afford to run double the infrastructure. They work best for stateless applications where both environments can share the same database. Be cautious with database migrations since both versions must be compatible with the current schema during the switch.

Canary Deployments

Canary deployments release the new version to a small subset of users first. If metrics look good, you gradually increase the percentage of traffic going to the new version until it handles 100% of requests.

How It Works

  1. Deploy the new version alongside the current version.
  2. Route a small percentage (for example, 5%) of traffic to the new version.
  3. Monitor error rates, latency, and other key metrics.
  4. Gradually increase traffic to the new version (10%, 25%, 50%, 100%).
  5. If metrics degrade at any step, roll back by sending all traffic to the old version.

Kubernetes Configuration with Nginx Ingress

You can implement canary deployments using Nginx Ingress annotations:

# stable-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-stable
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      track: stable
  template:
    metadata:
      labels:
        app: myapp
        track: stable
    spec:
      containers:
        - name: myapp
          image: myapp:1.0.0
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-stable
spec:
  selector:
    app: myapp
    track: stable
  ports:
    - port: 80
      targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-stable
spec:
  ingressClassName: nginx
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: myapp-stable
                port:
                  number: 80
# canary-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      track: canary
  template:
    metadata:
      labels:
        app: myapp
        track: canary
    spec:
      containers:
        - name: myapp
          image: myapp:2.0.0
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-canary
spec:
  selector:
    app: myapp
    track: canary
  ports:
    - port: 80
      targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-canary
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: myapp-canary
                port:
                  number: 80

Increase canary weight gradually:

# Increase to 25%
kubectl annotate ingress myapp-canary \
  nginx.ingress.kubernetes.io/canary-weight="25" --overwrite

# Increase to 50%
kubectl annotate ingress myapp-canary \
  nginx.ingress.kubernetes.io/canary-weight="50" --overwrite

# Full rollout - promote canary to stable
kubectl set image deployment/myapp-stable myapp=myapp:2.0.0
kubectl delete deployment myapp-canary
kubectl delete service myapp-canary
kubectl delete ingress myapp-canary

When to Use Canary

Canary deployments are the best choice when you need to validate a release with real user traffic before committing to a full rollout. They require good observability since you need metrics to decide whether to proceed or roll back. Canary is especially useful for high-traffic applications where even a small bug can impact thousands of users.

Rolling Deployments

Rolling deployments replace instances of the old version with the new version one at a time. At any point during the rollout, some instances run the old version and others run the new version. This is the default deployment strategy in Kubernetes.

How It Works

  1. Kubernetes starts a new pod with the new version.
  2. Once the new pod passes its readiness probe, an old pod is terminated.
  3. This process repeats until all pods run the new version.
  4. The rollout speed is controlled by maxSurge and maxUnavailable settings.

Kubernetes Configuration

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # At most 1 extra pod during update
      maxUnavailable: 0    # All existing pods stay available
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: myapp:2.0.0
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 15
            periodSeconds: 20
          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "256Mi"
              cpu: "200m"

Monitor and control the rollout:

# Watch the rollout progress
kubectl rollout status deployment/myapp

# Pause if something looks wrong
kubectl rollout pause deployment/myapp

# Resume the rollout
kubectl rollout resume deployment/myapp

# Roll back to the previous version
kubectl rollout undo deployment/myapp

# Roll back to a specific revision
kubectl rollout undo deployment/myapp --to-revision=3

When to Use Rolling

Rolling deployments are the simplest strategy and work well for most applications. They do not require double the infrastructure like blue-green and they are built into Kubernetes natively. The main drawback is that during the rollout, both old and new versions serve traffic simultaneously, so your application must handle version compatibility. Rollback is also slower since Kubernetes needs to perform another rolling update in reverse.

Comparing the Strategies

Here is a quick comparison to help you decide:

FactorBlue-GreenCanaryRolling
Rollback speedInstantFastSlow
Infrastructure cost2x during deploySlightly moreMinimal extra
ComplexityMediumHighLow
Traffic controlAll or nothingFine-grainedAutomatic
Risk exposureFull switchGradualGradual
Zero downtimeYesYesYes

Automating Rollbacks in Your Pipeline

Regardless of which strategy you choose, your CI/CD pipeline should include automated rollback triggers. Here is an example GitHub Actions workflow that checks deployment health and rolls back if needed:

# .github/workflows/deploy.yml
name: Deploy with Health Check
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Kubernetes
        run: |
          kubectl set image deployment/myapp \
            myapp=myapp:${{ github.sha }}

      - name: Wait for rollout
        run: |
          kubectl rollout status deployment/myapp --timeout=300s

      - name: Health check
        id: health
        run: |
          for i in $(seq 1 10); do
            STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://myapp.example.com/health)
            if [ "$STATUS" != "200" ]; then
              echo "Health check failed with status $STATUS"
              echo "healthy=false" >> "$GITHUB_OUTPUT"
              exit 0
            fi
            sleep 5
          done
          echo "healthy=true" >> "$GITHUB_OUTPUT"

      - name: Rollback on failure
        if: steps.health.outputs.healthy == 'false'
        run: |
          echo "Rolling back deployment..."
          kubectl rollout undo deployment/myapp
          kubectl rollout status deployment/myapp --timeout=300s
          exit 1

Wrapping Up

Blue-green deployments give you instant rollback by maintaining two full environments. Canary deployments let you test with real traffic before committing to a full release. Rolling deployments are the simplest option and work well for most teams starting out.

Start with rolling deployments if you are new to Kubernetes. Move to canary when you have good observability in place and need more control over rollouts. Use blue-green when instant rollback is a hard requirement. Whichever strategy you choose, always include health checks and automated rollback in your pipeline.