Troubleshoot Pod Frequent Restarts in 60 Seconds: OOMKilled vs Misconfigured Health Checks
A practical guide to diagnose Kubernetes pod frequent restarts by distinguishing OOMKilled from liveness probe failures, using kubectl describe, logs, and events, then fixing via memory limit adjustments or probe parameter tuning (initialDelaySeconds, periodSeconds, timeoutSeconds, failureThreshold), while avoiding common pitfalls like confusing liveness/readiness probes or depending on external dependencies for health checks.
A new version deployment caused a data-collector pod to restart 28 times in two hours (roughly every four minutes). The author demonstrates a systematic three-step troubleshooting process.
Step 1: Check Pod State to Identify the Cause
Run kubectl describe pod and examine State and Last State. In the example, Last State shows Reason: OOMKilled and Exit Code: 137. Two key exit codes to remember:
137 : Process received SIGKILL, typically an OOM kill.
143 : Process received SIGTERM, usually a graceful shutdown or liveness probe failure.
Step 2: Examine Events for Health Check Issues
Scroll to the Events section. If you see Liveness probe failed with messages like context deadline exceeded followed by Container failed liveness probe, will be restarted, the restart is due to a misconfigured liveness probe.
Step 3: Inspect Previous Container Logs
Use kubectl logs data-collector-xxx --previous to view logs from the crashed container instance. If this returns nothing, the pod was likely OOM-killed instantly before logs could be flushed to disk.
Resolving OOMKilled (Memory Limit Exceeded)
Immediate mitigation: increase the memory limit in the pod spec.
resources:
limits:
memory: 2Gi
requests:
memory: 512MiRoot causes to investigate:
Memory leaks : unclosed database connections, file streams, or large objects retained indefinitely.
Java heap misconfiguration : -Xmx set higher than the container memory limit.
Traffic spikes : sudden large data loads into memory.
Resolving Liveness Probe Failures
The most common mistake is setting initialDelaySeconds too short. If the application needs 30 seconds to start but the probe begins at 10 seconds, it will fail repeatedly, causing a restart loop. Example corrected configuration:
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 60
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3Key probe parameters and suggested values: initialDelaySeconds — Wait time after startup before first probe. Suggested: 30-60s (match startup time). periodSeconds — Interval between probes. Suggested: 10-30s. timeoutSeconds — Probe timeout threshold. Suggested: 3-5s. failureThreshold — Consecutive failures before restart. Suggested: 3-5.
Critical Reminders
Do not confuse liveness and readiness probes. Liveness failure triggers a restart; readiness failure only removes the pod from service endpoints. Swapping them causes either constant restarts or traffic sent to unhealthy pods.
Liveness probes must not depend on external resources. Using a database connection check as a liveness probe is dangerous: if the database is down, restarting the pod will not help and may create a restart storm.
Handling missing logs after OOM. Java applications often cannot flush logs before SIGKILL. Add JVM option -XX:+ExitOnOutOfMemoryError or use an asynchronous logging framework to ensure logs are written before termination.
Quick Three-Step Diagnosis Cheat Sheet
kubectl describe pod→ check Reason (OOMKilled vs Liveness probe failed). kubectl logs --previous → examine crash logs; if empty, suspect instant OOM. kubectl top pod → observe memory usage relative to limit; if near limit, increase limit or optimize code; if normal, review probe configuration.
Symptom → Root Cause → Action Reference
Symptom: Reason: OOMKilled | Root Cause: Memory limit exceeded | Action: Increase limit / investigate memory leak / optimize code
Symptom: Exit Code: 137 | Root Cause: Process killed by SIGKILL | Action: Same as OOM, investigate memory
Symptom: Liveness probe failed | Root Cause: Health check failing | Action: Increase initialDelaySeconds / verify probe path
Symptom: Slow startup, repeated restarts | Root Cause: initialDelaySeconds too short | Action: Allow sufficient startup wait time
Symptom: logs --previous shows nothing | Root Cause: Instant OOM, no log flush | Action: Configure async logging + OOM JVM flags
Symptom: Liveness and readiness confused | Root Cause: Misconfigured probes | Action: Liveness controls restart, readiness controls traffic
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Engineer Tang's Implementation Study Notes
Old Tang | Pseudo-full-stack tech player: writes code without going bald, manages projects without going crazy, delivers without staying up late. No formal tutorials here, only a "slacking-off" practical manual that cures system pain points. Focuses on Shell, SQL, Java, and delivery, turning complexity into simplicity and making efficiency fun.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
