1. Introduction

In Kubernetes, we have the concept of pods as a top-level tier. Further down, a pod can have one or multiple containers running within it. A container usually has commands passed to it. These are part of a YAML configuration file, which can dictate the behavior of the container as a whole. As a result, the container runs the instructions and commands at launch time within a pod.

In this tutorial, we’ll learn about passing multiple commands to a container running under Kubernetes.

2. Single Command Using a YAML Array

To begin with, we can assign a collection of strings to the command field:

$ cat /home/muasif80/k8s/test-job.yml
apiVersion: batch/v1
kind: Job
metadata:
  name: my-job
spec:
  template:
    spec:
      containers:
      - name: my-container
        image: ubuntu:latest
        command: ["echo", "Hello, Kubernetes!"]
      restartPolicy: Never

In other words, we passing a command as an element of a collection within an array of strings. In this case, we’re passing the echo shell command and the string Hello, Kubernetes! as an argument of echo.

This results in the string Hello, Kubernetes! being printed to the terminal when the container is launched within the Kubernetes pod.

To test out the above, we can run kubectl apply in a Kubernetes environment with test-job.yaml as the argument to -f:

$ kubectl apply -f test-job.yaml
job.batch/my-job created

After creating the pod, we can list all pods using the get subcommand:

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-job-677zv 0/1 Completed 0 38s

Further, to check the logs, we can employ the logs subcommand:

$ kubectl logs -f pods/my-job
Hello, Kubernetes!

At this point, we see the expected string in the logs.

3. Multiple Commands Using a Shell Executable

We can also provide multiple commands for the initial container launch. However, to do this, we have to expand on our previous example.

First, we’ll create a new YAML file that uses sh in the command field. Further, the -c argument invokes the shell into a mode that considers the list of arguments after -c as separate commands to run:

 cat /home/muasif80/k8s/test-job2.yml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: ubuntu:latest
    command: ["sh", "-c"]
    args:
    - |
      echo "Command 1"
      echo "Command 2"
      echo "Command 3"

Here, we also employ the args field, where the pipe | operator tells the Kubernetes interpreter to take the following lines as individual arguments to the command in the command field. Thus, we add several commands to run. Of course, we can use other shells with the same effect, as most have a similar switch.

After storing the pod configuration in test-job2.yml, we run it:

$ kubectl apply -f test-job2.yml
pod/my-pod created
$ kubectl logs -f pod/my-pod
Command 1
Command 2
Command 3

As expected, each echo command runs and produces its output, thereby invoking multiple commands at launch.

4. Multiple Commands Using a Script

A shell script consists of multiple commands as a bundle. Since a collection of commands is exactly what we’re after, this approach is systematic and offers several advantages over other methods.

4.1. Benefits of Multiple Commands as Script

Overall, passing multiple commands as a script file to a pod offers many benefits:

  • flexibility: write complex scripts separately and without syntax problems
  • maintainability: modify and maintain a single script
  • reusability: keep the script handy for future use
  • code organization: put everything in one file

In short, using scripts enables us to manage and execute complex commands or logic within the containerized environment more efficiently while keeping our codebase clean and maintainable.

4.2. Code Example

We begin with our code in the test-job3.yml file:

$ cat /home/muasif80/k8s/test-job3.yml
apiVersion: v1
kind: Pod
metadata:
  name: baeldung-test-pod
spec:
  containers:
  - name: baeldung-test-container
    image: ubuntu:latest
    command: ["/bin/bash", "-c"]
    args: ["/bin/baeldung-test-script.sh"]
    volumeMounts:
    - name: baeldung-script-volume
      mountPath: /bin/
      readOnly: true
      subPath: baeldung-test-script.sh
  volumes:
  - name: baeldung-script-volume
    configMap:
      defaultMode: 0700
      name: baeldung-script-configmap
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: baeldung-script-configmap
data:
  baeldung-test-script.sh: |
    #!/bin/bash
    echo "Command 1"
    echo "Command 2"
    echo "Command 3"

Now, let’s break down this code:

  • ConfigMap baeldung-script-configmap adds the contents of the script file baeldung-test-script.sh inline
  • the pod specification includes a container baeldung-test-container running the ubuntu-latest image
  • the command field specifies [“/bin/bash”, “-c”] as the shell we use to run the script
  • the args field is set to [“/bin/baeldung-test-script.sh”] to run the script file within the container
  • we mount a volume baeldung-script-volume at the path /bin/baeldung-test-script.sh inside the container

In this case, we just modify baeldung-test-script.sh in ConfigMap according to our needs. Finally, when the container starts within the pod, it executes the script file baeldung-test-script.sh in the shell. Again, we see the output in the logs.

Let’s run our script and verify this output:

$ kubectl apply -f .\test-job3.yml
pod/baeldung-test-pod created
configmap/baeldung-script-configmap created
$ kubectl logs -f pod/baeldung-test-pod
Command 1
Commnad 2
Command 3

Again, we see the same three echo commands running, this time from within the baeldung-test-script.sh script.

5. Conclusion

In this article, we learned that Kubernetes provides various ways to run and manage pods.

Although we can run a simple command when the pod starts, we also have ways to run multiple commands as well. Further, since pods are the smallest deployable units in the Kubernetes ecosystem, passing multiple commands is available to all of these constructs.