Deploy with confidence using canary releases that route a fraction of traffic to new versions. Covers traffic splitting, metrics comparison, automated rollback, progressive delivery controllers, and the patterns that catch regressions before they reach all users.
Canary deployments gradually roll out a new application version to a subset of users or infrastructure before full release. This technique reduces risk during releases by limiting the impact of failures and enabling quick rollback.
To route traffic to a canary deployment, configure your load balancer or ingress controller to split requests between old and new versions. For Kubernetes deployments, update the service selector to include pods running both versions:
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
version: v1
ports:
- port: 80
targetPort: 8080
Use kubectl patch to modify the service selector:
kubectl patch service myapp-service -p '{"spec":{"selector":{"version":"v2"}}}'
The service will now route traffic to pods labeled with version=v2. Update both labels and selectors simultaneously to avoid traffic disruption.
Configure traffic splitting using HTTP headers or query parameters. For example, when using NGINX Ingress Controller, define a custom annotation:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
Set canary-weight to 10 for 10% of traffic. Update the annotation value to adjust split percentage:
kubectl patch ingress myapp-ingress -p '{"metadata":{"annotations":{"nginx.ingress.kubernetes.io/canary-weight":"25"}}}'
Automate progressive traffic shifts using Kubernetes rollout strategies. Create a new deployment with updated image:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-canary
spec:
replicas: 1
selector:
matchLabels:
app: myapp
version: v2
template:
metadata:
labels:
app: myapp
version: v2
spec:
containers:
- name: myapp
image: myapp:v2.0
Apply with kubectl apply -f deployment-canary.yaml. Gradually increase replica count or weight.
Monitor application health using liveness and readiness probes. Add a readiness probe to detect when canary pods are ready:
spec:
template:
spec:
containers:
- name: myapp
image: myapp:v2.0
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
Check pod status with:
kubectl get pods -l version=v2
When a canary deployment fails, rollback using:
kubectl rollout undo deployment/myapp-canary
Implement custom health checks in your application code to signal readiness. Expose an endpoint like /healthz that returns HTTP 200 when service is ready.
Configure the readiness probe to call this endpoint:
readinessProbe:
httpGet:
path: /healthz
port: 8080
If the health check fails, the pod becomes unavailable for traffic. A failed readiness probe does not immediately terminate the pod but prevents it from receiving requests.
Manage traffic distribution using weighted routing. In Kubernetes, use a service selector to target specific versions:
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
version: v2
ports:
- port: 80
Update the selector to shift traffic:
kubectl patch service myapp-service -p '{"spec":{"selector":{"version":"v1"}}}'
Progressively increase traffic to canary deployments. Start with 5% and move to 25%, then 50%, and finally 100%.
Use kubectl scale to modify replica counts:
kubectl scale deployment/myapp-canary --replicas=3
Each increase should be followed by health checks.
Store rollout parameters in a configuration file or secret. Example configuration for traffic split:
apiVersion: v1
kind: ConfigMap
metadata:
name: canary-config
data:
traffic-weight: "10"
timeout-seconds: "300"
Mount the config map into pods:
spec:
containers:
- name: myapp
image: myapp:v2.0
volumeMounts:
- name: config-volume
mountPath: /etc/config
When issues occur, rollback to previous version using:
kubectl rollout undo deployment/myapp-canary
Check deployment status with:
kubectl rollout status deployment/myapp-canary
Ensure all replicas are running before proceeding.
Start a new deployment by applying updated manifests:
kubectl apply -f deployment-canary.yaml
Monitor progress with:
kubectl get deployments
kubectl get pods
When ready, shift traffic gradually. Complete the rollout by updating service selectors or annotations.
If a canary pod fails health checks, it will not receive traffic. Monitor logs with:
kubectl logs -l version=v2
Check for common issues like missing environment variables, database connection failures, or misconfigured readiness probes.
Use consistent version labeling to distinguish between production and canary deployments. For example:
version: v1version: v2-canaryThis allows filtering and targeting specific versions.
Update traffic routing with direct service modifications:
kubectl patch service myapp-service -p '{"spec":{"selector":{"version":"v2"}}}'
Adjust weight configuration:
kubectl patch ingress myapp-ingress -p '{"metadata":{"annotations":{"nginx.ingress.kubernetes.io/canary-weight":"50"}}}'
Monitor key metrics during canary deployment:
Use kubectl top pods to check resource usage.
Validate that traffic is properly routed by testing specific endpoints. For example, send requests to /healthz and verify responses from expected versions.
Monitor service logs to ensure proper routing:
kubectl logs -l app=myapp -l version=v2
Implement multiple traffic split strategies:
Each pattern requires different configuration in the ingress or service layer.
If a rollout fails, revert immediately using:
kubectl rollout undo deployment/myapp-canary
Ensure rollback preserves all previous configuration and data.
Remove canary resources after successful rollout:
kubectl delete deployment myapp-canary
kubectl delete service myapp-canary-service
Verify cleanup with:
kubectl get deployments
kubectl get services
A mismatch between service selector and pod labels prevents traffic routing. Verify selectors match labels:
kubectl get pods -l version=v2 -o wide
kubectl get svc myapp-service -o yaml
An incorrect readiness probe causes pods to appear healthy before they're ready, leading to traffic routing issues.
Inconsistent labeling prevents proper targeting of specific deployment versions.
Without proper health checks, failed canary deployments may continue receiving traffic.
Use multiple service selectors for complex routing:
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
version: v2
ports:
- port: 80
Update multiple labels simultaneously to maintain consistency.
Gradually increase traffic using a step-by-step approach:
Each step requires verification of health metrics and application behavior.
Verify deployment completion with:
kubectl rollout status deployment/myapp-canary
kubectl get pods -l version=v2
Check service configuration matches expected routing rules.
Validate configuration files before applying:
kubectl apply --dry-run=client -f deployment-canary.yaml
This prevents accidental misconfiguration during deployment.
Use standard tools for canary testing:
kubectl for deployment managementNo vendor-specific testing frameworks are required.
This page was rewritten on 15 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy