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.
- What this error means
- Step 1: See the actual error
- Cause 1: The app is slow to start, so the probe fires too early
- Cause 2: Wrong path, port, or scheme in the probe
- Cause 3: Thresholds are too aggressive
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:
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:
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/healthzIf 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:
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: 10Fix (simpler): if you don't want a startup probe, just raise initialDelaySeconds on the readiness probe:
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30 # wait 30s before the first check
periodSeconds: 10A 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
8080when the app listens on3000 - Hitting
/when the health endpoint is/healthz(and/returns a redirect or 404) - Using
HTTPwhen the container only servesHTTPS
Verify what the app actually exposes:
# Confirm the listening port and health path from inside the pod
kubectl exec -it <pod-name> -- curl -s http://localhost:3000/healthzFix: make the probe match reality exactly:
readinessProbe:
httpGet:
path: /healthz # the real health path
port: 3000 # the real listening port
scheme: HTTP # or HTTPS if the app serves TLS
periodSeconds: 10If 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.
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:
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 againThe 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.
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:
kubectl exec -it <pod-name> -- nc -zv postgres.default.svc.cluster.local 5432Be 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:
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
# 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 message | Likely 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: 404 | Wrong path (Cause 2) |
context deadline exceeded | timeoutSeconds too low, or app slow (Cause 3) |
statuscode: 503 | App 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
- Zero-Downtime Deployments with Rolling Updates and Readiness Probes
- Kubernetes Probes — Liveness, Readiness, Startup — how each probe works and how to configure them correctly
- Fix Kubernetes CrashLoopBackOff: Container Keeps Restarting — when the container is restarting instead of just not-ready
- Kubernetes Debugging Guide — a systematic workflow for diagnosing any pod problem
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
- Configure liveness, readiness and startup probes — every probe field and how failures are counted
- Debug Pods — reading pod status, events and container states
- kubectl reference — command syntax, output formats and selectors
Was this article helpful?
Be the first to rate this article
Related Topics
Found this useful? Share it.


