Lab 11 - Deployments and probes

Lab 11 - Deployments and probes

Goal: roll forward, break it, roll back - and see why the break was harmless. Chapter: Deployments

# 1 - generate, do not hand-write
cd ~
kubectl create deploy web --image nginx:1.27 --replicas 3 \
  --dry-run=client -o yaml > web-deploy.yaml
kubectl apply -f web-deploy.yaml
kubectl get deploy,rs,pods -l app=web

Three objects for one command: the Deployment you asked for, the ReplicaSet it created, and the Pods that ReplicaSet created.

# 2 - roll forward
kubectl set image deploy/web nginx=nginx:1.28
kubectl rollout status deploy/web
kubectl get rs -l app=web

Two ReplicaSets now: the old one at 0 replicas, the new one at 3. The old one is kept on purpose - it is the rollback.

# 3 - the history
kubectl rollout history deploy/web
kubectl rollout history deploy/web --revision=2
# 4 - break it on purpose
kubectl set image deploy/web nginx=nginx:doesnotexist
kubectl rollout status deploy/web --timeout=30s      # never completes
kubectl get pods -l app=web
kubectl get rs -l app=web

Look carefully: the old Pods are still running and still serving. Because maxUnavailable is 1, the Deployment refuses to remove healthy Pods until the new ones are ready - and they never are. A bad image stalls a rollout; it does not cause an outage.

# 5 - roll back
kubectl rollout undo deploy/web
kubectl rollout status deploy/web
kubectl get pods -l app=web -o jsonpath='{.items[0].spec.containers[0].image}{"\n"}'

Probes

# 6 - add a readiness probe that cannot succeed
kubectl patch deploy web -p '{"spec":{"template":{"spec":{"containers":[{"name":"nginx","readinessProbe":{"httpGet":{"path":"/nope","port":80},"periodSeconds":3}}]}}}}'
kubectl get pods -l app=web

The new Pods are Running but 0/1 READY. A readiness failure does not restart anything - it removes the Pod from Service endpoints. And because the rollout waits for readiness, this rollout is stuck too, safely.

# 7 - fix the probe path
kubectl patch deploy web -p '{"spec":{"template":{"spec":{"containers":[{"name":"nginx","readinessProbe":{"httpGet":{"path":"/","port":80},"periodSeconds":3}}]}}}}'
kubectl rollout status deploy/web
kubectl get pods -l app=web

Discovery

Infodiscovery

Task A. Make the rollout strictly zero-downtime: never fewer than the full number of Pods available, at most one extra Pod during the update. Then trigger a rollout and confirm the count never dips.

kubectl patch deploy web -p \
  '{"spec":{"strategy":{"rollingUpdate":{"maxUnavailable":0,"maxSurge":1}}}}'
kubectl set image deploy/web nginx=nginx:1.27-alpine
kubectl get pods -l app=web -w         # Ctrl-C when done

The cost is capacity: you need room for one more Pod than you run.

Task B. Restart every Pod of the Deployment without changing the image and without deleting Pods by hand.

kubectl rollout restart deploy/web
kubectl rollout status deploy/web

This is how you make a Deployment pick up a changed ConfigMap or Secret that is consumed as environment variables.

Task C. Find out which ReplicaSet is currently active and how many old ones the Deployment is keeping.

kubectl get rs -l app=web
kubectl get deploy web -o jsonpath='{.spec.revisionHistoryLimit}{"\n"}'

Default is 10 old ReplicaSets retained.

Clean up

kubectl delete -f web-deploy.yaml