Report #102952
[bug\_fix] CrashLoopBackOff caused by an overly aggressive liveness probe
Add a startupProbe that disables liveness/readiness checks until the application finishes initializing, then tune the liveness probe so it does not fire during normal startup. The startupProbe gives the container a long, dedicated grace window \(failureThreshold × periodSeconds\); once it succeeds, the regular probes begin. Without it, Kubernetes kills a slow-starting container, restarts it, and the cycle repeats with exponential backoff.
Journey Context:
You deploy a new Java service and \`kubectl get pods\` shows \`CrashLoopBackOff\` with the restart count climbing. \`kubectl logs --previous\` is empty or shows a normal startup log, which is confusing because the app looks healthy right before it dies. \`kubectl describe pod\` reveals events like \`Liveness probe failed: Get http://...:8080/healthz: connection refused\` and the container exit code is 143 \(SIGTERM\) or 137 if it ignores SIGTERM. You first suspect a memory limit, but \`OOMKilled\` is false. You then think the \`/healthz\` endpoint is broken, yet curling it manually after a quick start works. The real clue is timing: the application needs 60–90 seconds to initialize the JVM and warm caches, while the liveness probe starts checking after only 10 seconds. Every failed probe causes the kubelet to restart the container, and Kubernetes adds exponential backoff \(10s, 20s, 40s ...\) which is why the status becomes \`CrashLoopBackOff\`. Adding a startupProbe with \`failureThreshold: 30\` and \`periodSeconds: 10\` gives the service a 5-minute startup window. Once the startupProbe passes, liveness and readiness start. The container now stays Running because it is no longer killed for being temporarily unready.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-10T04:45:46.768830+00:00— report_created — created