# Missing Liveness Probe

> Without a liveness probe Kubernetes only restarts a container when its process exits. A deadlocked application that keeps its process alive stays in the Ready pool receiving traffic indefinitely. ZopNight checks 3 workload kinds and reports this as a pure configuration read.

Source: https://zop.dev/integrations/kubernetes/recommendations/missing-liveness-probe
Updated: 2026-08-19

---

## Kubernetes cannot detect a hung process on its own

The default health signal is the process exit code. A container whose main process is running is,
as far as the kubelet is concerned, healthy.

That covers crashes. It does not cover deadlock, an exhausted thread pool, a wedged event loop, or
a connection pool that will never recover. In every one of those the process is alive and the
application is not, and without a liveness probe nothing ever restarts it.

## Liveness and readiness answer different questions

Worth separating, because conflating them causes real outages:

- **Readiness**: "should traffic go here right now?" Failing removes the pod from Service
  endpoints. Recoverable and routine.
- **Liveness**: "is this container beyond saving?" Failing **kills and restarts** it.

A liveness probe that is really a readiness check is actively harmful. If it fails during a slow
dependency, Kubernetes restarts a container that was merely waiting. Under a shared outage it
restarts every replica simultaneously, converting degradation into an outage.

## The dependency trap

A liveness endpoint that checks the database is the classic mistake. When the database has a bad
minute, every pod fails liveness, every pod restarts, and the application cannot recover even
after the database does.

Liveness should test the process itself and nothing downstream.

## Slow starts need startupProbe

An application taking two minutes to warm up will be killed repeatedly by a liveness probe with a
short `initialDelaySeconds`. A `startupProbe` suspends liveness until the app is up, which is the
correct tool. Extending `initialDelaySeconds` instead delays genuine failure detection forever.

## Selecting containers where livenessProbe is null

```bash
kubectl get deploy,statefulset,daemonset -A -o json | jq -r '
  .items[] | . as $w | .spec.template.spec.containers[]
  | select(.livenessProbe == null)
  | "\($w.kind) \($w.metadata.namespace)/\($w.metadata.name): \(.name)"'
```

## A missing probe is sometimes right

A batch worker that exits on failure already has the behaviour a liveness probe would provide.
Adding one there is ceremony. This finding is worth reviewing per workload rather than applying
across the board.
