Probes, restart policies and disruption budgets

The three probes and what each one does when it fails, how readiness decides which Pods get traffic, and how a PodDisruptionBudget protects an app during a node drain.

40 min 3 hands-on tasksWorkloads · 15% of the exam

Key ideas in this lesson · tap one for a simple explanation

What you will be able to do

  • Add liveness, readiness and startup probes with the right check and timing, and say what each failure causes.
  • Trace a Pod that is Running but not Ready back to its probe, and see the effect on the Service's endpoints.
  • Create a PodDisruptionBudget and read whether it allows a disruption right now.

Kubernetes can only fix what it notices. If a crashes, the sees the process exit and restarts it. But what if your Django app is still running, yet stuck and answering nothing? A is a regular health check that the kubelet runs against a container, so it can notice that too.

On the exam, you may add probes to a workload, or fix a probe that checks the wrong place. You may also protect a workload from a with a .

Three probes, three different questions

When each probe runs

Startup probe

has the app finished starting?

Then, for the container's whole life

Readiness probe

can it take traffic now?

Liveness probe

is it stuck?

The startup probe runs first. Once it passes, readiness and liveness checks run side by side for the rest of the container's life.

ProbeAsksWhen it failsTypical check
livenessProbeIs the app stuck?The kubelet kills the container. restartPolicy decides what happens nextA cheap local check, such as a TCP port
readinessProbeCan it take traffic right now?The is marked not Ready and gets no traffic. Nothing is restartedA page that shows the app can serve
startupProbeHas it finished starting?Liveness and readiness wait until it passes. If it never passes, the container is killedThe liveness check, with more time allowed

Example: your Django app takes 60 seconds to load. A startup probe gives it that time. After that, the readiness probe keeps it out of the Service while it cannot serve, and the liveness probe restarts it if it hangs.

Each probe uses one kind of check, called a handler. The common ones are httpGet (send an HTTP request), tcpSocket (open a port) and exec (run a command inside the container).

All three probes, and the handler types
      containers:
        - name: web
          image: nginx:1.27
          ports:
            - containerPort: 80
              name: http
          startupProbe:
            httpGet:
              path: /
              port: http            # a named port works anywhere a port number does
            periodSeconds: 5
            failureThreshold: 24    # up to 24 x 5 = 120s to start
          readinessProbe:
            httpGet:
              path: /
              port: 80
            periodSeconds: 5
          livenessProbe:
            tcpSocket:
              port: 80
            periodSeconds: 10
            failureThreshold: 3
        # Other handlers:
        #   exec:     { command: ["cat", "/tmp/healthy"] }   # exit code 0 = success

These timing fields work the same on all three probes:

FieldDefaultMeaning
initialDelaySeconds0Seconds to wait after the container starts, before the first check
periodSeconds10How often to check
timeoutSeconds1How long one check may take
failureThreshold3Failures in a row before acting
successThreshold1Successes in a row to count as passing again. Must be 1 for liveness and startup
  • For a slow starter, use a startup probe, not a long initialDelaySeconds on liveness. The app gets time to start, and a later hang is still caught quickly.
  • Keep liveness checks local. Say a liveness probe calls the database. When the database has a short outage, every replica fails its check and restarts at once: one outage becomes two.

Readiness is what Services and rollouts trust

A Pod that fails readiness stays Running, but shows READY 0/1. Two things follow:

  • Services skip it. Its address stays in the Service's , marked ready: false, so no traffic is sent to it.
  • Rollouts wait for it. A counts only Ready Pods as available. So a whose new Pods never become Ready stops, instead of replacing healthy Pods.

A wrong readiness port is one of the most common cases of it is running but nothing works. Trace it like this:

From symptom to probe
kubectl -n wl-probe get pods -l app=catalog                    # Running, READY 0/1
kubectl -n wl-probe describe pod -l app=catalog | grep -E 'Readiness|Liveness|Unhealthy' | head
#   Warning  Unhealthy  ...  Readiness probe failed: Get "http://10.244.x.x:8080/": dial tcp ... connection refused
kubectl -n wl-probe get endpointslices -l kubernetes.io/service-name=catalog -o yaml | grep -A1 conditions
kubectl -n wl-probe get deploy catalog -o jsonpath='{.spec.template.spec.containers[0].readinessProbe}'; echo

restartPolicy and CrashLoopBackOff

restartPolicy is set once per Pod and covers every container in it. Deployments, and accept only Always. use OnFailure or Never.

After a crash or a liveness kill, the kubelet restarts the container, and it waits a little longer each time. While it waits, the Pod shows CrashLoopBackOff. Finding out why is covered in Application failures.

PodDisruptionBudgets

Sometimes Pods are removed on purpose, for example when you drain a node to upgrade it. A PodDisruptionBudget (PDB) makes sure enough Pods of an app stay up while that happens. Example: your shop runs 3 cart Pods. A PDB with minAvailable: 2 lets a drain take away only one of them at a time.

policy/v1: keep at least two Pods through voluntary disruptions
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: cart-pdb
  namespace: wl-probe
spec:
  minAvailable: 2          # or maxUnavailable: 1; never both. Integers or percentages.
  selector:
    matchLabels:
      app: cart
# Imperative: kubectl -n wl-probe create pdb cart-pdb --selector=app=cart --min-available=2
What happens during a drain

kubectl drain

asks to evict a Pod

PodDisruptionBudget

would enough Pods stay up?

Eviction

allowed, or refused and tried again

What a PDB protects against

  • It limits voluntary disruptions that go through the Eviction API: kubectl drain, a cluster autoscaler removing a node, and some upgrade tools.
  • It does nothing when a node crashes.
  • kubectl delete pod skips it completely.

How to read it. Run kubectl get pdb and look at ALLOWED DISRUPTIONS:

  • 1 or more: a drain may evict that many of these Pods right now.
  • 0: a drain of a node that runs one of these Pods will block.
  • The trap: minAvailable equal to the replica count always leaves 0, so it blocks every drain.

In the official docs· open on exam day too

Hands-on task 1 of 3wl-probe-1
~6 min5% weightWorkloads

Add readiness and liveness probes to a Deployment

The Deployment shop in namespace wl-probe has no health checks. Add to its nginx container a readiness probe that sends an HTTP GET to / on port 80 every 5 seconds, starting 3 seconds after the container starts, and a liveness probe that opens a TCP connection to port 80 every 10 seconds, starting after 10 seconds, and restarts the container after 3 consecutive failures. All 3 replicas must be ready afterwards.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-probe-1/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-probe-1/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-probe-1/cleanup | bash
Hands-on task 2 of 3wl-probe-2
~4 min4% weightWorkloads

Protect a Deployment from drains with a PDB

In namespace wl-probe, create a PodDisruptionBudget named cart-pdb for the Pods of Deployment cart so that voluntary disruptions such as a node drain can never leave fewer than 2 of them available.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-probe-2/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-probe-2/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-probe-2/cleanup | bash
Hands-on task 3 of 3wl-probe-3
~7 min6% weightWorkloads

Pods run but never become Ready

In namespace wl-probe, the Pods of Deployment catalog are all Running, yet none of them is Ready and the Service catalog sends traffic nowhere. Find the cause and fix the Deployment so that all 3 replicas become Ready and are registered as ready endpoints of the Service. Do not remove the readiness probe.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-probe-3/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-probe-3/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/wl-probe-3/cleanup | bash

Finished this lesson?

0 of 3 tasks passed. Your readiness counts tasks, so run them before you move on.