LearnDevOpsHands-On Labs
Troubleshooting Matrix/Readiness probe failed: HTTP probe failed with statuscode: 503
KubernetesHigh Severity

Readiness probe failed: HTTP probe failed with statuscode: 503

Fix "Readiness probe failed: HTTP probe failed": curl the endpoint inside the Pod, correct the port and path, then raise initialDelaySeconds or timeoutSeconds.

Observed Error Signature / Log Pattern
Readiness probe failed: HTTP probe failed with statuscode: 503

Incident Overview

KubernetesKubernetes

Fix "Readiness probe failed: HTTP probe failed": curl the endpoint inside the Pod, correct the port and path, then raise initialDelaySeconds or timeoutSeconds.

medium fix·6 min read

By Vishvesh Patel·DevOps Engineer·Updated 21 September 2026

BASHDiagnostic / remediation command
Readiness probe failed: HTTP probe failed with statuscode: 503

Readiness probe failed: Get "http://10.244.1.7:8080/healthz": dial tcp 10.244.1.7:8080: connect: connection refused

Liveness probe failed: Get "http://10.244.1.7:8080/healthz": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

Do this first3 steps

Run these in order. Each one tells you what its output means before you change anything.

• Read the probe failure and the Pod's ready count

READY 0/1 with a readiness failure means the Pod is running but excluded from its Service. A liveness failure instead means the kubelet is restarting the container, which you will see in RESTARTS climbing.

• Call the probe endpoint from inside the Pod

A 200 here with a failing probe means the probe is misconfigured, usually the wrong port or path. A non-200 or a refused connection means the application really is not ready and the probe is doing its job.

• Check the port the container actually listens on

Compare the hex port against the probe's port. A probe pointed at a port nothing is bound to fails with "connection refused" rather than an HTTP status, which is the clearest signal of a configuration mistake.

A failing readiness probe does not restart anything. It removes the Pod from the Endpoints of every Service that selects it, so traffic stops arriving. The Pod stays Running with READY 0/1, which is why this often presents as "the deployment succeeded but the site is down".

A failing liveness probe is louder: the kubelet kills the container and restarts it. Repeatedly, that becomes a CrashLoopBackOff caused entirely by the probe.

Knowing which one you have is the first step.

0/1 with 0 restarts is readiness. Climbing restarts is liveness.

BASHDiagnostic / remediation command
kubectl describe pod my-pod | grep -A10 Events && kubectl get pod my-pod

Read the exact failure

The three messages you will see mean quite different things:

The first is usually honest: your application's own health endpoint is reporting a problem, often a database it cannot reach. The second is usually a configuration mistake. The third is usually a timeout set too tight, or an app that is genuinely hanging.

BASHDiagnostic / remediation command
kubectl describe pod my-pod

Test the endpoint from inside the Pod

This separates "the app is broken" from "the probe is wrong" in one command:

A 200 while the probe fails means the probe is not testing what you think. Compare it against the spec:

Path /health against an app serving /healthz, port 8000 against an app on 8080. Either of those produces a failing probe on a perfectly healthy container.

If the container has no curl, use wget -qO-, or a shell redirect as a last resort:

BASHDiagnostic / remediation command
kubectl exec my-pod -- curl -sS -o /dev/null -w '%{http_code}\n' \
  http://localhost:8080/healthz

Fix 1: The probe points at the wrong port or path

The most common cause, and worth checking before anything else. Note that a probe's port can name a container port rather than a number, which is more robust:

Now renaming the port in one place cannot desynchronise the probe.

BASHDiagnostic / remediation command
ports:
  - name: http
    containerPort: 8080
readinessProbe:
  httpGet:
    path: /healthz
    port: http

Fix 2: The app starts slower than the probe allows

A JVM or a service that warms a cache can take a minute. With initialDelaySeconds: 3 the liveness probe starts killing it before it has ever finished starting, and it never comes up. The restart count climbs and the logs show the app beginning to boot over and over.

The right answer is a startup probe, not a larger initialDelaySeconds:

Liveness and readiness are both suspended until the startup probe passes once. You get a long grace period at boot and a tight check afterwards, instead of choosing between them.

Inflating initialDelaySeconds instead gives you a slow reaction to real failures forever, in exchange for surviving a slow boot once.

