How to get a shell in a Kubernetes Pod

May 10, 2022 by 

Idowu Oselumhe Ilekura

Access Container Shell

Containers are used for packaging software and all its dependencies before deployment.

Before the era of containers, software developers had to deal with compatibility issues during deployment. These could occur when software functions properly during the development phase but fails to function due to dependency issues in the production environment. With containers, however, all the software dependencies used for development can be shipped and used in the production environment.

After building your container image and running an instance of it, you might need to access the container for debugging or to try a hot fix, which will require you to access the container environment. To interact with any running container, you need to get into its shell to perform any task.

This article will show you how to get a shell into a running Docker container or Kubernetes pod. It will also help you understand the importance of doing so and how to use flags to achieve your task.

Reasons to get into running container shells

Here are some of the noteworthy reasons you might need to get into a running container shell:

  • To debug your applications in development: If you encounter errors while running your application inside a running container, you can use a container shell to debug your application instead of rebuilding and redeploying the application container image.

  • To run commands inside your application container: Your application might be programmed to download files from a server. To confirm the length of the files that have been downloaded, you might need to run the wc -l filename command which is used to get the number of lines of any file. The wc -l command can only be run in the container shell.

  • To investigate the internal state of the running container: Your running container might be broken due to some running processes that are taking too much processing power. To check the applications that are running inside your container, you will need to use the ps aux command, which needs to be run in the container shell.

Getting into a running Docker container shell

Docker helps developers containerize their applications with all their dependencies. Its containers are widely used for local deployment and production deployment.

For this guide, you will run a Docker container that has a simple Python application. If you don’t already have Docker installed, follow these tutorials to learn how to install it on Linux, macOS, and Windows.

Cloning the sample GitHub application repository

The sample application that will run inside the container was built with Flask, a simple web development framework. The application has two endpoints: a GET endpoint that will return a greeting, and a GET endpoint that downloads a sample CSV file and stores it.

For this guide, you’ll need to clone the application with the Dockerfile from this GitHub repository. To clone the repository, run the command below:

 git clone https://github.com/gravitational/devrel_container_guide.git

Next, change your directory into the cloned folder and type ls to check its contents.

Building the Docker container image and running the container

The next step is to build the Docker image for the application. In the same directory as your cloned application and Dockerfile, run the docker build command:

# -t is to tag, . is to specify the current directory
docker build -t demo-image .

To run the Docker container image, use the command below:

docker run demo-image 

You should see something similar to the following in your terminal:

Docker Run

Visit the URL shown in your terminal to see a Flask welcome page with a hello world output, showing that the application inside the container is working.

To test the second endpoint, append /download to the URL, ie http://172.17.0.2:5000/download. Even though you will see a web page telling you the file download is done, let's verify the file was actually downloaded.

If you look at the example code under demo.py, the command that is executed when the download endpoint is hit is: wget https://gist.githubusercontent.com/benarent/524f1745e49c0b416e4487bb85063fec/raw/80a537d4d1efdcef31443801aacc891a446f2bdd/SampleCSVFile_119kb.csv -O sample.csv. If you take a closer look at your terminal, you will find a 404 error stating that the wget command is not found. This means there’s a possibility the wget command was not installed in the Docker container. Perfect, a chance to test out our container debugging skills! Let's get into the container environment to confirm our hypothesis about wget.

Getting into the Docker container

To get into an interactive Docker container environment to check whether the wget command is installed there, you’ll use a command in the format of

docker exec -it container_name|container_id shellname

The exec command, with -t flag is used to allocate a pseudo-TTY connected to the standard container input, and the -i flag is used to create an interactive shell in the container. The -t flag binds an interactive terminal to the standard input of the Docker container, giving you a terminal for typing input commands that are routed to the standard input of the container by the -i flag. On Linux, TTY helps users interact with the system through the terminal. The terminal on Linux interacts with a virtual TTY, also known as a pseudo-TTY.

With docker exec -it container_name|container_id bash, Docker will execute a command that binds an interactive bash terminal to your Docker container. In order to get the id of the container running our demo image simply open a new terminal and run docker ps -a. This should show you a list of all the currently running containers. Look for our container named demo-image.

