DEV Community

Cover image for K8s imperative commands. Shell or not shell?
Francesco Vannini
Francesco Vannini

Posted on

K8s imperative commands. Shell or not shell?

--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
Enter fullscreen mode Exit fullscreen mode

and second

spec:
 containers:
 - command:
  - sh
  - -c
  - sleep 5000
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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" ]
Enter fullscreen mode Exit fullscreen mode
spec:
  containers:
  - name: ubuntu
    image: ubuntu   
    command:
      - "sleep"
      - "5000"
Enter fullscreen mode Exit fullscreen mode
spec:
  containers:
  - name: ubuntu
    image: ubuntu
    command: [ "sleep" ]
    args: [ "5000" ]
Enter fullscreen mode Exit fullscreen mode
spec:
  containers:
  - name: ubuntu
    image: ubuntu
    command:
    - sh
    - -c
    - sleep 5000
Enter fullscreen mode Exit fullscreen mode
spec:
  containers:
  - name: ubuntu
    image: ubuntu
    command: ["sh", "-c"]
    args: ["sleep 5000"]
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)