BASHDiagnostic / remediation command
startupProbe:
  httpGet:
    path: /healthz
    port: http
  failureThreshold: 30
  periodSeconds: 10          # allows up to 300s to start

livenessProbe:
  httpGet:
    path: /healthz
    port: http
  periodSeconds: 10
  failureThreshold: 3        # once started, react within ~30s

Fix 3: Timeout too tight

timeoutSeconds defaults to 1 second. A health endpoint that checks a database can easily exceed that under load, and then the probe fails for every replica at once, which takes the whole Service out precisely when it is busiest.

This is a genuinely common cause of self-inflicted outages under load. If your probe does real work, give it room.

BASHDiagnostic / remediation command
readinessProbe:
  httpGet:
    path: /healthz
    port: http
  timeoutSeconds: 5
  periodSeconds: 10
  failureThreshold: 3

Liveness and readiness should not be the same endpoint

Pointing both at one endpoint that checks the database creates a failure mode where a slow database restarts every one of your Pods, which does nothing to fix the database and removes whatever capacity was still serving cached responses.

A reasonable split:

/livez returns 200 unless the process is broken. /readyz can return 503 while the database is unreachable, which drains traffic without restarting anything.

BASHDiagnostic / remediation command
livenessProbe:
  httpGet: { path: /livez, port: http }
readinessProbe:
  httpGet: { path: /readyz, port: http }

The 503 that is telling the truth

If the endpoint really returns 503, read the application logs rather than tuning the probe:

Frameworks with built-in health endpoints, Spring Boot Actuator among them, aggregate dependency checks and return 503 when any is down. The probe is working correctly; something it depends on is not.

BASHDiagnostic / remediation command
kubectl logs my-pod --tail=50

A checklist

Frequently Asked Questions

What is the difference between a readiness and a liveness probe failure?

A failing readiness probe removes the Pod from the Endpoints of its Services, so traffic stops reaching it, but nothing is restarted. The Pod sits as Running with READY 0/1. A failing liveness probe makes the kubelet kill and restart the container, so you see the restart count climbing and, eventually, CrashLoopBackOff. Readiness answers "can this instance serve a request right now"; liveness answers "is this process wedged and in need of a restart".

Why does the probe fail when curling the endpoint works?

Because the probe is usually testing something slightly different. Compare the probe spec against what you curled: a path of /health against an app serving /healthz, or port 8000 against an app on 8080, both produce a failing probe on a healthy container. The other common cause is an application bound to 127.0.0.1 rather than 0.0.0.0: curling from inside the Pod as localhost works, while the kubelet probing the Pod IP gets a refused connection.

How do I fix a probe that kills my app before it finishes starting?

Add a startupProbe rather than increasing initialDelaySeconds. Liveness and readiness are both suspended until the startup probe succeeds once, so you can allow several minutes for boot with a high failureThreshold while keeping a tight failureThreshold on liveness afterwards. Raising initialDelaySeconds instead buys the same grace period at boot but permanently slows how quickly Kubernetes reacts to a genuine failure later.

What does "context deadline exceeded" mean on a probe?

The kubelet opened the connection and the application did not respond within timeoutSeconds, which defaults to just 1 second. A health endpoint that touches a database or another service can easily exceed that under load. The dangerous part is that it tends to fail for every replica simultaneously, taking the whole Service out exactly when it is busiest. If your health check does real work, set timeoutSeconds to something realistic such as 5, and consider making the readiness check cheaper.

Should liveness and readiness use the same endpoint?

No. If both point at an endpoint that checks the database, a slow database restarts every Pod you have, which does not help the database and destroys whatever capacity was still serving. Keep liveness cheap and dependency-free, so it only fails when the process itself is wedged, and let readiness check dependencies so that an unhealthy instance is drained of traffic without being killed. Two endpoints, commonly /livez and /readyz, are worth the small amount of extra code.

Reference and practice

Learn the underlying concept

Other Kubernetes errors

Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.

Get notified about new tutorials and features.

• Roadmaps

• Interview Prep

• Certifications

• Company

© 2026 DevOpsLesson. All rights reserved.

Need to practice this scenario?

Simulate this error condition and practice recovery commands safely in our in-browser terminal.

Open Kubernetes Sandbox