Skip to main content

Kubernetes-101: Pods, part 1

·2030 words·10 mins
Kubernetes - This article is part of a series.
Part 1: This Article

This is my own story of what a Kubernetes pod is. There are a number of blog posts and documentation pages about this topic out there1. What can I possibly bring to the table with yet another story of what a pod is? Honestly, this might be more for my own sake of learning to document technical topics than it is for the benefit of you, the reader. However, maybe you find something of value in here.

Note that this article is about stand-alone pods. In future articles I will describe controller objects that creates and controls pods for us (for instance the deployment resource).

Also, a big caveat, if you have not used Kubernetes before this article will not teach you about the basics of setting up a cluster. I will discuss these topics in later articles, but for now I assume you either know some basics or know how to find relevant information online on how to do this. What I will say is that if you want a simple experience (and you are using a mac with homebrew and docker installed) you could get a working cluster by running the following commands:

$ brew install minikube
$ brew install kubectl
$ minikube start

Introduction
#

What is a pod anyway? A fitting definition of the word is:2

a number of animals (such as whales) clustered together

In Kubernetes we are not handling a number of animals (such as whales), instead we are handling a number of containers. A container is a running instance of an image (e.g. a Docker image) that contains your application source code and all the dependencies that are required to run your application. Returning to the word pod, and rewriting the previous definition a bit:

a pod is a number of containers (such as Docker containers) clustered together

There we go! I said we are not handling a number of whales in Kubernetes, but it is interesting that Docker uses a whale as its icon.

With the basic definition out of the way, let us dig deeper into what a pod is, what we use pods for, and how we can create a pod in an imperative way and declarative way.

When do we use pods in Kubernetes?
#

The short answer is: all the time! I would argue that the pod is the single most important object in the Kubernetes world. Pods are the running instances of your application code3.

So when you have written your application code and built an image using Docker or some other containerization tool, you can create an instance of your application in the form of a container running inside of a pod in Kubernetes. However, your applications are not the only pods running in your cluster. There are a number of system pods running the whole time, as well as other helper pods you might set up depending on your needs. Basically, pods are the lowest level objects you will be dealing with on a day-to-day basis.

So how many pods do you need? This depends on a number of things. First of all, let’s say you are building some sort of microservice architecture. Each service should have its own pod. Actually, it should probably have a number of identical pods running to allow for pod failures and to handle more traffic. Each pod can contain several containers, but that does not mean you should put all your microservices inside of a single pod. A pod should only contain containers that are intimately related with one another. Microservices should not be intimately related to each other - thus they should not be in the same pod. What is an example of intimately related containers? A common use-case is to have a sidecar container that performs a certain task. For instance, if you are using Prometheus for monitoring you might expose an endpoint on your container that exposes the values of a number of metrics of interest. Then you could run a Prometheus sidecar container that scrapes this endpoint, collects the metric values, and publishes the values to a Prometheus server. Thus your main application container does not need to know anything about how to publish metrics to Prometheus, it just needs to expose the metrics it knows about and the sidecar handles the rest.

In the rest of this article I will go through some examples of how to create pods in your Kubernetes cluster. What I will not show in this article is a better way of creating pods. In reality we do not create individual pod objects in Kubernetes, we would rather create other types of resources that in turn create pods for us. One example of this is the deployment resource. A deployment is an abstraction on top of pods where we can control things like how many copies of our pod we want to create. I will go through deployments in a later article.

Working with Kubernetes pods
#

Imperatively creating a pod in Kubernetes
#

There are two main ways of creating a pod in Kubernetes, an imperative way and a declarative way. We will look at the (preferred) declarative way below. Here we will look at the imperative way.

The main way of interacting with Kubernetes is through the Kubernetes CLI tool called kubectl. Not sure how this name is pronounced, is it kube-control or is it kube-c-t-l? Or something else completely? I digress! Let us run a command with kubectl to create a new pod running an Nginx web-server:

$ kubectl run web --image=nginx:latest

pod/web created

That was easy. I have specified that I want to run a pod with the name web that should run the image nginx:latest4. If I want to list the pod I just created I can run a get command:

$ kubectl get pods

NAME    READY   STATUS    RESTARTS   AGE
web     1/1     Running   0          15s

Already at this point I feel that it is a good idea to talk a bit about shortcuts in the kubectl tool. The command I just ran, kubectl get pods is not a long command, but each type of resource in Kubernetes has a short name when using the kubectl tool5. For pods the short name is po, 50% less characters than in pods! So the last command could be written as:

$ kubectl get po

NAME    READY   STATUS    RESTARTS   AGE
web     1/1     Running   0          15s

