K8s imperative commands. Shell or not shell?
Francesco Vannini
Posted on July 29, 2024
--command -- sleep 5000
vs
--command -- sh -c 'sleep 5000'
When spinning up a new pod you can add a command to be run via the imperative form but also in the declarative yaml.
I've seen the two forms above often used interchangeably but there is a slight difference.
This is how they get translated in the declarative form:
First
spec:
containers:
- command:
- sleep
- 5000
and second
spec:
containers:
- command:
- sh
- -c
- sleep 5000
Explanation
The first runs the sleep command directly, while the second command uses a shell to run sleep.
The difference really is then that the first one can only just run that one command whereas the second, despite a small overhead from the shell, could be used to run more than just one command i.e. kubectl run busybox --image=busybox --command -- sh -c 'echo "I'm going to bed"; sleep 5000'
Having said that in some cases and under certain circumstances running kubectl exec busybox -- ps -ef
will not show a shell running for our second type of command.
This is due to the way "exec" behaves in shells. If the command is simple, like the sleep we use in this example, the shell will be replaced directly with the command itself.
You'll then get
PID USER TIME COMMAND
1 root 0:00 sleep 5000
30 root 0:00 ps -ef
In both cases.
Tip: Don't forget that if you want to generate a yaml file for a command like the one above you have to add --dry-run=client -o=yaml before the -- which always need to be the last in an imperative command:
kubectl run busybox --image=busybox --dry-run=client -o=yaml --command -- sh -c 'echo "I'm going to bed"; sleep 5000' > pod.yaml
Interestingly also at a declarative level all of the following are equivalent:
spec:
containers:
- name: ubuntu
image: ubuntu
command: [ "sleep", "5000" ]
spec:
containers:
- name: ubuntu
image: ubuntu
command:
- "sleep"
- "5000"
spec:
containers:
- name: ubuntu
image: ubuntu
command: [ "sleep" ]
args: [ "5000" ]
spec:
containers:
- name: ubuntu
image: ubuntu
command:
- sh
- -c
- sleep 5000
spec:
containers:
- name: ubuntu
image: ubuntu
command: ["sh", "-c"]
args: ["sleep 5000"]
Conclusion
When running a pod that requires a command either using the imperative or declarative forms the choice of syntax mostly boils down to whether or not the command to run is one or more.
Read more at Define a Command and Arguments for a Container
Posted on July 29, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.