Kubernetes is a container orchestrator that automates the process of deploying and scaling containerized applications. It allows you to operate production apps with high availability, fault tolerance, and advanced rollout deployment strategies that help mitigate the effects of errors.
This article explores the benefits of blue-green deployments and discusses three key ways to implement them in Kubernetes. Let’s get started!
What we will cover:
TL;DR
- Blue-green deployment in Kubernetes runs two versions at once: blue serves production traffic while green is tested in isolation, then promotion switches all traffic to green in one step.
- Three ways to implement it: a Kubernetes Service selector by hand, Argo Rollouts with
strategy.blueGreen, or Flagger with a Canary resource set toiterations. - No service mesh or ingress controller is required. A Layer 7 traffic manager is only needed for canary releases and A/B testing.
- Argo Rollouts sets
autoPromotionEnabledto true by default, so omitting it promotes green with no window to test. Set it tofalse. - Blue-green gives you an application rollback, not a database rollback, so schema changes need backward-compatible expand-and-contract migrations.
What is blue-green deployment in Kubernetes?
Blue-green deployment is a popular deployment strategy in Kubernetes that runs two versions of your app side-by-side, with traffic directed to the old release until you promote the new one. It improves the operational resilience of your Kubernetes workloads, allowing developers to safely test the new deployment in your production cluster without immediately exposing the changes to users.
How do blue-green deployments work?
Blue-green deployments work by maintaining two production environments: blue (live) and green (idle or staging), and switching traffic between them to release changes with minimal downtime and risk.
In practice, the current version of the application runs in the blue environment. When a new version is ready, it is deployed to the green environment, which is tested in isolation. Once validated, you switch traffic from blue to green. In Kubernetes this normally means changing a Service selector or an Ingress backend rather than a DNS record, so the cutover takes effect in seconds instead of waiting out DNS TTLs on every client.
Green deployments are accessible to your developers and QA team, allowing changes to be tested and verified. Once the tests are complete and you’re satisfied no faults will be introduced, you can promote the green deployment. Promotion replaces the old blue deployment and resets the cycle, ready for the next release.

To summarize the blue-green deployment in Kubernetes:
- The blue environment is launched and serves all production traffic.
- Deploying an update leaves the blue deployment untouched but creates an additional Green environment that runs the new code.
- Tests are executed against the green deployment to detect bugs and regressions in a production-like environment.
- The green deployment is promoted, becoming the new blue deployment that serves production traffic.
Using blue-green deployments allows you to improve the safety and reliability of a critical production environment that can’t tolerate faults. If an error is detected in the green environment, then you can roll back or prepare another update without negatively affecting the user experience.
How to implement a blue-green deployment in Kubernetes?
Kubernetes provides a convenient platform for implementing blue-green deployments. Its service-based networking model lets you route incoming traffic between different deployments, such as your blue and green releases, or you can use popular ecosystem tools to declaratively configure your rollout strategy and benefit from automated management.
Three of the main ways to run blue-green deployments in your cluster include:
- Manually, using a Kubernetes Service selector
- Using Argo Rollouts
- Using Flagger
Manual blue-green deployments using a Kubernetes Service
It’s straightforward to set up blue-green Kubernetes deployment yourself by changing the destination of the service that serves your production traffic. With this strategy, each new release is assigned a unique label; once it’s ready to be promoted to a production environment, the service is updated, so it selects pods with that label.
1. Create the blue deployment
First, create a deployment for the blue release – this is the deployment that will initially serve your users:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-app-blue
spec:
replicas: 3
selector:
matchLabels:
app: demo-app
release: v1
template:
metadata:
labels:
app: demo-app
release: v1
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5Use Kubectl to create the deployment in your cluster:
$ kubectl apply -f deployment-blue.yaml
deployment.apps/demo-app-blue createdThe readiness probe is what makes the promotion in step 6 safe. A Service routes only to Pods that pass it, so without a probe Kubernetes adds a Pod to the Service the moment its container starts, even if the application inside is still booting. In a blue-green deployment that means promoting green can send production traffic to Pods that are not yet serving.
2. Create the blue service
Next, write the manifest for the service that routes the traffic to your deployment:
apiVersion: v1
kind: Service
metadata:
name: demo-app
spec:
selector:
app: demo-app
release: v1
ports:
- protocol: TCP
port: 80
targetPort: 80The service selects pods with the release: v1 label that we assigned to the blue deployment above.
Add the Service to your cluster:
$ kubectl apply -f service.yaml
service/demo-app createdNow, your users can reach your live deployment by connecting to the service on port 80.
3. Create the green deployment
Because the green deployment is kept completely separate from the blue one, you can configure it in whichever way you require for the new version of your application.
In this example, we’re simply changing the container image that will be deployed, but you may also require other changes when you make more substantial updates to your app. The release label must also be updated to distinguish the new green deployment from the existing blue one.
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-app-green
spec:
replicas: 3
selector:
matchLabels:
app: demo-app
release: v2
template:
metadata:
labels:
app: demo-app
release: v2
spec:
containers:
- name: nginx
image: httpd:alpine
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5Create the deployment now:
$ kubectl apply -f deployment-green.yaml
deployment.apps/demo-app-green created4. Create the preview service
Your developers and QA team need a way to reach green without going through the production service. Give green its own service:
apiVersion: v1
kind: Service
metadata:
name: demo-app-preview
spec:
selector:
app: demo-app
release: v2
ports:
- protocol: TCP
port: 80
targetPort: 80$ kubectl apply -f service-preview.yaml
service/demo-app-preview created5. Test your deployments
You can now test your deployments to see your blue and green releases in action. For the purposes of this tutorial, you can use Kubectl port-forwarding to connect.
First, try interacting with the service you created—this routes traffic to your blue deployment and should be exposed to your production traffic. The following command will make the service accessible on localhost:8080:
$ kubectl port-forward svc/demo-app 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80Visiting localhost:8080 in your browser should display the default NGINX landing page because the blue deployment is configured with the nginx container image.

