Introducing Pods (and other Kubernetes objects)

Eric Gregory
Mirantis
Published in
6 min readJun 17, 2022

One of the biggest challenges for implementing cloud native technologies is learning the fundamentals — especially when you need to fit your learning into a busy schedule. In this series, we’ll break down core cloud native concepts, challenges, and best practices into short, manageable exercises and explainers, so you can learn five minutes at a time.

In the last lesson, we investigated the architecture of a Kubernetes cluster, including the major components of the control plane and worker nodes, as well as common architectural patterns for a cluster. Today, we’ll start to break down the core abstractions that organize activity on the cluster — starting with Pods.

Table of Contents

  1. What is Kubernetes?
  2. Setting Up a Kubernetes Learning Environment
  3. The Architecture of a Kubernetes Cluster
  4. Introducing Pods (and other Kubernetes objects) ← You are here

These lessons assume a basic understanding of containers. If you need to get up to speed on Docker and containerization, download our free ebook, Learn Containers 5 Minutes at a Time. This concise, hands-on primer explains:

- The key concepts underlying containers — and how to use core tools like image registries

- Fundamentals of container networking that are essential for understanding container orchestrators like Kubernetes

- How to deploy containerized apps in single-container and multi-container configurations

What are Kubernetes objects?

Kubernetes defines entities on the cluster as objects. The term functions the same way here as in most computer science contexts: Kubernetes objects are instances of a class with certain attributes, and they give us a model for abstraction. In Kubernetes, we’re using objects to define entities in our cluster — and more specifically, the desired state and status of those entities. Kubernetes is all about intent, and objects are the model we use to express our intent.

So far we’ve been a little vague — what kind of “entities” are we talking about here, and what might we intend for them? Well, let’s have a look. We can use kubectl to retrieve a complete list of abstractions that are manageable through the Kubernetes API. Start Minikube and then enter:

% kubectl api-resources

You should see a list something like this:

NAME                             SHORTNAMES   APIVERSION
bindings v1
componentstatuses cs v1
configmaps cm v1
endpoints ep v1
events ev v1
limitranges limits v1
namespaces ns v1
nodes no v1
persistentvolumeclaims pvc v1
persistentvolumes pv v1
pods po v1
podtemplates v1
replicationcontrollers rc v1
resourcequotas quota v1
secrets v1
serviceaccounts sa v1
services svc v1
mutatingwebhookconfigurations admissionregistration.k8s.io/v1
validatingwebhookconfigurations admissionregistration.k8s.io/v1
customresourcedefinitions crd,crds apiextensions.k8s.io/v1
apiservices apiregistration.k8s.io/v1
controllerrevisions apps/v1
daemonsets ds apps/v1
deployments deploy apps/v1
replicasets rs apps/v1
statefulsets sts apps/v1
tokenreviews authentication.k8s.io/v1
localsubjectaccessreviews authorization.k8s.io/v1
selfsubjectaccessreviews authorization.k8s.io/v1
selfsubjectrulesreviews authorization.k8s.io/v1
subjectaccessreviews authorization.k8s.io/v1
horizontalpodautoscalers hpa autoscaling/v2
cronjobs cj batch/v1
jobs batch/v1
certificatesigningrequests csr certificates.k8s.io/v1
leases coordination.k8s.io/v1
endpointslices discovery.k8s.io/v1
events ev events.k8s.io/v1
flowschemas flowcontrol.apiserver.k8s.io/v1beta2
prioritylevelconfigurations flowcontrol.apiserver.k8s.io/v1beta2
nodes metrics.k8s.io/v1beta1
pods metrics.k8s.io/v1beta1
ingressclasses networking.k8s.io/v1
ingresses ing networking.k8s.io/v1
networkpolicies netpol networking.k8s.io/v1
runtimeclasses node.k8s.io/v1
poddisruptionbudgets pdb policy/v1
podsecuritypolicies psp policy/v1beta1
clusterrolebindings rbac.authorization.k8s.io/v1
clusterroles rbac.authorization.k8s.io/v1
rolebindings rbac.authorization.k8s.io/v1
roles rbac.authorization.k8s.io/v1
priorityclasses pc scheduling.k8s.io/v1
csidrivers storage.k8s.io/v1
csinodes storage.k8s.io/v1
csistoragecapacities storage.k8s.io/v1beta1
storageclasses sc storage.k8s.io/v1
volumeattachments storage.k8s.io/v1

Read through the complete list; some concepts like “nodes’’ should be familiar already. (We’ve removed the NAMESPACED and KIND columns for readability, but those are informative — review them, too!)

Kubernetes uses these abstractions to record our intent for system resources in a way that the API server can use in communicating with other components. A resource might have to do with workloads, services, policies, or another area of the system. These are essentially the classes that Kubernetes objects instantiate, and objects give us a common model for all of these resources.

In this series, we’ll focus on the most essential Kubernetes objects for developers. Let’s start with the elementary particle of Kubernetes: the Pod.

What is a Pod?

We can ask Kubernetes itself. In the terminal, enter:

% kubectl explain pod

You should get the following answer:

KIND:     Pod
VERSION: v1
DESCRIPTION:
Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts.

So what does this mean? What is a Pod? A Pod is a unit of one or more containers that share a network namespace and storage volumes while running on a Kubernetes node. It is also Kubernetes’ most granular unit of scheduling for a containerized workload.

Up until now, we’ve used the general term “workload” to refer to the containerized processes that Kubernetes is orchestrating. As we’ve seen previously, the system assigns these workloads to worker nodes, the physical or virtual machines that are part of the cluster. These are the “hosts” in the definition above. But Kubernetes adds a conceptual layer separating the node from the container, and that’s the Pod.

Each Pod is assigned a unique IP address, so containers within the Pod can communicate with one another over localhost, and Pods can communicate with one another at fixed addresses.

These two ideas — the abstraction of the Pod, and each Pod having its own IP address — are fundamental, defining concepts for Kubernetes. They extend all the way back to the Borg project at Google, and they distinguish Kubernetes from other container orchestrators like Swarm. It is difficult to overstate the importance of the Pod; it contributes to the high scalability of Kubernetes, and it informs many of the networking patterns we will encounter going forward.

We’ve said that a Pod consists of “one or more containers.” The conventional wisdom on containers-per-Pod is that a given Pod should include only one container if possible, and multiple containers only when they are tightly coupled. Sometimes, your Kubernetes configuration may necessitate a multi-container Pod — when using an Istio service mesh, for example, each Pod will include a “sidecar” container in addition to the primary container. But we wouldn’t expect to see more than two or three containers in most Pods. (We’ll talk more about service meshes later, but if you’re ready to dive into the deep end now, you can check out Service Mesh for Mere Mortals.)

Testing the limits

“Sure,” I hear you say, “I understand that we should run no more than a handful of containers per Pod. But I’m a maverick! I want to test the limits. How many containers can we run in a Pod?”

Short answer: There’s no defined limit. As of version 1.23, the Kubernetes docs note that Kubernetes is designed for a maximum of 300,000 total containers. Technically, you could cram all of them into one Pod (assuming you could satisfy the underlying compute and storage requirements). But the docs also tell us that the system is designed for no more than 150,000 Pods, and that ratio is instructive. Operating at the extremities of scale, we would have two containers per Pod.

By separating out the functionality of your containerized services into minimal viable units, you can scale those units — those services or microservices — independently. Say, for example, that you have a Pod representing the core functionality of the auth service on your web app, and you suddenly experience a barrage of sign-ups. The cluster can scale up your auth service as needed without needlessly duplicating other, unrelated elements of the app.

Read the rest of this tutorial on the Mirantis blog.

--

--