13 min read

Kubernetes for students: the essential concepts before you touch a cluster

The Kubernetes mental model you need before your first cluster: declarative desired state, the control plane and worker split, pods versus containers, controllers, Services, and the order in which to learn the rest.

ByAndré Ribeiro· Founder, Obelinf
Kubernetes for students: the essential concepts before you touch a cluster
Kubernetes for students: the essential concepts before you touch a cluster · August 19, 2026
On this page

Most students meet Kubernetes the wrong way. They finish a container tutorial, hear that Kubernetes is how production runs containers, and open the first guide that promises a running cluster, which usually means copying YAML into kubectl and watching numbers appear. The commands work and the model never forms, and a week later a Deployment that will not schedule looks like a bug in someone else’s language. The problem is not that Kubernetes is hard to operate. The problem is that it runs software on a model that is unlike every other way you have run software so far: servers you log into and patch, scripts you rerun when they fail, containers you start by hand. Kubernetes is none of those, and reaching for those familiar metaphors is exactly how beginners get lost.

This guide gives you the model before the syntax: what Kubernetes actually is as a system, how a cluster splits decisions from execution, why pods rather than containers are the unit of work, how controllers turn your files into running software, and how Services give volatile pods a stable name. You will still want a tutorial for command flags, but you will know what every command is doing and why it exists, which is the difference between running a cluster and operating one.

What Kubernetes Actually Does

The reconciliation loop: you declare state, the API server stores it, controllers converge on it Desired state API server Controllers The cluster your YAML describes it stores it in etcd compare with real state converge to match kubectl apply -f state lives in etcd reconciliation loop run, scale, replace the loop never stops: controllers watch and write updates continuously Nothing happens because you ran a YAML file. Everything happens because a controller noticed a gap between what you described and what is true.

Kubernetes is a machine for keeping a declared state true. You describe the software you want running, how many copies, on what ports, and with what configuration, and the cluster brings the real world into line with your description and holds it there. A node dies and the cluster replaces the pods that lived on it. A pod crashes and it restarts until it stops crashing. You ask for eight replicas and the cluster makes eight. Almost everything you will ever do with Kubernetes, including the parts that confuse you, is this one loop wearing different clothes.

From that definition the commands stop being magic. kubectl is not the system, it is a client that talks to the API server, the only door into a cluster. kubectl apply does not run your YAML anywhere, it sends your desired state to the API server, which stores it in etcd so controllers can work against it. kubectl get and kubectl describe are not windows into your app, they are the cluster’s idea of its own state at one moment in time. Keep that anatomy in your head and the long status fields and stuck workloads start to read as one loop reporting its progress.

The shift from imperative to declarative is the hardest part for students, because every tool you have used so far is imperative: do this, then that, check the result. Kubernetes is not. You state what you want and hold out for it, and the controllers chase the moving target until it arrives. When a Deployment shows as in progress, nobody is running a script at that moment. The controllers are simply behind schedule and catching up, which is exactly what the status field is reporting.

The Cluster Is Two Kinds of Machines

A cluster split into a deciding control plane and executing worker nodes, with clients talking only to the API server You: kubectl + YAML Control plane: decides api server etcd scheduler controller manager Worker nodes: execute kubelet container runtime kube-proxy Clients talk only to the control plane. Workers receive assignments and report results, and a single machine cluster hides the split by running both halves at once.

A cluster is a control plane plus a set of worker nodes, and the only conversation you ever have is with the control plane. The control plane decides: the API server accepts your desired state, etcd stores it, the scheduler chooses which node runs each pod, and the controller manager runs the loops that keep reality aligned with your spec. The workers execute: every node runs a kubelet that talks to the API server and starts and restarts the pods assigned to it, backed by a container runtime and kube-proxy for service traffic.

minikube and kind collapse both halves onto one machine, which is a blessing for learning and a trap for understanding, because it hides how little the workers think. In a real cluster the workers never decide anything. They receive assignments and report results, and if the control plane becomes unreachable, a node keeps running what it already has but makes no new decisions. When you read about a control plane outage you are reading about the brain of the cluster, and holding the split in your head is what lets you tell which half is misbehaving when something goes wrong.

Pods, Not Containers

One pod containing two containers that share its IP address and an attached volume Pod: one network namespace, one IP, one set of volumes Container A your app, listening on port 8080 Container B sidecar for logs, proxies, sync shared volume Containers inside a pod share its IP and its volumes, so two services that want the same port cannot share a pod. The classic pod is one main container plus small helpers.

Containers are what you build and move around. Pods are what the cluster runs. Every object you schedule is a pod: a group of one or more containers that share an IP address, a network namespace, and any volumes you attach. The cluster assigns each pod one address, and every container inside answers on that address together, which is why the classic design is one main container plus a small sidecar, and why two containers that want the same port cannot share a pod.

Two habits are worth building on day one. First, think in pods, not containers: a Deployment of three replicas is three pods, each with its own IP, and nothing else is running anywhere. Second, treat pods as disposable. Kubernetes has no console culture and no habit of fixing by hand. When a pod misbehaves you delete it and the controller builds a fresh one from the same spec, which looks wasteful until you realize it is the entire source of Kubernetes resilience.

Controllers Turn a File Into Reality

Deployment drives a ReplicaSet, which supervises pods; a dead pod is replaced by a loop back to the ReplicaSet Deployment ReplicaSet Pods your versioned spec desired replica count the work running 10.244.2.11 10.244.2.12 10.244.2.22 pod pod pod down the ReplicaSet replaces what dies A rollout creates a new ReplicaSet next to the old one. A crash restores the replica count. Both are the same loop converging on what the Deployment declares.

The chain to memorize first is Deployment to ReplicaSet to pods. You declare a Deployment, the Deployment controller creates a ReplicaSet, and the ReplicaSet controller creates and supervises the pods. The Deployment gives you versioned rollouts, so kubectl rollout undo can revert a bad change, and the ReplicaSet holds the desired replica count. When a pod dies, the ReplicaSet controller notices the count is wrong and replaces it. When you bump the image in the Deployment, it rolls out a second ReplicaSet next to the first and steps the old pods down.

The same model explains why your first deployment spends time in odd states. Pending is the scheduler speaking: no node currently has the CPU, memory, or tolerations the pod needs. ImagePullBackOff means the image could not be fetched. CrashLoopBackOff means the container keeps starting and exiting, so the cluster restarts it with a growing pause, and kubectl logs is the tool that tells you why. None of these are random errors. Each is a controller reporting where the gap between what you asked for and what is true is sitting, which is why reading the status field beats guessing.

Services Give Churn a Stable Name

Clients reaching a stable Service that balances across churning backend pods selected by label Clients other pods, load balancers Service stable IP + DNS name 10.96.0.20 svc.ns.svc selector: app=api pod pod pod 10.244.3.11 10.244.3.12 10.244.3.19 replacement, new IP Clients hold one address and the Service holds the matching pods by label, so pod churn is invisible to the caller. ClusterIP for internal, NodePort for local dev, LoadBalancer for the cloud.

Pod IPs are temporary on purpose. Every pod you create gets a fresh address, every replacement gets a different one, and nothing should ever hold on to a pod IP, because it will be gone within the day. That is why a Service exists: a stable name in front of a changing set of pods. A Service selects pods by label, listens on a fixed ClusterIP with a stable DNS name, and kube-proxy balances traffic across the pods that currently match. You can delete every pod in a ReplicaSet and the Service keeps answering, because its backends are found by label, never by IP.

Learn the three Service types and stop there at first. ClusterIP is the default, internal to the cluster, and the one you will use constantly. NodePort exposes a Service on a fixed port on every node, which is handy for local development. LoadBalancer asks the cloud provider to put a real load balancer in front, which is how production traffic gets in. Ingress, which routes HTTP hostnames and paths into Services, is a separate topic. Meet it when you hurt from its absence, not in your first week.

Config and State, Not Files

The rest of the object model follows the same logic: the things the cluster manages live as objects, not as files and not as pets. Namespaces partition one cluster into logical workspaces so several teams can share a control plane without colliding. ConfigMaps and Secrets hold configuration and credentials as cluster objects that pods consume instead of bytes baked into images. PersistentVolumeClaims request storage separately from any pod, because storage has a different lifecycle than compute: a pod can die and its successor can attach the same volume.

You do not need every object type to begin. The right order is pods, Deployments, Services, then ConfigMaps and Secrets, then persistent volumes. Everything else, RBAC, Operators, custom resource definitions, service meshes, advanced autoscaling, is infrastructure you adopt to solve a problem you actually have, and adopting it first is a reliable way to add confusion without adding capability.

The Learning Path That Works

Run your first cluster with kind or minikube and exercise the model deliberately instead of copying a walkthrough end to end. Create one Deployment with a tiny image and watch it reach Running. Scale it to three replicas. Delete a pod and watch a replacement appear. Change the image and watch the rollout. Then add a Service and connect from a second pod using its DNS name. Each exercise makes one concept visible, and together they cover the control loop, the decision and execution split, pod disposability, controllers, and service discovery.

When you finish, test whether the model survived: you should be able to say in one sentence each why a Service deserves its own IP, what a Deployment controller does when a pod disappears, and why the scheduler is the component that decides which node runs a pod. If you can, tutorials become reference material instead of instructions, and the next steps, cluster networking, managed services like EKS, AKS, and GKE, Ingress, and observability, become upgrades to a model you already hold instead of new mountains to climb.

Frequently Asked Questions

Do I need to learn Docker before Kubernetes?
Yes, but only the core: what an image is, how a container runs, registries, ports, and volumes. Kubernetes schedules and runs containers, so you need to be fluent with a single container before you let a cluster manage hundreds of them. Compose deep dives and Swarm knowledge are not required.
What is the difference between a pod and a container?
A pod is the smallest unit the cluster schedules, with its own IP address and network namespace. The containers inside a pod share that IP, its ports, and any attached volumes. Most pods run a single main container, which keeps the mental model simple: you usually reason about pods, not containers.
Why is my pod stuck in CrashLoopBackOff?
CrashLoopBackOff means the controller started the pod but its container keeps exiting, so the cluster restarts it with a growing pause between attempts. Run `kubectl logs` on the pod to read the process output, and check your image, your entrypoint, and any configuration the app needs at startup.
Is Kubernetes the same as Docker Compose?
Both accept YAML, but the model is different. Compose starts a defined set of containers on one host. Kubernetes is a control loop running across a cluster: you declare a desired state and controllers converge on it continuously, replacing failed pods, running rollouts, and scaling replicas.
Should I learn Kubernetes on minikube, kind, or a cloud cluster?
Start locally with minikube or kind, where a single machine hosts an entire cluster that you can destroy and rebuild for free. Once the core concepts feel intuitive, move to a managed cluster such as EKS, AKS, or GKE, because a real multi node cluster under load is where Kubernetes shows its value.

Stop reaching for a spreadsheet

Obelinf keeps every subnet, device, circuit, and rack in one live source of truth, with audit logs and a topology view. Free for personal use.

Related Articles