← Back to DevBytes

Fix Kubernetes 'CrashLoopBackOff' Error: Complete Troubleshooting Guide

Understanding the CrashLoopBackOff State

CrashLoopBackOff is not an error itself β€” it is a Kubernetes pod status that signals a recurring crash pattern. When a container within a pod terminates unexpectedly (non-zero exit code) multiple times in succession, the kubelet applies an exponential backoff delay before restarting it. This prevents endless restart storms and gives you time to investigate. The status appears in kubectl get pods output as CrashLoopBackOff and indicates that Kubernetes is still trying to recover, but the container keeps dying shortly after startup.

Why does this matter? A pod stuck in CrashLoopBackOff is effectively unavailable. It can’t serve traffic, process jobs, or perform its intended function. For production services, this means downtime or degraded user experience. For CI/CD pipelines, it can block deployments. Understanding how to quickly diagnose and resolve the root cause is a core Kubernetes debugging skill that directly impacts reliability and mean time to recovery (MTTR).

Diagnosing the Root Cause: Step-by-Step Inspection

πŸš€ Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

1. Identify the failing pod and check restart counts

Start by listing pods in the affected namespace. Look for the RESTARTS column and the status.

kubectl get pods -n <namespace> --watch
# Example output:
# NAME                          READY   STATUS             RESTARTS   AGE
# my-app-7f8c9d6b5-xq4lz       0/1     CrashLoopBackOff   5          6m

The restart count shows how many times the container has been restarted. A high number confirms a persistent crash pattern.

2. Inspect pod details with kubectl describe

This command reveals critical clues: exit codes, reason for termination, events, and configuration problems.

kubectl describe pod <pod-name> -n <namespace>

Pay close attention to:

3. Retrieve container logs (including previous crashes)

Current logs show what happened during the last (probably brief) run. Previous logs capture output from the crashed instance before restart.

# Current logs
kubectl logs <pod-name> -n <namespace>

# Logs from the previous crashed container instance
kubectl logs <pod-name> -n <namespace> --previous

# If multiple containers, specify one:
kubectl logs <pod-name> -c <container-name> --previous

Search for stack traces, "out of memory", connection refused to a dependency, missing file errors, or configuration parsing failures.

4. Check resource consumption (OOMKilled detection)

If the pod was killed with exit code 137, memory limits were exceeded. Verify with describe:

# Look for "OOMKilled" in the container's last state
kubectl describe pod <pod-name> | grep -A10 "Last State"

You can also check resource metrics (if metrics-server is installed):

kubectl top pod <pod-name> -n <namespace>

5. Examine liveness/startup probe failures

If events mention Liveness probe failed, the health check is incorrectly configured or the app takes too long to become healthy. Check probe definitions in the pod spec:

kubectl get pod <pod-name> -o yaml | grep -A20 "livenessProbe\|startupProbe"

Common Crash Scenarios and Fixes

Scenario 1: Application Fails to Start Due to Misconfiguration

The container exits with code 1 immediately. Logs show errors like missing environment variables, invalid flags, or unreadable config files.

Fix: Correct the configuration source. For ConfigMap/Secret mounted as files, ensure the keys exist and are mounted correctly.

# Example: Mounted config file not found
# Pod spec snippet (incorrect)
volumes:
  - name: app-config
    configMap:
      name: my-app-config   # must exist in namespace
containers:
  - name: app
    volumeMounts:
      - name: app-config
        mountPath: /etc/config   # app expects /etc/config/app.yaml

Verify ConfigMap data:

kubectl get configmap my-app-config -o yaml

If the app requires a specific file name, use items and path in the volume mount to map a specific key.

Scenario 2: Out of Memory (OOMKilled)

The container exceeds its memory limit. Kernel kills it with SIGKILL, exit code 137. Logs may show nothing after the kill.

Fix: Increase memory limits or reduce application memory usage. Analyze memory profile locally or with a sidecar. Update pod resource limits:

# Example resource adjustment
resources:
  limits:
    memory: "512Mi"   # increase from 256Mi
  requests:
    memory: "256Mi"

Apply changes with a new deployment rollout:

kubectl edit deployment <deployment-name> -n <namespace>
# or update the YAML and apply
kubectl apply -f deployment.yaml

Scenario 3: Liveness Probe Misconfigured

The app starts but is slow to become healthy. The liveness probe kicks in too early, kills the container before it's ready, triggering CrashLoopBackOff. Events show Liveness probe failed: ...

Fix: Use a startupProbe to protect the slow-starting application. Keep liveness probe for ongoing health checks but with appropriate initialDelaySeconds or better, rely on startupProbe.

# Recommended probe configuration for slow-starting apps
containers:
  - name: app
    ...
    startupProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
      failureThreshold: 30   # up to 5 min (30*10s) to start
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      periodSeconds: 15
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      periodSeconds: 5
      failureThreshold: 2

After startupProbe succeeds, liveness probe takes over. This prevents premature kills.

Scenario 4: Missing Init Container Dependencies

If an init container fails, the main container never starts. Pod may show Init:CrashLoopBackOff or Init:Error.

Fix: Inspect init container logs:

kubectl logs <pod-name> -c <init-container-name>

Common causes: database not reachable, migration script failing, wrong credentials. Ensure init containers have correct command, environment, and network access.

Scenario 5: Incorrect Command or Entrypoint Override

The container's default command is overridden incorrectly. For example, a shell script path is wrong, or arguments are missing.

# Pod spec with broken command
containers:
  - name: app
    image: my-image
    command: ["/app/start.sh"]   # script not executable or missing
    args: ["--config=/etc/config"]

Fix: Verify the path exists inside the container. Test with an interactive shell:

kubectl run debug --rm -it --image=my-image --command -- /bin/sh
# Inside the container, check /app/start.sh

Then correct the command/args in the pod template.

Scenario 6: Image Pull Issues (Not Always CrashLoopBackOff, but related)

If the image can't be pulled, the pod may show ImagePullBackOff or ErrImagePull, but sometimes a subsequent crash appears. Verify image name, tag, registry credentials.

kubectl describe pod <pod-name> | grep -i "Failed to pull"

Fix: Ensure image exists, tag is correct, and imagePullSecrets are set for private registries.

Preventing CrashLoopBackOff: Best Practices

Advanced Troubleshooting: Interactive Debugging with Ephemeral Containers

When logs and describe don't give enough insight, you can attach an ephemeral debug container to a running (or even crashing) pod. This requires the EphemeralContainers feature gate (enabled by default in recent Kubernetes versions). It lets you run a shell in the pod's context without modifying the original container.

kubectl debug -it <pod-name> --image=busybox --target=<container-name> -n <namespace>

Inside the debug shell, you can inspect files, check network connectivity with nc or curl, and run the application manually with verbose flags. This is extremely useful when the container lacks debugging tools.

Conclusion

CrashLoopBackOff is Kubernetes' way of telling you that a container is repeatedly failing to stay alive. Rather than blindly restarting, Kubernetes forces you to pause and investigate. By systematically examining exit codes, pod events, previous logs, and resource constraints, you can pinpoint the exact cause β€” whether it's an OOM kill, a misconfigured probe, a missing file, or a broken command. Armed with the diagnostic techniques and fixes outlined above, you can reduce downtime, improve application resilience, and build a deeper understanding of how your workloads behave inside a cluster. Remember: every crash is a signal; treat it as a learning opportunity to harden your deployments and apply the best practices that keep your pods running reliably.

πŸš€ Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started β€” $23.99/mo
← Back to all articles