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:latest
4. 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
v1
6 - 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 themetadata.name
, although I use the same value) - I say that my container should use the image
nginx:latest
4 - 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 image
s 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.
-
First and foremost the official documentation at https://kubernetes.io/docs/concepts/workloads/pods/ ↩
-
Definition found at https://www.merriam-webster.com/dictionary/pod on 2022-12-12 ↩
-
Technically the containers inside of the pods are the running instances of your application ↩
-
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 ↩ -
To make every command a lot shorter there is a custom of creating an alias for
kubectl
withalias k=kubectl
, in that case thekubectl get pods
command can be shortened tok get po
. To make things even simpler you could create additional aliases, for instancealias kgp="kubectl get pods"
↩ -
The full definition of this API can be found at https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/ ↩
Top comments (0)