How to fix Exit Code 0 in Kubernetes

KubernetesBEGINNERMEDIUMUpdated Dec 6, 2025· 203 views

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.

Quick fix

Fixes Exit Code 0

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: 3
  1. Determine if the workload should be long-running or batch
  2. Convert to a Job for one-time tasks
  3. Use init containers for setup tasks
  4. Ensure main container runs a persistent process
kubernetes — error
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: 3
Exit Code 0

What this error means

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.

Typical symptoms

  • Pod shows CrashLoopBackOff but exit code is 0
  • Container logs show successful completion with no errors
  • Last State shows Terminated with Reason: Completed
  • Restart count keeps incrementing for seemingly healthy containers
  • Exponential backoff delays grow (5s, 10s, 20s, 40s...)
  • kubectl logs --previous shows clean execution
  • Deployments never reach Available status

Common causes

  1. Running batch or one-time tasks in a Deployment instead of a Job
  2. Container entrypoint completes without running a long-lived process
  3. Init-style setup scripts without a foreground service to keep container alive
  4. Application designed to exit after completing work rather than wait for signals
  5. Shell script runs commands and exits instead of exec-ing into a service
  6. Missing tail -f, sleep infinity, or service process to keep container running

How to fix "Exit Code 0"

1Determine if the workload should be long-running or batch

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

2Convert to a Job for one-time tasks

If your container should run once and complete, use a Job:

yaml
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: 3

Jobs expect containers to exit. Exit code 0 = success, no restart.

3Use init containers for setup tasks

For setup steps that run before your main application:

yaml
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-running

Init containers run to completion before the main container starts. Exit code 0 from init containers is expected and doesn't cause restarts.

4Ensure main container runs a persistent process

For Deployments, the container must run continuously:

dockerfile
# 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:

bash
#!/bin/bash
./setup.sh
exec python server.py  # exec replaces shell with server process

The last command must be a process that runs until terminated.

5Add a keep-alive for debugging or special cases

If you need the container to stay running without a real service (for debugging):

yaml
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.

6Verify restart policy matches workload type

Deployment defaults to restartPolicy: Always, which cannot be changed. For different policies:

yaml
# Jobs allow OnFailure or Never
restartPolicy: OnFailure  # Restart only if exit code != 0
restartPolicy: Never      # Never restart, even on failure

If you need restartPolicy other than Always for a pod, you cannot use Deployment—use a bare Pod or Job instead.

Advanced notes

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.

Frequently asked questions

What does "Exit Code 0" mean?
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.
How do I fix "Exit Code 0"?
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.
What causes "Exit Code 0"?
Running batch or one-time tasks in a Deployment instead of a Job Container entrypoint completes without running a long-lived process Init-style setup scripts without a foreground service to keep container alive
Is the "Exit Code 0" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading