Kubernetes Pods 101

·

7 min read

Introduction

A pod is the smallest, most basic deployable object in Kubernetes. It represents an instance of a process running in a Kubernetes cluster. It is also referred to as the smallest unit of Deployment in Kubernetes.

In this article, You will learn about Kubernetes Pods, Use Cases, Lifecycle, and a simple example of using a Pod

Prerequisites

What is a Pod

Pod

A pod usually contains one or more containers that share network and storage resources as well as a specification on how to run the containers. A pod can be made up of single or multi-containers. In either case, the contents of the pod are always co-scheduled and co-located. E.g Let's say you have a multi-container pod i.e Two containers in your pod - One for the actual application and the other one for logging. If the container for application needs to access the logging container - It can just call the logging container directly because it is local to it. Locating your containers in a pod eliminates extra communication setup because they are co-located, so everything is local and they share all the resources.

Pod Types

  • Single Container Pod - Single container pods are the most common use cases as they are made up of a single container in the Pod. The container is usually the packaged application. In most cases, Kubernetes does not manage containers directly. Kubernetes manages objects and Pod is the smallest unit of Deployment in Kubernetes
  • Multi Container Pod - multi-container pod is usually made up of multiple containers as the name reads. There is the main container and, there is the supporting container. This deployment pattern is always referred to as the Side Car Pattern. The other container is usually there to support the main container. E.g In a Service Mesh, proxies are injected into each pod and they help route traffic from a particular service to different services based on the configurations set on the Service Graph(a map containing the rules that determine which service communicate to another service via the proxy) in Istio

Pod Lifecycle

A Kubernetes Pod usually goes through several phases or Lifecycle as you may call it. The state of the Pod determines where the pod will be in its lifecycle as this is always changing. A pod can be in several phases

  • Pending - A pod is Pending when it has been accepted by the Kubernetes Cluster but one or more of its containers is yet to run. This can include time spent downloading the container image from the registry and the time taken to schedule pod on a node
  • Running - A pod is Running when it has been bound to a node, and all the containers are already created. At least one container is still running or is in the process of starting or restarting.
  • Succeeded - A pod is in the Succeeded state when all containers have successfully terminated in success and not will be restarted
  • Failed - A pod is in the Failed state when all the containers in the Pod are terminated, with at least one container failing i.e the container either exited with non-zero status or was terminated by the system.
  • Unknown - A pod is in the Unknown state when the state of the Pod could not be obtained

NB: Sometimes you can see the status of a Pod as Terminating, this happens when the Pod is being deleted which usually has a term to terminate gracefully. The default is 30s. However, the Terminating state is not part of a Pod Lifecycle.

Pods In Practice

In this section, You will understand the basic structure of a Pod Template. The template is usually written in YAML.

Let's go over a simple pod manifest, then we’ll look at how to work with it.

The manifest (YAML) We will break the manifest down into four parts:

  • apiVersion – Version of the Kubernetes API you’re using
  • kind – Kind of object you want to create. There are several kinds of Object i.e Pod, Deployment, StatefulSet, etc
  • metadata – Information that uniquely identifies the object, such as name or namespace.
  • spec – Specified configuration of our pod, for example, image name, container name, volumes, etc.

The apiVersion, kind, metadata, and spec are required fields that are also applicable to other Kubernetes objects. It is also important to mention that the spec part of the template varies across objects.

Single Container Pod

Create a file first-pod.yaml and add this

apiVersion: v1
kind: Pod
metadata:
  name: my-first-pod
  labels:
    app: myapp
spec:
  containers:
  - name: nginx-container
    image: nginx

This is an example of a Pod. The name of the pod is my-first-pod and the pod contains a single container i.e nginx. You can also see that the container under the spec section is an array. This means you can have more than one container.

Now deploy the pod to your local cluster. To do that run this command

kubectl apply -f first-pod.yaml

The kubectl is the command-line interface(CLI) that allows your run commands against the Kubernetes cluster. The command above should create the pod in the default namespace on the cluster

Then run the command below to list the available pods

kubectl get pods

The pod should be running now and it should output something similar to this image.png

Multi Container Pods

multi-container pods are very useful for deploying more than a single pod. These pods are usually co-located, co-managed, and share volume together.

Creating a Pod that runs two Containers

muti-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod
spec:
  restartPolicy: Never
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:

  - name: nginx-container
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html

  - name: debian-container
    image: debian
    volumeMounts:
    - name: shared-data
      mountPath: /pod-data
    command: ["/bin/sh"]
    args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]

In the YAML file above, The pod has two containers, one called nginx-container and the other called debian-container. Both containers use a volume called shared-data and the volume is mounted in a different location in each container. i.e In the nginx-container which uses an nginx image, the volume is mounted at /usr/share/nginx/html. For the debian-container which also makes use of the debian image, the volume is mounted at /pod-data.

The mount paths can be different, It doesn't matter since they share the same volume. The second container writes a message into /pod-data/index.html and then exits. This becomes available to the first container mount path since they share the same volume.

To apply the YAML definition, run the command below

kubectl apply -f multi-pod.yaml

This will apply the definition to the current default namespace. The second container terminates immediately after writing to the specified path. To view the status of both containers you can run

kubectl get pod multi-container-pod -o=yaml

This will output the details of the container as well as the status of each one. To view the statuses, scroll to the containerStatutes section, you should see the status of both containers. The -o flag is used to specify the format of the output

statuses.png

From the output above, you can see the debian-container was terminated while the nginx-container is still running, which is expected.

To view the written text in the nginx-container you need to access the container first. To access the nginx-container run

kubectl exec -it multi-container-pod -c nginx-container -- /bin/bash

The command above will login into the container in interactive mode. Because it's a multi-container pod the -c flag is used to specify the name of the container. The /bin/bash is for specifying the shell to use.

Once you have access to the container - You can run

root@multi-container-pod:/# curl localhost

The output shows that nginx serves a web page written by the debian container

Hello from the debian container

Conclusion

While you might not necessarily use a pod alone to deploy your next application, Understanding how they work is very important. They are the building block of most deployments. Typically you would use a Kubernetes Deployment to deploy your application. Deployment is another type of Kubernetes object. They are more robust and allow you to define more configurations like how many instances(replicas) of your application you want to be running, rolling updates, and other interesting features

In this article, you have learned what a Kubernetes Pod is, The different types, Lifecycle, States, and how to create a multi-container pod sharing the same volume. You can learn more about Kubernetes Pods here