Kubernetes Using Kubernetes Deployments for Stateless Workloads Created: 25 Jul 2026 Updated: 25 Jul 2026

Kubernetes Blue/Green Deployments

A Blue/Green deployment is a release strategy in which you run two identical production environments — called Blue and Green. At any moment, only one environment receives live traffic. When you are ready to release a new version, you deploy it to the idle environment, verify that everything works, and then switch all traffic at once by updating the Kubernetes Service selector.

The key advantage of Blue/Green is instant rollback. If the new version has a problem, you simply switch the Service selector back to the old environment — no waiting for Pods to reschedule, no partially-rolled-out state, no lost requests. The entire switch takes less than a second.

The trade-off is resource cost: you need double the resources during the transition because both versions run simultaneously. For critical services like a payment API where zero-downtime and instant rollback are non-negotiable, this cost is usually worth it.

Core Concepts

Step 1: How Blue/Green Works — The Big Picture

The strategy uses two Kubernetes Deployments and one Service:

  1. Blue Deployment — Runs the current production version (e.g., v1.0). Receives all live traffic through the Service.
  2. Green Deployment — Runs the new version (e.g., v2.0). Initially receives no traffic.
  3. Service — A ClusterIP or LoadBalancer Service whose selector points to either Blue or Green. Switching traffic is as simple as changing the version label in the selector.

Think of it like a train track switch: traffic is always flowing, you just redirect which track it follows.

Step 2: Label Convention

The whole strategy hinges on labels. You need at least two labels on every Pod:

  1. app: payment-api — Identifies which application the Pod belongs to.
  2. version: blue or version: green — Identifies which environment the Pod belongs to.

The Service selects on both labels. When you want to switch traffic, you update the version value in the Service's selector.

Step 3: The Switch — How Traffic Moves

When you change a Service's selector, Kubernetes immediately recalculates the endpoints. Within seconds, kube-proxy updates the iptables rules (or IPVS rules) on every Node. All new connections go to the new set of Pods. Existing connections to old Pods are not forcefully killed — they complete naturally.

This is why Blue/Green feels instantaneous: you are not waiting for Pods to start or stop. Both sets of Pods are already running and healthy. The only thing that changes is which Pods the Service points to.

Step 4: When to Use Blue/Green

ScenarioBlue/Green?Reason
Critical service that cannot tolerate partial failuresYesInstant rollback protects against bad releases.
Database schema changes that are not backward-compatibleYesYou can test the new version against the new schema before switching traffic.
Many microservices with frequent small releasesMaybe notRolling updates are more resource-efficient for routine releases.
Environments with tight resource budgetsNoRunning double the Pods is expensive.

Step 5: Blue/Green vs Rolling Update

FeatureBlue/GreenRolling Update
Traffic switchInstant (all-at-once)Gradual (pod-by-pod)
Rollback speedInstant (switch selector back)Slower (new rollout needed)
Resource usage during release2x (both versions running)~1x + surge (configurable)
Old and new versions running simultaneouslyYes, but only one gets trafficYes, both get traffic during transition
ComplexityTwo Deployments + manual switchBuilt into Deployment object

Step 6: The Rollback Process

If the Green environment has a bug, rollback is trivial:

  1. Patch the Service selector back to version: blue.
  2. All traffic instantly returns to the Blue (working) Deployment.
  3. Debug the Green Deployment at your leisure — it is still running but receives no traffic.
  4. Once fixed, re-deploy and switch again.

This is dramatically faster than a rolling update rollback, which requires Kubernetes to create new Pods with the old image and wait for them to become ready.

Hands-On: Kubernetes Commands

Apply the Blue Deployment

kubectl apply -f payment-api-blue-deployment.yaml

Apply the Service (Pointing to Blue)

kubectl apply -f payment-api-service.yaml

Verify Blue Is Receiving Traffic

kubectl get endpoints payment-api-service

Deploy the Green Version

kubectl apply -f payment-api-green-deployment.yaml

Verify Green Pods Are Ready (But Not Receiving Traffic)

kubectl get pods -l app=payment-api,version=green

Switch Traffic to Green

kubectl patch service payment-api-service -p '{"spec":{"selector":{"version":"green"}}}'

Verify the Switch

kubectl get endpoints payment-api-service
kubectl describe service payment-api-service

Rollback to Blue (If Needed)

kubectl patch service payment-api-service -p '{"spec":{"selector":{"version":"blue"}}}'

Clean Up the Old Environment

kubectl delete deployment payment-api-blue

Step-by-Step Example

