Quick Links

Applications running in Kubernetes are normally long-lived services that you don't need to interact with. Sometimes you might want to manually run a command inside a container though, perhaps for a one-off maintenance operation or to assist a debugging procedure.

In this article we'll show how to run commands and get interactive shell sessions inside Kubernetes containers. This will let you start processes in the container using your local terminal. It's fully integrated with Kubernetes and its Kubectl CLI, so you don't have to pollute your container images with an SSH daemon to enables remote access.

Using Kubectl Exec

kubectl exec executes a command inside a running container. It has the following basic syntax:

$ kubectl exec demo-pod -- demo-command

This will run demo-command inside the first container of the demo-pod Pod. The command is executed with root privileges.

Additional flags are needed to set up an interactive terminal session:

  • --stdin (-i) - Pass your terminal's standard input stream into the container.
  • --tty (-t) - Mark the standard input stream as a TTY, making it interactive.

Here's an example of getting a shell to the first container in a Pod:

$ kubectl exec -it demo-pod -- /bin/sh

Everything after the -- becomes part of the command that's executed inside the container. kubectl exec ignores the container's default entrypoint, instead launching a new process with the command you specify. You shouldn't wrap the command with quotation marks ("/bin/sh") unless you'd use them normally when running the command locally.

Choosing a Different Container

kubectl exec connects to the Pod's default container when no other arguments are given. The default container is the one with the kubectl.kubernetes.io/default-container annotation. This will be the first container in the Pod if you've not manually added the annotation to any other.

Here's a Pod that runs two containers:

apiVersion: v1
    

kind: Pod

metadata:

name: demo-pod

spec:

containers:

- name: app-container

image: nginx:latest

- name: sidecar-container

image: busybox:latest

You can run a command inside the sidecar-container by adding the -c flag to kubectl exec:

$ kubectl exec --it demo-pod -c sidecar-container -- /bin/sh

Waiting for Pods to Be Running

Kubectl will wait a minute for the Pod to be Running if its containers haven't already started when you run the exec command. This timeout value can be changed with the --pod-running-timeout flag. It's useful when you want to run a command straight after creating a new Pod, when it may not have been scheduled to a Node.

$ kubectl exec --pod-running-timeout=5m demo-pod -- demo-command

When Should I Use It?

kubectl exec is best reserved for specialist situations where you need to directly interact with a container's filesystem. You could use it to access logs or caches after a problem or to run an infrequently used housekeeping script that's provided in a container image.

Although kubectl exec lets you run any command, you should avoid dramatically modifying the container's environment. This could cause the container to drift away from the expected state. Containers shouldn't normally require intervention so use of kubectl exec inside production environments usually signals that something's gone wrong.

Don't use this command to install packages or apply updates inside the container. This kind of operation should be handled by building a new container image that includes the changes, then replacing your Kubernetes Pods with ones that run the revised build. Following this principle ensures your changes won't be lost when the Pod restarts and reverts to its container image's filesystem. Keeping your containers immutable also guarantees they can be reliably reproduced from their images, which enhances reliability and ease of debugging.

Summary

Running a one-off command inside a Kubernetes container lets you debug issues, perform maintenance tasks, and inspect the container's filesystem. In each of these situations, you can use kubectl exec to get a connection to a container.

Adding the -it flag combination will forward your terminal's standard input stream as a TTY, providing an interactive shell session. This won't always be necessary depending on the command you want to use: if it only produces output, without requiring any input, you can safely omit the flags.