Kubernetes Liveness, Readiness, and Startup Probes Explained
The three probe types keep Kubernetes applications healthy — and misconfigure one and you'll restart healthy containers or starve them of traffic. Here's how each works.
Published on • October 11, 2026
AI Assistant

Kubernetes can restart a crashed container trivially. The hard problem is knowing whether a container is running but broken — hung on a deadlock, overloaded, or still warming up. Probes are how the kubelet asks your application “are you okay?” — and there are three kinds, each with a distinct job. Get them confused and you’ll either restart healthy pods or send traffic to broken ones.
The three questions
Every container lifecycle raises three separate questions:
- Is it alive? → liveness probe. Should Kubernetes restart a container that’s wedged?
- Is it ready for traffic? → readiness probe. Should this pod be in the Service’s endpoint list right now?
- Is it done starting up? → startup probe. Can slow-starting apps boot without being killed prematurely?
They’re configured independently and don’t depend on each other to succeed.
Liveness probes: “should I restart you?”
The liveness probe detects states a process can’t recover from — deadlocks, corrupted state. When it fails, the kubelet kills the container and the pod’s restartPolicy takes over.
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
Four probe mechanisms are supported:
httpGet— success is any 2xx/3xx status code (anything else fails).exec— run a command in the container; exit code 0 succeeds. Simple and universal:cat /tmp/healthy.tcpSocket— open a TCP connection to the port; connect succeeds = healthy. Coarse but protocol-agnostic.grpc— call the gRPC Health Checking Protocol, stable since Kubernetes v1.27.
The classic example from the Kubernetes probe task docs: a container creates /tmp/healthy, deletes it after 30 seconds, and the liveness probe — cat /tmp/healthy every 5 seconds — kills and restarts it once the file is gone.
The liveness anti-pattern: pointing liveness at something that depends on external services (a database, a downstream API). If the database blips, you restart every app pod — a self-inflicted outage cascading through your system. Liveness should check only internal, self-contained state.
Readiness probes: “should I receive traffic?”
A pod that fails its readiness probe is removed from the Service’s endpoints. It keeps running — no restart — it just gets no user traffic until it recovers.
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3
Readiness is where your app answers operational questions: Has it loaded its configuration? Is a warmup cache complete? Is it safe to take writes?
Two subtleties:
- Readiness runs for the pod’s whole life, not just at startup. A dependency outage should flip readiness to false so the Service stops routing to an instance that’s about to fail requests.
- Readiness failing doesn’t restart anything. If your app can only recover by being restarted, that’s a liveness concern — use both probes on the same container for both behaviors.
Readiness is also the correct probe for graceful shutdown: when a pod is deleted, Kubernetes removes it from endpoints first (via the terminating state), so don’t fight it with clever signal handling alone.
Startup probes: “give me time to boot”
Slow applications — JVM apps, large ML model servers — can’t pass a liveness probe quickly. Without protection, a tight liveness probe kills them during startup, and they crash-loop forever.
The startup probe runs until it succeeds once, and only then do liveness and readiness take over:
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10
Here the app gets 30 × 10 = 300 seconds (5 minutes) to finish booting. If it never succeeds, the container is killed and subject to restartPolicy. Once it passes, the liveness probe (say, failureThreshold: 1, periodSeconds: 10) resumes its job of fast deadlock detection.
Rule of thumb: if your app might take more than ~30 seconds to start, use a startup probe instead of inflating initialDelaySeconds — delays don’t adapt, and a large delay also delays your deadlock detection.
Shared configuration fields
All three probes use the same timing knobs:
| Field | Purpose | Default |
|---|---|---|
initialDelaySeconds | Wait before first probe | 0 |
periodSeconds | Interval between probes | 10 |
timeoutSeconds | Per-probe timeout | 1 |
successThreshold | Consecutive successes to pass | 1 (readiness: 1) |
failureThreshold | Consecutive failures to fail | 3 |
For HTTP probes you can reference a named port (port: liveness-port), and HTTP/2 cleartext (h2c) probing is available behind a feature gate for gRPC-only services.
A complete example
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: api
image: my-api:2.1.0
ports:
- containerPort: 8080
startupProbe:
httpGet: { path: /healthz, port: 8080 }
failureThreshold: 30
periodSeconds: 10
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet: { path: /ready, port: 8080 }
periodSeconds: 5
failureThreshold: 2
Debugging probes
When a probe misbehaves, kubectl describe pod shows the events:
kubectl describe pod my-api-7d9f | tail -20
# Warning Unhealthy Liveness probe failed: HTTP probe failed with statuscode: 500
# Normal Killing Container my-api failed liveness probe, will be restarted
A restart loop with Unhealthy events almost always means a liveness probe that’s too aggressive or pointed at the wrong dependency.
The decision tree
- App might hang after startup? → liveness
- App has dependencies that should gate traffic? → readiness
- App takes ages to boot? → startup (then liveness takes over)
- Never: liveness on an external dependency; readiness that never recovers without a restart.
Get the trio right and Kubernetes does the right thing automatically — restart what’s broken, shield what’s unready, and wait for what’s slow. The full reference lives in the Kubernetes probe documentation.