Scenario 1: Initial Blue Deployment

We will deploy a .NET 10 Payment API using the Blue/Green strategy. The Blue environment runs version 1.0 and handles all production traffic.

1. Create the Blue Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-api-blue
labels:
app: payment-api
version: blue
spec:
replicas: 3
selector:
matchLabels:
app: payment-api
version: blue
template:
metadata:
labels:
app: payment-api
version: blue
spec:
containers:
- name: payment-api
image: myregistry.azurecr.io/payment-api:1.0
ports:
- containerPort: 8080
env:
- name: ASPNETCORE_URLS
value: "http://+:8080"
- name: PAYMENT_GATEWAY_URL
value: "https://gateway.internal.svc.cluster.local"
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
readinessProbe:
httpGet:
path: /healthz/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz/live
port: 8080
initialDelaySeconds: 10
periodSeconds: 15

Apply it:

kubectl apply -f payment-api-blue-deployment.yaml

2. Create the Service Pointing to Blue

apiVersion: v1
kind: Service
metadata:
name: payment-api-service
spec:
type: ClusterIP
selector:
app: payment-api
version: blue
ports:
- port: 80
targetPort: 8080

Apply it:

kubectl apply -f payment-api-service.yaml

3. Verify Only Blue Pods Receive Traffic

kubectl get pods -l app=payment-api --show-labels
kubectl get endpoints payment-api-service

The endpoints list should contain only the IP addresses of the three Blue Pods.

Scenario 2: Deploying the Green Version and Switching

A new version (2.0) is ready. We deploy it to the Green environment, validate it, and switch.

4. Create the Green Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-api-green
labels:
app: payment-api
version: green
spec:
replicas: 3
selector:
matchLabels:
app: payment-api
version: green
template:
metadata:
labels:
app: payment-api
version: green
spec:
containers:
- name: payment-api
image: myregistry.azurecr.io/payment-api:2.0
ports:
- containerPort: 8080
env:
- name: ASPNETCORE_URLS
value: "http://+:8080"
- name: PAYMENT_GATEWAY_URL
value: "https://gateway.internal.svc.cluster.local"
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
readinessProbe:
httpGet:
path: /healthz/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz/live
port: 8080
initialDelaySeconds: 10
periodSeconds: 15

Apply it:

kubectl apply -f payment-api-green-deployment.yaml

5. Wait for Green Pods to Become Ready

kubectl rollout status deployment/payment-api-green
kubectl get pods -l app=payment-api,version=green

All three Green Pods should show 1/1 Running. They are healthy but receiving no traffic because the Service still points to Blue.

6. Test the Green Environment Internally

Before switching live traffic, test Green using port-forward or a temporary test Pod:

kubectl port-forward deployment/payment-api-green 9090:8080

In another terminal:

curl http://localhost:9090/healthz/ready

If the health check passes and your smoke tests succeed, proceed to the switch.

7. Switch Traffic from Blue to Green

kubectl patch service payment-api-service -p '{"spec":{"selector":{"version":"green"}}}'

Verify the switch:

kubectl describe service payment-api-service | Select-String "Selector"
kubectl get endpoints payment-api-service

The endpoints now list the Green Pod IPs. All new requests go to version 2.0. Existing connections to Blue Pods complete normally.

Scenario 3: Emergency Rollback

Imagine monitoring shows errors spiking after the switch. Rolling back is one command:

8. Rollback to Blue

kubectl patch service payment-api-service -p '{"spec":{"selector":{"version":"blue"}}}'

Traffic flows back to the Blue Pods instantly. You can now investigate the Green Deployment without affecting users.

9. Clean Up After Successful Release

Once you are confident the Green version is stable, delete the old Blue Deployment:

kubectl delete deployment payment-api-blue

For the next release, the current Green becomes the new "Blue" (stable), and you deploy the next version as a new "Green."

Summary

  1. Blue/Green runs two identical environments. One is live (Blue), one is idle (Green). You switch traffic by changing the Service selector.
  2. Traffic switches are instant — no waiting for Pods to start or stop. Both sets of Pods are already running and healthy before the switch.
  3. Rollback is equally instant — patch the selector back to the old version.
  4. The trade-off is double resource usage during the transition, since both Deployments run simultaneously.
  5. The strategy relies on a label convention (e.g., version: blue / version: green) and the Service's selector to control traffic routing.
  6. Best for: critical services where instant rollback is more important than resource efficiency — payment systems, authentication services, core APIs.
  7. Always test the idle environment (via port-forward or internal requests) before switching live traffic.


Share this lesson: