Kubernetes
9 min readJuly 2, 2026Updated August 19, 2026

Fix Kubernetes 'Readiness probe failed': Pod Running but Not Ready

AJ
Ajeet Yadav
Platform & Cloud Engineer
Fix Kubernetes 'Readiness probe failed': Pod Running but Not Ready

Quick answer

Your pod is Running but shows 0/1 Ready, and describe pod reports 'Readiness probe failed'. That means Kubernetes pulled it out of the Service endpoints, so it gets no traffic. Here's how to find the real cause and fix it.

9 min read · Kubernetes

Fix Kubernetes 'Readiness probe failed': Pod Running but Not Ready

You run kubectl get pods and everything looks alive, but one pod refuses to become ready:

NAME          READY   STATUS    RESTARTS   AGE
api-7d9f8b    0/1     Running   0          3m

The container is up. It isn't crashing. But READY stays at 0/1, and traffic never reaches it. When you check the events, you see Readiness probe failed: .... This post walks through exactly what that means and how to fix each cause.


What this error means

A readiness probe answers one question: is this container ready to serve traffic right now? Kubernetes runs it on a schedule. As long as the probe passes, the pod's IP stays in the Service's endpoint list and receives traffic. The moment it starts failing, Kubernetes marks the pod not ready (0/1) and removes it from the Service endpoints — so no requests are routed to it.

The key difference from a liveness probe: a failing readiness probe does not restart the container. That's why the pod stays Running with zero restarts but never becomes ready. It's just sitting there, healthy from the kubelet's point of view, but quietly excluded from load balancing.

The three probes, in one sentence each:

  • startupProbe — has the app finished booting? Gates the other two until it passes.
  • readinessProbe — can the app serve traffic right now? Controls Service endpoints.
  • livenessProbe — is the app deadlocked and needs a restart? Controls container restarts.

For the full breakdown, see Kubernetes Probes — Liveness, Readiness, Startup.


Step 1: See the actual error

The probe message tells you which kind of failure you're dealing with. Start here:

bash
kubectl describe pod <pod-name>

Look at the Events section:

Warning  Unhealthy  30s (x6 over 2m)  kubelet
  Readiness probe failed: HTTP probe failed with statuscode: 503

# or
  Readiness probe failed: Get "http://10.1.2.3:8080/healthz": dial tcp 10.1.2.3:8080: connect: connection refused

# or
  Readiness probe failed: Get "http://10.1.2.3:8080/healthz": context deadline exceeded (Client.Timeout exceeded)

Each variant points somewhere different:

  • 503 / non-2xx status → the app answered but reports itself not ready
  • connection refused → nothing is listening on that port (yet, or ever)
  • context deadline exceeded → the app didn't respond within timeoutSeconds

Then check the app's own logs and, when in doubt, probe the endpoint from inside the pod:

bash
kubectl logs <pod-name>

# curl the exact path and port the probe uses, from inside the container
kubectl exec -it <pod-name> -- curl -sv http://localhost:8080/healthz

If curl inside the pod fails the same way the probe does, the problem is the app or the probe config — not networking.


Cause 1: The app is slow to start, so the probe fires too early

The most common cause. A JVM app, a Rails boot, or anything that warms a cache can take 30–90 seconds before it serves requests. If your readiness probe starts checking after a few seconds, it fails repeatedly at first. You'll see connection refused early, flipping to success later.

If the pod eventually becomes ready on its own, this is almost certainly your issue.

Fix (better): add a startupProbe. It gives the app a long, generous window to boot, and holds off the readiness and liveness probes until it passes:

yaml
1startupProbe:
2  httpGet:
3    path: /healthz
4    port: 8080
5  failureThreshold: 30    # 30 × 10s = up to 5 minutes to start
6  periodSeconds: 10
7
8readinessProbe:
9  httpGet:
10    path: /healthz
11    port: 8080
12  periodSeconds: 10

Fix (simpler): if you don't want a startup probe, just raise initialDelaySeconds on the readiness probe:

yaml
readinessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 30   # wait 30s before the first check
  periodSeconds: 10

A startupProbe is preferred because it adapts to how long boot actually takes instead of hard-coding a guess.


Cause 2: Wrong path, port, or scheme in the probe

If the probe never succeeds — even after the app is fully up — the probe is pointed at the wrong place. Classic mistakes:

  • Probing port 8080 when the app listens on 3000
  • Hitting / when the health endpoint is /healthz (and / returns a redirect or 404)
  • Using HTTP when the container only serves HTTPS

Verify what the app actually exposes:

bash
# Confirm the listening port and health path from inside the pod
kubectl exec -it <pod-name> -- curl -s http://localhost:3000/healthz

Fix: make the probe match reality exactly:

yaml
readinessProbe:
  httpGet:
    path: /healthz     # the real health path
    port: 3000         # the real listening port
    scheme: HTTP       # or HTTPS if the app serves TLS
  periodSeconds: 10

If you use a named port, make sure the name matches a containerPort in the spec — a typo there produces the same connection refused.


Stuck on this in production?

We debug exactly this kind of issue for platform teams — usually in a single working session.

Talk to us

Cause 3: Thresholds are too aggressive

Sometimes the app is healthy but bursty — a slow GC pause or a brief spike makes one probe check time out, and a tight failureThreshold immediately yanks the pod from the Service. You'll see the pod flap between 0/1 and 1/1.

The four knobs that matter:

yaml
1readinessProbe:
2  httpGet:
3    path: /healthz
4    port: 8080
5  timeoutSeconds: 5       # how long to wait for a response (default 1s — often too short)
6  periodSeconds: 10       # how often to check
7  failureThreshold: 3     # consecutive failures before marking not-ready
8  successThreshold: 1     # consecutive successes to mark ready again

The default timeoutSeconds: 1 is a frequent culprit — a health endpoint that occasionally takes 1.5s will fail intermittently. Bump timeoutSeconds and failureThreshold to give a healthy-but-slow app some slack, without hiding a genuinely broken one.


Cause 4: The app (or a dependency) is genuinely unhealthy

If the probe returns a 503 or other non-2xx, the app is doing its job — it's telling you it isn't ready. Many health endpoints check downstream dependencies (a database, a cache, a message broker) and report 503 when one is unreachable.

What you'll see: Readiness probe failed: HTTP probe failed with statuscode: 503, and the app logs a reason.

bash
kubectl logs <pod-name>
# e.g. "readiness: database connection failed: dial tcp: i/o timeout"

Fix: this isn't a probe problem — fix the underlying dependency. Confirm the database Service resolves and is reachable from the pod:

bash
kubectl exec -it <pod-name> -- nc -zv postgres.default.svc.cluster.local 5432

Be careful chaining hard dependency checks into readiness: if every app marks itself not-ready when a shared database blips, an entire tier drops out of load balancing at once. Keep readiness focused on "can this instance serve traffic."


Cause 5: Probe points at the wrong container in a multi-container pod

In a pod with a sidecar (service mesh proxy, log shipper, etc.), the readiness probe is defined per container. It's easy to put the probe under the wrong container, or aim its port at the sidecar instead of the app — so it checks a port nothing serves on.

Fix: confirm the probe lives on the container that actually serves the health endpoint, and that its port matches that container's containerPort:

bash
kubectl get pod <pod-name> -o jsonpath='{range .spec.containers[*]}{.name}{": "}{.readinessProbe.httpGet.port}{"\n"}{end}'

Move the probe to the right container if it's misplaced. With a service mesh, remember the proxy may intercept traffic — probe localhost so the check bypasses the mesh.


Quick reference

bash
# The commands that solve most readiness-probe failures
kubectl describe pod <name>                              # Events → which failure mode
kubectl logs <name>                                      # what the app says
kubectl exec -it <name> -- curl -sv localhost:<port>/<path>   # reproduce the probe by hand
Probe messageLikely cause
connection refused (early, then clears)App still starting — add a startupProbe (Cause 1)
connection refused (never clears)Wrong port, or app not listening (Cause 2)
statuscode: 404Wrong path (Cause 2)
context deadline exceededtimeoutSeconds too low, or app slow (Cause 3)
statuscode: 503App or a dependency is unhealthy (Cause 4)

Frequently Asked Questions

Why is my pod Running but not Ready?

Because the container process is alive (so the kubelet keeps it Running), but its readiness probe is failing. A failing readiness probe marks the pod 0/1 and removes it from the Service's endpoints, but — unlike a liveness probe — it never restarts the container. So it stays up, healthy-looking, and traffic-less.

Does a failed readiness probe restart the pod?

No. Only a failed liveness probe restarts the container. A failed readiness probe just takes the pod out of the Service endpoints so it receives no traffic. If your pod is restarting, look at the liveness probe or check for CrashLoopBackOff instead.

What's the difference between readiness and liveness probes?

Readiness answers "can this pod serve traffic right now?" and controls Service endpoints. Liveness answers "is this pod broken and in need of a restart?" and controls container restarts. Use readiness to gate traffic during boot or transient dependency issues; use liveness only to recover from unrecoverable states like deadlocks.

Why does traffic stop reaching my pod?

Kubernetes routes Service traffic only to pods listed in the Service's endpoints, and it removes any pod whose readiness probe is failing. Run kubectl get endpoints <service> — if your pod's IP is missing, its readiness probe is failing and that's why it gets no requests.

How do I give a slow-starting app more time to become ready?

Add a startupProbe with a high failureThreshold (for example 30 checks × 10s = five minutes). It holds off the readiness and liveness probes until the app has finished booting, which is cleaner than padding initialDelaySeconds with a hard-coded guess.


See also

Stuck on a pod that won't go ready in production? Talk to us at Coding Protocols — we help teams get their Kubernetes health checks and rollouts right so deploys stop stalling.

Official References

Was this article helpful?

Be the first to rate this article

Related Topics

Kubernetes
Troubleshooting
Readiness Probe
Debugging
DevOps

Found this useful? Share it.

Practice this

Related tools

Read Next