Lab: Advanced Deployment Strategies¶
Duration: 20 minutes
Objectives¶
- Configure safer rolling updates
- Deploy blue and green application versions
- Switch production traffic with a Service selector
- Run a canary deployment by replica weighting
- Promote or roll back a canary release
Prerequisites¶
- Kind cluster running
- kubectl configured and working
- Basic understanding of Deployments and Services
Tasks¶
Task 1: Create the Lab Namespace¶
Create a namespace for all deployment strategy resources.
Requirements:
- Namespace name:
deploy-strategy-lab - Set your current context namespace to
deploy-strategy-lab - Verify the namespace exists
Hint
Create the namespace:
Set it as the default namespace for your current context:
Solution
Task 2: Configure an Advanced Rolling Update¶
Deploy a baseline application with rolling update controls and readiness checks.
Requirements:
- Deployment name:
rollout-demo - Image:
nginx:1.25-alpine - Replicas: 4
- Label:
app=rollout-demo - Rolling update strategy with
maxUnavailable: 0andmaxSurge: 1 minReadySeconds: 5- Readiness probe on
/ - Service name:
rollout-demo, port: 80
Hint
The strategy belongs under spec.strategy:
A simple readiness probe for nginx can use:
Solution
Create rollout-demo-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: rollout-demo
spec:
replicas: 4
minReadySeconds: 5
selector:
matchLabels:
app: rollout-demo
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
template:
metadata:
labels:
app: rollout-demo
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 2
periodSeconds: 3
Create rollout-demo-service.yaml:
apiVersion: v1
kind: Service
metadata:
name: rollout-demo
spec:
selector:
app: rollout-demo
ports:
- port: 80
targetPort: 80
Apply and verify:
Task 3: Watch a Rolling Update¶
Update the image and observe how Kubernetes replaces Pods.
Requirements:
- Change the Deployment image to
nginx:1.26-alpine - Watch the rollout status
- Confirm the new image is running
- Inspect rollout history
- Roll back to the previous revision
Hint
Update the image:
Watch rollout status and history:
kubectl rollout status deployment/rollout-demo
kubectl rollout history deployment/rollout-demo
kubectl describe deployment rollout-demo
Roll back:
Solution
kubectl set image deployment/rollout-demo nginx=nginx:1.26-alpine
kubectl rollout status deployment/rollout-demo
kubectl get pods -l app=rollout-demo
kubectl describe deployment rollout-demo | grep Image
kubectl rollout history deployment/rollout-demo
kubectl rollout undo deployment/rollout-demo
kubectl rollout status deployment/rollout-demo
Expected result: The Deployment keeps available replicas during the update and returns to nginx:1.25-alpine after rollback.
Task 4: Deploy Blue and Green Versions¶
Deploy two complete versions of the same app side by side.
Requirements:
- Blue Deployment name:
web-blue, labels:app=web, version=blue, page containsBLUE version - Green Deployment name:
web-green, labels:app=web, version=green, page containsGREEN version - One replica for each Deployment
- Service name:
web, selector initially points toapp=web, version=blue
Hint
Use nginx with a shell command that writes index.html before starting nginx:
command: ["/bin/sh", "-c"]
args:
- |
echo 'BLUE version' > /usr/share/nginx/html/index.html
nginx -g 'daemon off;'
Create the Service selector with both labels:
Solution
Create web-blue.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-blue
spec:
replicas: 1
selector:
matchLabels:
app: web
version: blue
template:
metadata:
labels:
app: web
version: blue
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
command: ["/bin/sh", "-c"]
args:
- |
echo 'BLUE version' > /usr/share/nginx/html/index.html
nginx -g 'daemon off;'
Create web-green.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-green
spec:
replicas: 1
selector:
matchLabels:
app: web
version: green
template:
metadata:
labels:
app: web
version: green
spec:
containers:
- name: nginx
image: nginx:1.26-alpine
ports:
- containerPort: 80
command: ["/bin/sh", "-c"]
args:
- |
echo 'GREEN version' > /usr/share/nginx/html/index.html
nginx -g 'daemon off;'
Create web-service.yaml:
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
version: blue
ports:
- port: 80
targetPort: 80
Apply:
Task 5: Switch and Roll Back Blue/Green Traffic¶
Use the Service selector to switch production traffic.
Requirements:
- Port-forward the
webService - Confirm traffic initially reaches blue
- Patch the Service selector to
version=green - Confirm traffic reaches green
- Patch the Service selector back to
version=blue - Confirm rollback is instant
Hint
Port-forward the Service:
Patch the selector to green:
Patch it back to blue:
Solution
In another terminal:
curl http://localhost:8080
kubectl patch service web -p '{"spec":{"selector":{"app":"web","version":"green"}}}'
curl http://localhost:8080
kubectl patch service web -p '{"spec":{"selector":{"app":"web","version":"blue"}}}'
curl http://localhost:8080
Expected result:
Task 6: Run a Canary Deployment¶
Deploy stable and canary versions behind one Service.
Requirements:
- Stable Deployment name:
api-stable, labels:app=api, track=stable, 4 replicas, page containsstable - Canary Deployment name:
api-canary, labels:app=api, track=canary, 1 replica, page containscanary - Service name:
api, selector matchesapp=apionly
Hint
The canary Service should select only the shared app label:
Kubernetes load balances across all matching Pods. With 4 stable Pods and 1 canary Pod, the canary receives roughly 20% of requests.
Solution
Create api-stable.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-stable
spec:
replicas: 4
selector:
matchLabels:
app: api
track: stable
template:
metadata:
labels:
app: api
track: stable
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
command: ["/bin/sh", "-c"]
args:
- |
echo 'stable' > /usr/share/nginx/html/index.html
nginx -g 'daemon off;'
Create api-canary.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-canary
spec:
replicas: 1
selector:
matchLabels:
app: api
track: canary
template:
metadata:
labels:
app: api
track: canary
spec:
containers:
- name: nginx
image: nginx:1.26-alpine
ports:
- containerPort: 80
command: ["/bin/sh", "-c"]
args:
- |
echo 'canary' > /usr/share/nginx/html/index.html
nginx -g 'daemon off;'
Create api-service.yaml:
apiVersion: v1
kind: Service
metadata:
name: api
spec:
selector:
app: api
ports:
- port: 80
targetPort: 80
Apply:
Task 7: Promote or Roll Back the Canary¶
Observe traffic split and then choose a final action.
Requirements:
- Send at least 20 requests to the
apiService - Count how many responses go to stable vs canary
- Promote by scaling stable to 0 and canary to 5
- Roll back by scaling canary to 0 and stable to 5
- Leave the app in either promoted or rolled-back state
Hint
Port-forward the canary Service:
In another terminal, send requests:
Promote canary:
Roll back canary:
Solution
In another terminal:
Expected result: ~16 stable and ~4 canary responses (approximately 80/20 split with 4+1 replicas).
Promote:
Or roll back:
Verification¶
Check your work:
kubectl get deployments,services
kubectl rollout history deployment/rollout-demo
kubectl get endpoints web api
Expected outcomes:
rollout-demorolls forward and back without dropping all replicaswebService can switch between blue and greenapiService sends traffic to both stable and canary while both have replicas- Canary can be promoted or rolled back with scaling changes
Cleanup¶
kubectl delete namespace deploy-strategy-lab
kubectl config set-context --current --namespace=default
Key takeaways¶
maxUnavailable: 0withmaxSurgeensures zero-downtime rolling updates by always keeping old Pods running during the rollout- Blue/green deployments enable instant traffic switching and fast rollback simply by updating a Service selector
- Canary releases expose a controlled percentage of traffic to new code by managing replica ratios between stable and canary Deployments
- Service selectors are the traffic control plane — changing a label match redirects all traffic without touching Pods
- Progressive delivery controllers like Flagger automate canary promotion based on real metrics, removing the need for manual replica management
- Replica-weighted canary has limits — traffic split is coarse-grained and tied to replica count, making precise percentages impossible at low replica numbers
Next section¶
Once you've reviewed the content and completed the lab, proceed to the next section.