Chapter 13 of 47 · Workloads and Services

Health probes: liveness, readiness and startup

Kubernetes can see if your process is running. It cannot see if your app is actually working. A process can be alive but frozen, or still starting up, or unable to reach its database. Probes are small checks Kubernetes runs again and again to ask your app "are you OK?". The answer decides whether the container is restarted, and whether it gets traffic.

Running is not the same as working

Think of a shop assistant. "Is the assistant in the building?" is not the same question as "Can the assistant serve customers right now?". They might be asleep at the counter, or still unpacking boxes in the morning.

What Kubernetes sees for free

The main process exists. If it crashes, the container is restarted (chapter 7). That is all.

What it cannot see without help

  • A frozen app: stuck in an endless loop or deadlock, process still alive.
  • An app still loading data, not ready for users yet.
  • An app that lost its database connection.

Three probes, three questions

Three probes and what happens when they failThe startup probe runs first, until it succeeds once. Then liveness and readiness run all the time. A failing liveness probe restarts the container. A failing readiness probe takes the Pod out of the Service. Startup probe"Have you finishedstarting?" then Liveness probe"Are you still alive,or stuck?" Readiness probe"Can you takerequests right now?" fails Container restartedRESTARTS +1 fails Out of the Serviceno restart, no traffic
ProbeQuestionIf it failsRuns
LivenessAre you stuck beyond repair?The container is killed and restartedAll the time
ReadinessCan you serve traffic right now?The Pod is removed from Service endpoints (chapter 11). Not restarted. Added back once it passes.All the time
StartupHave you finished starting?Keeps checking; after too many failures the container is restarted. Liveness and readiness wait until it succeeds.Only at the start, until it passes once
Easy way to remember: liveness = "turn it off and on again". Readiness = "put up a 'back in 5 minutes' sign". Startup = "give it time to wake up first".

How a probe checks

livenessProbe:
  httpGet:
    path: /healthz
    port: 4000

Kubernetes calls the URL. Any status from 200 to 399 counts as healthy; anything else, or no answer in time, is a failure. The best choice for web apps like posts.

The timing knobs

Every probe has the same settings. Click each one:

livenessProbe:
  httpGet:
    path: /healthz
    port: 4000
  initialDelaySeconds: 0
  periodSeconds: 10
  timeoutSeconds: 2
  failureThreshold: 3
  successThreshold: 1

periodSeconds

How often to check. Default 10 seconds.

Simple maths: time until action ≈ periodSeconds × failureThreshold. A startup probe with periodSeconds: 5 and failureThreshold: 30 allows up to 150 seconds to start.

Probes for the posts service

Give the app two small endpoints. /healthz answers "is this process OK?" and checks nothing outside it. /ready answers "can I serve requests?" and may check what the app truly needs.

// posts/index.js
let ready = false;
let shuttingDown = false;                                    // set to true in your SIGTERM handler

app.get('/healthz', (req, res) => res.sendStatus(200));     // alive = event loop answers

app.get('/ready', (req, res) => {
  if (ready && !shuttingDown) return res.sendStatus(200);
  res.sendStatus(503);                                      // "not now, send traffic elsewhere"
});

await loadCache();          // slow startup work
ready = true;
containers:
  - name: posts
    image: micro-posts:1.0
    ports:
      - containerPort: 4000
    startupProbe:
      httpGet: { path: /healthz, port: 4000 }
      periodSeconds: 5
      failureThreshold: 30        # up to 150s to start
    livenessProbe:
      httpGet: { path: /healthz, port: 4000 }
      periodSeconds: 10
      timeoutSeconds: 2
      failureThreshold: 3
    readinessProbe:
      httpGet: { path: /ready, port: 4000 }
      periodSeconds: 5
      failureThreshold: 2

Readiness also makes deploys safe: during a rolling update, an old Pod is removed only after a new one is ready (chapter 10). Without a readiness probe, "ready" just means "the process started", even if the app cannot answer yet. And on shutdown, flipping /ready to 503 helps traffic drain away (chapter 14).

Try it: which probes save you?

Pick a problem and a probe setup. Read what Kubernetes does. Find the setup that is green in every case:

Common mistakes

Two extras

Seeing why it failed

$ kubectl describe pod posts-depl-4kq2p
Events:
  Warning  Unhealthy  Liveness probe failed:
           HTTP probe failed with statuscode: 500
  Normal   Killing    Container posts failed liveness
           probe, will be restarted

When a container dies, it can also write a short reason to /dev/termination-log. Kubernetes shows that text as the "Message" of the last state in kubectl describe.

Readiness gates

Sometimes something outside the Pod must agree it is ready, for example a cloud load balancer that has finished registering it. A readinessGates entry adds such an extra condition, set by another controller. You will mostly meet this in cloud load balancer setups, not write it yourself.

Recap

Quick check

Your Pods restart every time the database has a short hiccup. What is the most likely cause?
Show answer

The liveness probe checks the database. Move that check to the readiness probe (or drop it), and keep liveness to "does my process answer".

A new version takes 60 seconds to start and is stuck in CrashLoopBackOff. Liveness uses the defaults. Fix?
Show answer

Liveness kills it at about 30 seconds, before it finishes starting. Add a startup probe, for example periodSeconds: 5 and failureThreshold: 24 (up to 120s).

Health probes: common questions

What is the difference between liveness and readiness probes?

A failing liveness probe restarts the container. A failing readiness probe only removes the Pod from Service traffic until it passes again.

Should a liveness probe check the database?

No. A database outage would then restart every Pod again and again. Keep liveness about the process itself and put dependency checks in readiness, if anywhere.