Blue-Green and Canary Deployment for Enterprise CI/CD Platforms
Prerequisites
- Working knowledge of Kubernetes and containerized applications
- Familiarity with CI/CD pipelines, ingress controllers, and observability metrics
Steps
Blue-green and canary deployment reduce release risk by shifting traffic between isolated application versions with fast rollback paths. This guide explains architecture, implementation, security controls, and operational trade-offs for enterprise practitioners.
Overview
Blue-green and canary deployment are progressive delivery patterns used to release application changes with lower operational risk. In blue-green deployment, two production environments run side by side: blue serves live traffic while green hosts the new release, and traffic is switched only after validation. In canary deployment, a small percentage of users is routed to the new version first, then gradually increased as health and business metrics remain within thresholds.
Enterprises use these models to reduce downtime, improve rollback speed, and validate releases under real traffic. They are especially valuable for regulated environments, customer-facing APIs, and microservices running on Kubernetes, service meshes, or cloud load balancers.
Architecture
Core components typically include:
- CI pipeline to build, test, sign, and publish artifacts
- CD controller such as Argo Rollouts, Flagger, or Spinnaker
- Traffic manager such as NGINX Ingress, AWS ALB, or Istio
- Observability stack with Prometheus, Grafana, ELK, and tracing
- Artifact registry such as ECR, ACR, or Harbor
- Secrets manager such as HashiCorp Vault or AWS Secrets Manager
Deployment models
- Blue-green: two identical stacks behind a load balancer; cutover is immediate or weighted
- Canary: one stable version and one canary version with incremental traffic weights such as 5%, 20%, 50%, 100%
- Hybrid: canary validation followed by full blue-green switch for stateful or highly regulated workloads
Data flow
- Developer merges code to
main. - CI builds container image, runs tests, signs artifact, and pushes to registry.
- CD updates Kubernetes manifests or Helm values.
- Traffic controller routes requests to stable and candidate versions.
- Metrics and logs are evaluated automatically.
- Rollout proceeds or rolls back based on SLOs.
Implementation Guide
The example below uses Kubernetes, Argo Rollouts, and NGINX Ingress.
- Install Argo Rollouts:
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
kubectl argo rollouts version
- Deploy the application and rollout object:
kubectl apply -f rollout.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
- Watch rollout progress:
kubectl argo rollouts get rollout payments -n prod --watch
- Promote a paused canary manually if needed:
kubectl argo rollouts promote payments -n prod
- Abort and rollback on failure:
kubectl argo rollouts abort payments -n prod
kubectl argo rollouts undo payments -n prod
- Validate traffic split and pod health:
kubectl get pods -n prod -l app=payments -o wide
kubectl describe rollout payments -n prod
curl -I https://api.example.com/healthz
For blue-green, define active and preview services, run smoke tests against preview, then promote:
kubectl argo rollouts promote payments -n prod
kubectl get svc -n prod
Code Examples
1. Bash deployment validation
#!/usr/bin/env bash
set -euo pipefail
NS=prod
APP=payments
kubectl argo rollouts get rollout "$APP" -n "$NS"
kubectl wait --for=condition=available deployment/${APP}-stable -n "$NS" --timeout=120s
curl -fsS https://api.example.com/healthz | jq .status
2. Argo Rollouts canary manifest
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: payments
namespace: prod
spec:
replicas: 6
strategy:
canary:
canaryService: payments-canary
stableService: payments-stable
steps:
- setWeight: 10
- pause: {duration: 120}
- setWeight: 25
- pause: {duration: 300}
- setWeight: 50
- pause: {}
selector:
matchLabels:
app: payments
template:
metadata:
labels:
app: payments
spec:
containers:
- name: payments
image: registry.example.com/payments:2.4.1
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /healthz
port: 8080
3. Python metric gate
import requests
error_rate = requests.get("http://prometheus.monitoring.svc:9090/api/v1/query", params={"query": "sum(rate(http_requests_total{job='payments',status=~'5..'}[5m])) / sum(rate(http_requests_total{job='payments'}[5m]))"}, timeout=5).json()
value = float(error_rate["data"]["result"][0]["value"][1])
if value > 0.02:
raise SystemExit("Canary failed: error rate above 2%")
print("Canary passed")
Security Hardening
- Enforce RBAC so only the CD service account can promote or abort rollouts.
- Use image signing with Cosign and verify signatures in admission control.
- Encrypt secrets at rest with KMS and in transit with mTLS between services.
- Restrict preview or canary endpoints with IP allowlists or identity-aware proxies.
- Enable audit logging for
kubectl argo rollouts promote, ingress changes, and secret access. - Apply network policies so canary pods only reach required dependencies.
- Gate promotion on security scans, SBOM validation, and policy checks with OPA or Kyverno.
Comparison
| Capability | Blue-green / Canary | Argo Rollouts | Spinnaker | AWS CodeDeploy |
|---|---|---|---|---|
| Pricing | Pattern, tooling-dependent | Open source; infra cost only | Open source; higher ops overhead | Pay for underlying AWS resources |
| Deployment | Kubernetes-native weighted, pause, abort, promote | Strong for K8s progressive delivery | Broad multi-cloud pipelines | Strong for EC2, ECS, Lambda |
| Scalability | High with service mesh or ingress weighting | High for K8s clusters | High but operationally complex | High within AWS-managed ecosystems |
| Security | Depends on RBAC, secrets, policy controls | Integrates with K8s RBAC and policy engines | Mature approvals and pipeline controls | Tight IAM integration and AWS auditability |
Troubleshooting
Error 1: Canary never becomes ready
Log sample:
Warning Unhealthy 42s (x8 over 2m) kubelet Readiness probe failed: Get "http://10.42.3.17:8080/healthz": dial tcp 10.42.3.17:8080: connect: connection refused
Fix: verify container port, startup time, and readiness path; add startupProbe for slow boot applications.
Error 2: Rollout degraded after traffic shift
Log sample:
time="2026-08-16T10:14:22Z" level=error msg="AnalysisRun failed: metric error-rate assessed Failed, consecutiveError limit exceeded"
Fix: inspect Prometheus query, compare stable vs canary latency and 5xx rates, then abort rollout and review recent code or dependency changes.
Error 3: Ingress weight not applied
Log sample:
I0816 10:18:07.114321 7 controller.go:1338] Service "prod/payments-canary" does not have any active Endpoint
Fix: ensure canary pods are labeled correctly, service selectors match, and endpoints exist before increasing traffic weight.
Best Practices
Do
- Use automated rollback when error rate, latency, or saturation breaches SLOs.
- Test schema changes with backward-compatible migrations before traffic switching.
- Keep blue and green environments configuration-identical except for versioned artifacts.
- Route internal staff or synthetic traffic to preview before exposing external users.
Don't
- Do not couple release promotion to manual DNS changes when a load balancer or ingress can switch instantly.
- Do not run canaries without baseline metrics; for example, a 1% traffic slice is useless without request volume and conversion context.
- Do not introduce breaking database changes during the same step as application rollout.
- Do not grant developers cluster-admin just to promote releases; use scoped service accounts and approval workflows.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI