If you’re encountering the following error:
job *** failed: BackoffLimitExceeded
pod *** CrashLoopBackOff
You might be facing a CrashLoopBackOff caused by incorrect use of the & operator in your pod command .
The Problem:
In shell scripting, using &
allows a process to run in the background:
/app run -c config & sleep 300
However, in k8s pod container, if you define the command in an array form, like this:
apiVersion: v1
kind: Pod
metadata:
name: ubuntu
labels:
app: ubuntu
spec:
containers:
- image: ubuntu
command:
- date
- '&'
- "sleep"
- "604800"
You might expect date to run in the background. But Kubernetes does not automatically interpret these as shell commands , so:
-
- The
&
is passed literally to your application as an argument .
- The
-
- The container exits with an invalid argument error or crashes.
-
- The pod enters CrashLoopBackOff, blocking your application.
The Cause
In Kubernetes:
- Array-form command: […] skips the shell layer entirely .
- Shell operators (&, &&, |) are treated as plain arguments, unless you explicitly tell Kubernetes to use a shell.
- This means background operators like & won’t work unless explicitly inside a shell .
The Fix
Update your command to use a shell explicitly, like:
command: ["/bin/sh", "-c", "/app run -c config.yaml & sleep 604800"]
This makes sure:
- The command is interpreted by the shell.
- The
&
runs your app in the background. - The sleep 604800 keeps the container alive temporarily.
For Kubernetes Job,
You can use activeDeadlineSeconds
for job timeouts.
Example using activeDeadlineSeconds
:
apiVersion: batch/v1
kind: Job
metadata:
name: timed-job
spec:
activeDeadlineSeconds: 15 # Terminate pod after 15s if the pod has not completed running.
template:
spec:
containers:
- name: example
image: busybox
command: ["sh", "-c", "sleep 10 & wait"] # Simulate a long-running job. Set to > 15s to see the job fail
restartPolicy: Never