Health Checks & Self-Healing

Kubernetes Fundamentals

Chapter 11 · Health Checks & Self-Healing

Chapter 5's self-healing and Chapter 2's reconciliation loop both assume Kubernetes can actually detect a problem. This chapter covers exactly how.

The Problem — "Running" Doesn't Mean "Healthy"

Revisiting Chapter 3's pod phase material: a container can sit in the "Running" phase while being completely unresponsive, deadlocked, or stuck in an infinite loop. The process technically hasn't crashed, so Kubernetes' default behavior — restarting only on an actual process exit — wouldn't catch this at all. "The process is running" and "the application is working correctly" are not the same claim.

Probes — How Kubernetes Actually Checks

  • Liveness — "is this container still alive and functioning, or should it be restarted?"
  • Readiness — "is this container ready to receive traffic right now?" (directly tied to Chapter 6's Service/Endpoints material.)
  • Startup — "has this container finished its possibly slow startup process yet?" — used to prevent liveness probes from prematurely killing a container still legitimately starting up.

Liveness Probes — Restart on Failure

A failed liveness probe causes Kubernetes to kill and restart the container. This is what actually triggers self-healing at the container level — genuinely distinct from Chapter 5's pod-replacement-level self-healing via the ReplicaSet. A liveness probe failure restarts a container within the same pod; a pod being deleted entirely is a separate, higher-level event handled by the ReplicaSet.

Readiness Probes — Removing From Service Without Killing

Sometimes a container is perfectly alive and functioning, but temporarily not ready to serve traffic — still loading a large dataset at startup, or briefly overloaded and needing a moment to catch up. Killing and restarting it in this case would be actively counterproductive. A readiness probe instead just temporarily removes the pod from the Service's Endpoints (Chapter 6) until it reports ready again — no restart involved at all.

A genuinely common mistake: using only a liveness probe
Using a liveness probe alone for a signal that's really a readiness concern causes unnecessary restarts for a problem that never actually needed one — a temporarily-busy-but-healthy container simply needed to be pulled out of rotation for a moment, not killed.

Startup Probes — Handling Slow-Starting Applications

Some applications — heavy initialization work like loading a large ML model or warming a cache — take much longer to become ready than a typical liveness probe's failure threshold tolerates, causing the liveness probe to repeatedly kill the container before it ever finishes starting. A genuinely frustrating, common real problem. A startup probe defers liveness (and readiness) probing entirely until it itself succeeds once, giving slow-starting applications the room they genuinely need.

Probe Mechanics — HTTP, TCP & Exec

  • HTTP GET — the most common; checks for a successful response code from a specified path.
  • TCP socket — simply checks whether a port accepts a connection; useful for non-HTTP services.
  • Exec — runs a command inside the container and checks its exit code; most flexible, also the most expensive and slowest of the three.

Configurable timing parameters — initialDelaySeconds, periodSeconds, failureThreshold — are genuinely practical knobs worth knowing exist, even without exhaustive detail on each here.

A Concrete Example — Liveness & Readiness Together

containers: - name: web image: myapp:latest livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 10 periodSeconds: 15 readinessProbe: httpGet: path: /ready port: 8080 periodSeconds: 5

A genuinely common real-world pattern: an application exposes two separate health endpoints with distinct meanings, matching the liveness-vs-readiness distinction explained above.

Restart Policies

spec.restartPolicy controls what happens when a container exits: Always (default, appropriate for long-running services like Deployments), OnFailure (only restarts on a non-zero exit — relevant for Course 2's own Jobs material), Never. This is a pod-level setting, genuinely distinct from the per-container liveness-probe-triggered restarts covered above — two related but different restart mechanisms worth not conflating.

How This All Ties Together — The Full Self-Healing Picture

The reconciliation loop (Chapter 2) is the general mechanism. ReplicaSets (Chapter 5) use it to maintain pod count. Liveness probes (this chapter) tell Kubernetes when a specific container needs restarting. Readiness probes (this chapter) tell Services (Chapter 6) which pods should currently receive traffic. Together, this is what makes Kubernetes self-healing in the full, practical sense Chapter 1 promised — a satisfying convergence of nearly everything this course has covered so far, ahead of Chapter 12's own capstone.

Readiness vs. liveness — the most commonly confused pair in this chapter
Liveness asks "should this be restarted?" Readiness asks "should this currently receive traffic?" Being deliberate about which question a given health signal actually answers avoids both unnecessary restarts and traffic sent to a genuinely broken container.

Hands-On Exercises

Exercise 1

Explain the difference between a liveness probe failing and a readiness probe failing — specifically, what action Kubernetes takes in each case.

📄 View solution
Exercise 2

Explain why a startup probe is needed for some applications even though liveness and readiness probes already exist. What specific problem does it solve that the other two don't?

📄 View solution
Exercise 3

An application is occasionally slow to respond to database queries under heavy load, but is not actually broken or deadlocked. A liveness probe with a very short timeout keeps killing and restarting the container during these slow periods, making the problem worse. Explain what's misconfigured here and how it should be fixed.

📄 View solution

Chapter 11 Quick Reference

  • "Running" ≠ "healthy" — a deadlocked container can stay in the Running phase indefinitely without probes
  • Liveness (restart the container) vs. readiness (remove from Service Endpoints, no restart) vs. startup (defers the other two until initial startup finishes)
  • Probe mechanics: HTTP GET (most common), TCP socket, Exec (most flexible, slowest)
  • restartPolicy (Always/OnFailure/Never) is pod-level, distinct from container-level liveness-triggered restarts
  • Full self-healing picture: reconciliation loop (Ch.2) → ReplicaSets maintain count (Ch.5) → liveness restarts a container → readiness controls Service traffic (Ch.6)
  • A liveness probe that's too aggressive can kill a genuinely healthy, just-temporarily-slow application — tune thresholds deliberately
  • Next chapter: Capstone — A Small Multi-Tier App, combining everything from this course