AI Hints
Home›Kubernetes Tutorial›Bonus Labs: Zero Downtime
Kubernetes · Lesson 81 of 86

Lab: Prove Zero Downtime

Rolling updates under load.

⏱ 2 min read▶ Video at 3:02:26🎓 Free
Watch this lesson in the Kubernetes courseWatch on YouTube ↗Full Kubernetes course

We said that rolling updates cause no downtime. Let's prove it. In this lab, a load generator sends ten requests every second to a service, and counts every failure. Then we update the application, twice. Once with a careful rolling update, and once with the strategy that stops everything first. The numbers will speak for themselves.

Lab: Prove Zero Downtime
From the video: Lab: Prove Zero Downtime
  • Claims need proof
  • A load generator counts failures
  • Rolling versus recreate

The careful rollout

Here is the careful configuration. Three replicas. A rolling update strategy, with max unavailable set to zero, which means, never remove a working pod, before a replacement is ready. Max surge of one, so there can be one extra pod during the change. Min ready seconds, so a new pod proves itself for three seconds. And a readiness probe, that checks the web page, every second. These few lines are the recipe, for updates that nobody notices.

web.yamlyaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  minReadySeconds: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:1.25
        readinessProbe:
          httpGet:
            path: /
            port: 80
          periodSeconds: 1
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
  - port: 80

Rolling update under load

First, the careful rollout. The load generator is already running, in the background. We update the image, and wait for the rollout to finish. Then we count what the load generator saw, during the last twenty seconds. Every request was answered. The count of failures does not even appear, because there was none. While the pods were being replaced, a ready pod was always available, so every request found one.

kubectl
kubectl set image deployment/web web=nginx:1.27
deployment.apps/web image updated
kubectl rollout status deployment/web
Waiting for deployment "web" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "web" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "web" rollout to finish: 1 old replicas are pending termination...
deployment "web" successfully rolled out
kubectl logs loadgen --since=25s | sort | uniq -c
 170 OK
File used: web.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  minReadySeconds: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:1.25
        readinessProbe:
          httpGet:
            path: /
            port: 80
          periodSeconds: 1
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
  - port: 80

The Recreate strategy

Now the contrast. We switch to the recreate strategy, which stops all old pods first, and then starts the new ones. We run the same load generator, and update the image again. After the rollout, we count again. This time, some requests failed. For a few seconds, there were no pods at all, and the service had nothing to send traffic to. Same application, same update, a different strategy, and a measurable outage.

kubectl
kubectl set image deployment/web web=nginx:1.27
deployment.apps/web image updated
kubectl rollout status deployment/web
Waiting for deployment "web" rollout to finish: 0 out of 3 new replicas have been updated...
Waiting for deployment "web" rollout to finish: 0 of 3 updated replicas are available...
Waiting for deployment "web" rollout to finish: 1 of 3 updated replicas are available...
Waiting for deployment "web" rollout to finish: 2 of 3 updated replicas are available...
deployment "web" successfully rolled out
kubectl logs loadgen --since=25s | sort | uniq -c
   3 FAIL
  71 OK
   1 wget: can't connect to remote host (10.109.195.175): Connection refused
   2 wget: download timed out
File used: web.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:1.25
        readinessProbe:
          httpGet:
            path: /
            port: 80
          periodSeconds: 1
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
  - port: 80

Summary

Excellent. A rolling update, with max unavailable zero, and a good readiness probe, served every request. The recreate strategy caused a visible outage. Always check readiness probes, because they are what makes rolling updates safe. Next, protecting your pods, during maintenance, with disruption budgets.

Key takeaways
  • maxUnavailable 0 + readiness probe
  • Recreate causes an outage
  • Measure, do not assume
Next up: Lab: Disruption Budgets — safe maintenance