Next, try your green deployment through the preview service you created in step 4:
$ kubectl port-forward svc/demo-app-preview 8081:80
Forwarding from 127.0.0.1:8081 -> 80
Forwarding from [::1]:8081 -> 80You’ll find the default Apache “it works” page is now served at localhost:8081, proving the changes made in the green deployment have been effective:

6. Promote your green deployment
Now, you’re ready to promote your green deployment so it becomes blue. To do this, you can simply modify your service’s manifest, so it selects pods labeled release: v2 instead of the original release: v1:
apiVersion: v1
kind: Service
metadata:
name: demo-app
spec:
selector:
app: demo-app
release: v2
ports:
- protocol: TCP
port: 80
targetPort: 80Use Kubectl to apply the changes to the service:
$ kubectl apply -f service.yaml
service/demo-app configuredConnecting to the service will now display the Apache page instead of the NGINX one. The service is directing its traffic to the second deployment, which runs Apache and not NGINX.

Rolling back is the same command with the old label:
$ kubectl patch service demo-app -p '{"spec":{"selector":{"release":"v1"}}}'Keep the blue deployment running until you are confident in green. The instant rollback only exists while those Pods are still there, so deleting blue right after promotion gives up the main advantage of the strategy. Once you are satisfied, delete the blue deployment and start a new cycle.
Changing a selector moves new connections, not existing ones. Long-lived connections such as WebSockets or gRPC streams stay pinned to blue until the client reconnects or the Pod terminates. Set `terminationGracePeriodSeconds` on the blue Pods to give those connections time to drain.
Note: As the steps in this tutorial show, your releases don’t have to be named “blue” and “green.” It’s often simpler to use incrementing version numbers for each release. The blue-green deployment workflow simply refers to there being two active deployments at each time, only one of which is exposed to users, with support for zero-downtime switches between them.
Blue-green deployments with Argo Rollouts
Managing Deployment objects and Service selectors by hand gets fragile once you are running more than a couple of apps. Argo Rollouts replaces the Deployment object with a Rollout, a custom resource that runs the blue-green sequence for you: it creates the new ReplicaSet, points the preview Service at it, waits for your approval, then switches the active Service.
Once you have installed Argo Rollouts, you create a Rollout object to set up your deployments. Argo Rollouts creates and manages the ReplicaSets, but it does not create your Services. You create the active and preview Services yourself, in the same namespace as the Rollout, and the controller rewrites their selectors by injecting the ReplicaSet’s pod template hash. That is how a Service moves from blue to green without you touching it.
apiVersion: v1
kind: Service
metadata:
name: demo-app-active
spec:
selector:
app: demo-app
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: demo-app-preview
spec:
selector:
app: demo-app
ports:
- protocol: TCP
port: 80
targetPort: 80A basic blue-green Rollout manifest resembles the following:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: demo-app
spec:
replicas: 3
selector:
matchLabels:
app: demo-app
template:
metadata:
labels:
app: demo-app
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
strategy:
blueGreen:
activeService: demo-app-active
previewService: demo-app-preview
# Defaults to true. Left unset, Argo promotes green as soon as its
# ReplicaSet is available, leaving you no window to test.
autoPromotionEnabled: false
# How long the old ReplicaSet stays up after the switch. Default is 30.
scaleDownDelaySeconds: 30You create new releases by changing the Pod template at spec.template, exactly as you would with a Deployment. Argo Rollouts creates a new ReplicaSet, repoints demo-app-preview at it, and pauses. Test against the preview service, then promote with the kubectl plugin:
$ kubectl argo rollouts promote demo-appThe active service switches to the new ReplicaSet. If a problem shows up after the switch, abort and traffic goes back to the previous stable ReplicaSet:
$ kubectl argo rollouts abort demo-appBlue-green deployments with Flux CD and Flagger
Flagger is the other main option. It is a CNCF graduated project and part of the Flux family of GitOps tools, but it installs from its own Helm chart and does not require Flux CD to run.
Blue-green is the one Flagger strategy that needs no extra networking. Canary releases and A/B testing require a Layer 7 traffic manager, either a service mesh or an ingress controller, but the Flagger docs state that for blue/green deployments no service mesh or ingress controller is required. Flagger drives the cutover with Kubernetes L4 networking using provider: kubernetes. A mesh is optional here, and with Istio it unlocks blue/green mirroring, which copies each incoming request to both versions so you can compare them under real traffic.
Flagger has three custom resources, all on flagger.app/v1beta1. Canary defines the target workload, the rollout strategy, and the promotion criteria. MetricTemplate defines custom metric queries against Prometheus, Datadog, CloudWatch, and others. AlertProvider defines where notifications go. Despite the name, Canary is the resource you use for blue-green: you switch the analysis from traffic weights to iterations.
What Flagger needs
Flagger requires a Kubernetes cluster on v1.16 or newer, plus Prometheus for the metric analysis. Install both together:
$ helm repo add flagger https://flagger.app
$ helm upgrade -i flagger flagger/flagger \
--namespace flagger \
--set prometheus.install=true \
--set meshProvider=kubernetesIf you already run Prometheus, point Flagger at it instead with --set metricsServer=http://prometheus.monitoring:9090.
Configuring a blue-green Canary
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: demo-app
namespace: test
spec:
provider: kubernetes
targetRef:
apiVersion: apps/v1
kind: Deployment
name: demo-app
autoscalerRef:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
name: demo-app
progressDeadlineSeconds: 60
service:
port: 80
analysis:
interval: 30s
threshold: 2
# iterations, rather than stepWeight, is what puts Flagger in blue-green mode
iterations: 10
metrics:
- name: request-success-rate
thresholdRange:
min: 99
interval: 1mThe iterations field is the switch. Replacing stepWeight and `maxWeight` with iterations tells Flagger to validate green over a fixed number of intervals and then cut over, instead of shifting traffic gradually.
Flagger’s own tutorial still shows autoscaling/v2beta2 for the HPA reference. Kubernetes stopped serving that API version in v1.26, so use autoscaling/v2, which has been available since v1.23.
What Flagger creates, and how it promotes
On bootstrap, Flagger creates three ClusterIP services (demo-app, demo-app-primary, and demo-app-canary) plus a demo-app-primary deployment holding the blue version. Your original deployment becomes the green side. Conformance tests must target demo-app-canary to reach green. Promotion works differently from the other two approaches. Flagger does not flip a selector.
Once the analysis passes, it copies the green Pod spec onto the primary deployment and triggers a rolling update of primary, routing traffic to green in the meantime so the transition stays smooth. The end state is that primary runs the new version and green scales to zero.
So Flagger gives you gated, metrics-driven promotion, but the final step is a rolling update rather than an instant cutover. If the analysis fails more times than threshold allows, green is scaled to zero and the rollout is marked failed. No traffic ever moves.
What are the advantages of blue-green deployments?
Blue-green deployments trade resource cost for two things that are hard to get any other way: a real test against production infrastructure before any user is exposed, and a rollback measured in seconds.
| Blue-green deployments advantages | |
| Safe production tests | You can test new deployments in production to ensure infrastructure compatibility and detect environment-specific bugs without impacting any users. |
| Immediate rollbacks on failure | If faults do occur, you can immediately roll back, investigate, and prepare a new update without risk of customer disruption. |
| Zero-downtime promotion | Once green is verified, switching production traffic takes seconds. The exception is AWS ALB Ingress, which cannot do this without risking downtime. See the note in the Argo Rollouts section. |
| Combined ease of deployment and reliability | Blue-green deployments provide the flexibility to rapidly move software toward production without actually rushing unproven updates straight through to users. |
These advantages mean blue-green deployments are an ideal strategy for teams that want to continually deliver to production but can’t accept the risk that releases may fail in ways not detected during development.
What are the disadvantages of blue-green deployments?
Despite their compelling strengths, blue-green deployments have some drawbacks:
Running two full versions at once roughly doubles resource usage for the length of the rollout. That number is not fixed, though: Argo Rollouts’ previewReplicaCount lets you test green at reduced scale, and scaleDownDelaySeconds controls how long you pay for both ReplicaSets after the switch.
| Blue-green deployments disadvantages | |
| All or nothing | With blue-green deployments, real users only ever interact with one version of your app. You can’t expose access to a new release to a subset of users, so some problems could still go unnoticed. |
| Shared state limits your rollback | Blue and green talk to the same database, so a rollback only works if the old version can still read the new schema. The usual approach is expand and contract: ship an additive, backward-compatible migration first, promote the app, then remove the old columns in a later release once you are sure you will not roll back. Blue-green gives you an application rollback, not a database rollback. |
| Long-lived connections do not move | Switching a selector redirects new connections only. WebSocket and gRPC streams stay on blue until the client reconnects or the Pod terminates, so set terminationGracePeriodSeconds to let them drain. |
Even with these limitations, blue-green deployments remain a favorable deployment technique for many kinds of apps. However, they’re generally the easiest to configure and most cost-efficient when used with relatively simple systems that have no complex infrastructure requirements.
What are the alternatives to blue-green deployments?
Blue-green deployments aren’t the only advanced rollout strategy available for your Kubernetes workloads. You can also choose from alternatives including:
- Canary deployments: A small proportion of traffic is directed to the new deployment, increasing over time if no failures are detected. This enables automated progressive delivery with a high degree of safety.
- A/B deployments: Commonly used to test the performance of different feature variations, A/B deployments allow you to direct different user groups to specific deployment revisions.
- Best-effort controlled rollout: A rolling update with
maxUnavailableset, so the rollout moves as fast as it can while guaranteeing a minimum number of replicas stay available. This is industry shorthand rather than an official Kubernetes strategy name. The Deployment object itself supports onlyRollingUpdateandRecreate. - Rolling update: App replicas are gradually replaced with ones that run the new rolling deployment, requiring no downtime — this is the default strategy used by the Kubernetes Deployment object.
The technique to use depends on your requirements for rollout speed, reliability, and traffic weighting. Blue-green deployment is the best option when safety is your top priority: New releases are initially inaccessible to users, unlike the other options on this list.
Kubernetes + Spacelift
If you need any assistance with managing your Kubernetes projects, take a look at Spacelift. It brings with it a GitOps flow, so your Kubernetes Deployments are synced with your Kubernetes Stacks, and pull requests show you a preview of what they’re planning to change.
To take this one step further, you could add custom policies to harden the security and reliability of your configurations and deployments. Spacelift provides different types of policies and workflows easily customizable to fit every use case. For instance, you could add plan policies to restrict or warn about security or compliance violations or approval policies to add an approval step during deployments.
You can try it for free by creating a trial account or booking a demo with one of our engineers.
Key points
We’ve explored the blue-green deployment strategy, a popular approach to launching app updates that run two versions side-by-side as two identical production environments. The blue deployment serves production traffic, while the fresh green deployment is used by your developers to complete reliability tests. This provides a final opportunity to detect bugs before users encounter them.
Kubernetes gives you blue-green almost for free, because a Service selector is already an indirection layer between your users and your Pods. Changing one label is the entire cutover. You can implement blue-green deployment yourself by configuring Kubernetes services, or you can use dedicated controllers like Argo Rollouts and Flagger to simplify your experience.
Manage Kubernetes better with Spacelift
Spacelift is an infrastructure orchestration platform built for IaC. It brings collaboration, automation, and governance into a single workflow, so your team can provision cloud infrastructure faster without losing control.
