Exit code 0 means the container completed successfully, but Deployments restart completed containers causing CrashLoopBackOff. Use Jobs for one-time tasks or ensure your container runs a long-lived process.
Exit code 0 indicates successful termination—the container completed its task without errors. However, when running in a Deployment or StatefulSet with the default restartPolicy: Always, Kubernetes restarts completed containers immediately, creating a CrashLoopBackOff loop. This is a semantic mismatch: exit code 0 signals success to the container runtime, but Kubernetes controllers treat any container exit as a condition requiring correction. The container runs, completes successfully, exits, restarts, completes, exits—and eventually enters CrashLoopBackOff as Kubernetes applies exponential backoff delays.
Ask: Should this container run continuously or complete and exit?
Long-running services (web servers, APIs, workers):
- Should use Deployment, StatefulSet, or DaemonSet
- Container must run a persistent foreground process
- Process should handle SIGTERM for graceful shutdown
Batch tasks (scripts, migrations, one-time jobs):
- Should use Job or CronJob resources
- Expected to complete and exit with code 0
- Kubernetes won't restart completed Jobs
If your container should run once and complete, use a Job:
apiVersion: batch/v1
kind: Job
metadata:
name: my-batch-job
spec:
template:
spec:
containers:
- name: worker
image: my-image:latest
command: ["./run-migration.sh"]
restartPolicy: OnFailure # or Never
backoffLimit: 3Jobs expect containers to exit. Exit code 0 = success, no restart.
For setup steps that run before your main application:
spec:
initContainers:
- name: setup
image: my-setup-image
command: ["./init.sh"] # Runs once, exits with 0
containers:
- name: app
image: my-app-image
command: ["./start-server.sh"] # Long-runningInit containers run to completion before the main container starts. Exit code 0 from init containers is expected and doesn't cause restarts.
For Deployments, the container must run continuously:
# Wrong - script completes and exits
CMD ["./setup.sh"]
# Correct - exec into long-running process
CMD ["./setup.sh", "&&", "exec", "python", "server.py"]Or in your shell script:
#!/bin/bash
./setup.sh
exec python server.py # exec replaces shell with server processThe last command must be a process that runs until terminated.
If you need the container to stay running without a real service (for debugging):
command: ["tail", "-f", "/dev/null"]
# or
command: ["sleep", "infinity"]This keeps the container alive so you can exec into it. Not recommended for production—use proper service processes instead.
Deployment defaults to restartPolicy: Always, which cannot be changed. For different policies:
# Jobs allow OnFailure or Never
restartPolicy: OnFailure # Restart only if exit code != 0
restartPolicy: Never # Never restart, even on failureIf you need restartPolicy other than Always for a pod, you cannot use Deployment—use a bare Pod or Job instead.
The CrashLoopBackOff state for exit code 0 is technically correct behavior—Kubernetes is doing what it's designed to do. The "fix" is using the right resource type for your workload.
Common patterns that cause this issue:
- Database migrations that should run once before the app
- Configuration scripts that generate files for the main container
- Health check scripts mistakenly deployed as the main container
- CI/CD pipelines deploying test containers as Deployments
For sidecar containers that should exit after completing their task, consider the new Kubernetes sidecar container feature (beta in 1.28+) or use Jobs with multiple containers.
In GitOps workflows, this often appears when a Job manifest is accidentally converted to a Deployment, or when a Dockerfile CMD is changed from a service to a script.
No subnets found for EKS cluster
How to fix "eks subnet not found" in Kubernetes
unable to compute replica count
How to fix "unable to compute replica count" in Kubernetes HPA
error: context not found
How to fix "error: context not found" in Kubernetes
default backend - 404
How to fix "default backend - 404" in Kubernetes Ingress
serviceaccount cannot list resource
How to fix "serviceaccount cannot list resource" in Kubernetes