Once you have the container id, type docker exec -it your_container_id bash. After executing the command, you will see something similar to the following, indicating that you are inside the container's working directory (app):

Terminal

Now that you are inside the container shell, you can install the wget command with apt update && apt install wget. Then, exit the container shell by typing exit. Once again, using your web browser visit the download endpoint at http://172.17.0.2:5000/download. You will see an output similar to the following, which confirms that the file was downloaded:

Docker download info

You might now want to check the file’s length. To do so, you will need to move back into the shell of the container using the previous command, docker exec -it your_container_id bash.

When inside the Docker container, type ls to check the files in the working directory. You will notice that there is now a sample.csv file, which is the file that was downloaded. To check the length of the file, run cat sample.csv. You’ll see that the file has ten lines.

Getting a shell into a Kubernetes pod

Kubernetes is a container orchestration platform for managing containers automatically. Kubernetes works with pods, which can be likened to houses with containers running inside them.

To get into a shell of a pod running on Kubernetes, you’ll first deploy the previously built demo-image container image on Kubernetes and then move into a shell of the pod running a container.

Deploying a container image on Kubernetes

To deploy your previously built Docker image on Kubernetes, you need to have minikube and kubectl installed.

Then, you need to define a deployment template to specify details about the container. The content below is a template for creating the demo-image pod. Save it in a file with the name demopod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: demoapp
  labels:
    name: demoapp
spec:
  containers:
  - name: demoimage
    image: idowuilekura/teleport_demo
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
    ports:
      - containerPort: 5000

Create the pod by running this command in the same directory:

kubectl create -f demopod.yaml

To get the status of the pod, run the kubectl get pods command. You should see the something like this in your terminal, showing that the pod is running:

NAME      READY   STATUS    RESTARTS   AGE
demoapp   1/1     Running   0          42s

Getting into a shell of a container running inside a pod

You now have a new container running inside the Kubernetes pod. However, since Kubernetes deployed a new container, the changes made to the Docker container in the previous steps aren’t available again. You will need to install the wget command inside the new container image.

To get into a shell of a container running on Kubernetes, you will use the command kubectl exec -it nameofpod terminal_name. It is similar to the command that you ran for Docker containers. You can also use kubectl exec --stdin --tty nameofpod -- name_of_terminal, which will bind a pseudo-TTY and route any command in the terminal to the standard input of the container.

Next, run the command kubectl exec --stdin --tty demoapp -- bash to move into the container image.

You can use the ls command to check the contents of the files in your Docker container, which will show the demo.py file. Install the wget command with apt update && apt install wget.

You can also explore the container environment further if you wish to.

Securing your Kubernetes containers against unwanted access

Moving into the shell of a container on Kubernetes is useful for debugging and other activities, but you don't want everyone to have access to a container shell. It can lead to disastrous results, such as your application being stopped and tampered with.

Setting up role-based access in your environment is a good way to disable this functionality. Role-based access control (RBAC) can help limit how external users interact with your containers. To learn more about RBAC and how to implement it, you can check out this tutorial.

Monitoring access to Kubernetes shells with Teleport

It’s good practice to monitor access to your container shell and the activities users are performing. Teleport is one of the tools that can help you do so. It is an identity-aware, multiprotocol access proxy for accessing Kubernetes clusters easily and securely. Teleport consolidates connectivity, authentication, authorization, and auditing of Kubernetes clusters into a single platform, which helps to improve security and agility.

Teleport issues users with short-lived kubeconfigs and certificates using single sign-on (SSO), and switches between clusters without logging in twice. Admins can use roles to implement policies, and organizations can achieve compliance by capturing kubectl activities.

If you are interested in learning about using Teleport for Kubernetes access, you can check out this tutorial from Teleport.

Conclusion

This article showed the importance of getting into the shell of a running Docker container or Kubernetes pod and how to do it. It also touched on the importance of restricting access with RBAC in Kubernetes and how to know who is accessing your cluster with Teleport.

Teleport offers an improved and streamlined Kubernetes experience for securely accessing Kubernetes clusters remotely and getting into the shells of containers and pods. It lets you easily view the status of your Kubernetes cluster. To learn more about Teleport for Kubernetes access, check out this resource.

Try Teleport today

In the cloud, self-hosted, or open source
Get StartedView developer docs