Pods
Get introduced to Pods in Kubernetes.
We'll cover the following
The atomic unit of scheduling in the VMware world is the virtual machine (VM). In the Docker world, it’s the container. In Kubernetes, it’s the Pod.
Yes, Kubernetes runs containers, VMs, Wasm apps, and more. But they all need to be wrapped in Pods.
Pods and containers
The simplest configurations run a single container per Pod, which is why we sometimes use the terms Pod and container interchangeably. However, there are powerful use cases for multi-container Pods, including:
Service meshes
Helper services that initialize app environments
Apps with tightly coupled helper functions such as log scrapers
The following figure shows a multi-container Pod with a main application container and a service mesh sidecar. Sidecar is jargon for a helper container that runs in the same Pod as the main app container and provides services to it. In this figure, the service mesh sidecar encrypts network traffic coming in and out of the main app container and provides telemetry.
Multi-container Pods also help us implement the single responsibility principle where every container performs a single simple task. In the above figure, the main app container might be serving a message queue or some other core application feature. Instead of adding the encryption and telemetry logic into the main app, we keep the app simple and implement it in the service mesh container running alongside it in the same Pod.
Pod anatomy
Each Pod is a shared execution environment for one or more containers. The execution environment includes a network stack, volumes, shared memory, and more.
Containers in a single-container Pod have the execution environment to themselves, whereas containers in a multi-container Pod share it.
As an example, the following figure shows a multi-container Pod with both containers sharing the Pods IP address. The main application container is accessible outside the Pod on 10.0.10.15:8080
, and the sidecar is accessible on 10.0.10.15:5005
. If they need to communicate with each other, container-to-container within the Pod, they can use the Pod’s localhost
interface.
We should choose a multi-container Pod when our application has tightly coupled components needing to share resources such as memory or storage. In most other cases, we should use single-container Pods and loosely couple them over the network.
Pod scheduling
All containers in a Pod are always scheduled to the same node. This is because Pods are a shared execution environment, and we can’t easily share memory, networking, and volumes across nodes.
Starting a Pod is also an atomic operation. This means Kubernetes only ever marks a Pod as running when all its containers are started. For example, if a Pod has two containers and only one is started, the Pod is not ready.
Pods as the unit of scaling
Pods are the minimum unit of scheduling in Kubernetes. As such, scaling an application up adds more Pods, and scaling it down deletes Pods. We do not scale by adding more containers to existing Pods. The following figure shows how to scale the web-fe microservice using Pods as the unit of scaling.
Pod lifecycle
Pods are mortal — they’re created, they live, and they die. Anytime one dies, Kubernetes replaces it with a new one. Even though the new one looks, smells, and feels the same as the old one, it’s always a shiny new one with a new ID and new IP.
This forces us to design applications to be loosely coupled and immune to individual Pod failures.
Pod immutability
Pods are immutable. This means we never change them once they’re running.
For example, if we need to change or update a Pod, we should always replace it with a new one running the updates. We should never log on to a Pod and change it. This means any time we talk about “updating Pods”, we always mean deleting the old one and replacing it with a new one. This can be a huge mindset change for some of us, but it fits nicely with modern tools and GitOps-style workflows.