Anyway: there we have it, a Running pod! We see that the READY column reports 1/1. This indicates that we have 1 container (out of a total of 1) that is up-and-running. If I want additional details of my pod I can run a describe command:

$ kubectl describe pod web

I won’t include the output of this command here since it is very verbose. Suffice to say that you get a lot of information related to your pod with this command. How can I delete my pod once I am done with it? For that I will use the kubectl delete command:

$ kubectl delete pod web

pod "web" deleted

Declaratively creating a pod in Kubernetes
#

The preferred way to work with pods (or anything else for that matter) in Kubernetes is a declarative approach. In a declarative approach we specify what we want our pod to look like using YAML, and then we give this specification to Kubernetes and Kubernetes makes sure that our pod looks the way we want it to look. It is a very powerful approach.

Without further ado, let us create a very simple Nginx web-server in the form of a pod:

# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: web
spec:
  containers:
    - name: web
      image: nginx:latest
      ports:
        - containerPort: 80

This is the declarative definition of a pod. All YAML documents that describe Kubernetes resources are called manifests. To break it down a bit further:

  • I am using API version v16
  • I say that the kind of resource I want to create is a Pod
  • I give some metadata about my pod, specifically giving it a name that I can refer to later
  • I provide a specification spec of what my pod should contain
  • I say that my pod should contain a single container inside of containers
  • I give my container the name web (this name is different from the metadata.name, although I use the same value)
  • I say that my container should use the image nginx:latest4
  • I specify that my container should be accessible on containerPort 80

Now I need to tell Kubernetes that I want to have this pod created. I do this using kubectl and an apply command:

$ kubectl apply -f pod.yaml

pod/web created

Similarly to the imperative case, I can check the status of my new pod with the kubectl get command:

$ kubectl get po

NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          20s

It worked! If I want to change settings for my pod I can update the YAML file, and then run another kubectl apply command to update it. It is that simple. If I want to delete my pod I can run kubectl delete:

$ kubectl delete -f pod.yaml

pod "web" deleted

Declaratively running several containers in Kubernetes
#

Hang on a moment. In the introduction we defined a pod as a number of containers clustered together. Let us expand on this for a moment. A pod usually only contains a single container, like in the examples we have seen so far. However, it is possible, and not that uncommon, to run more than one container in the same pod. What would be a typical use-case for running two or more containers in the same pod, you ask? From my own experience in Kubernetes the most common use-case is to run a sidecar-container that performs a given task. For instance, the Prometheus use-case I discussed above.

As an example, let us set up a pod with an Nginx container as well as a Prometheus container:

# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: web
spec:
  containers:
    - name: web
      image: nginx:latest
      ports:
        - containerPort: 80
    - name: prometheus
      image: prom/prometheus:latest
      ports:
        - containerPort: 9090

Here we have two containers, one named web and one named prometheus. They run different images and they expose different containerPorts. The two containers can communicate over localhost because they are in the same pod.

We apply the manifest to create the pod:

$ kubectl apply -f pod.yaml

pod/web created

Then we check the status:

$ kubectl get pods

NAME   READY   STATUS    RESTARTS   AGE
web    2/2     Running   0          22s

In this case we see that the READY column says 2/2. This means both of our containers are ready to receive traffic. Actually, the Prometheus container is not really supposed to receive traffic in the way that the Nginx container is. But let us ignore that for now. If we want to delete the pod we run the kubectl delete command:

$ kubectl delete -f pod.yaml

pod "web" deleted

Summary
#

We have learned the basics about what pods are, what they are used for, and how to set them up. Along the way we have learned basic commands with kubectl and a little bit about YAML manifests. There are more parts of a pod that we have not covered yet, but we will gradually learn more in future articles in this series. Most importantly, we will learn how to interact with our pods.


  1. First and foremost the official documentation at https://kubernetes.io/docs/concepts/workloads/pods/ ↩︎

  2. Definition found at https://www.merriam-webster.com/dictionary/pod on 2022-12-12 ↩︎

  3. Technically the containers inside of the pods are the running instances of your application ↩︎

  4. I only have to specify the name of the image (nginx) and the tag (latest) I want to use. If I do not specify anything other than this Kubernetes will default to fetching the image from Docker Hub ↩︎ ↩︎

  5. To make every command a lot shorter there is a custom of creating an alias for kubectl with alias k=kubectl, in that case the kubectl get pods command can be shortened to k get po. To make things even simpler you could create additional aliases, for instance alias kgp="kubectl get pods" ↩︎

  6. The full definition of this API can be found at https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/ ↩︎

Mattias Fjellström
Author
Mattias Fjellström
Cloud architect consultant and an HashiCorp Ambassador
Kubernetes - This article is part of a series.
Part 1: This Article