What Kubernetes is

The problem it solves, in plain terms.

Beginner8 min · lesson 1 of 24
In plain terms
Kubernetes is an air-traffic controller for your apps. You say “keep three of these running,” and it handles the take-offs, landings, and the plane that breaks down — so you’re not on the runway waving flags yourself.

You wrote an app and packaged it into a container. A container is your program bundled together with everything it needs to run, sealed up so it behaves the same on any machine. Running one copy on your laptop is a single command. The hard part shows up when one copy isn't enough. Real traffic means running many copies across many machines, restarting the ones that crash, shifting work off a server that dies, and rolling out new versions without going dark. By hand, that's a job that never sleeps. Kubernetes does it for you.

The one idea that makes it click

Start with a thermostat on the wall. You don't flip the heater on and off all day. You set a target, say 21 degrees, and the thermostat holds the room there. Gets cold, it turns the heat on. Warm enough, it stops. You set the goal, and the device handles the fussing. Kubernetes runs on that same idea. You don't feed it a list of steps to perform. You tell it the end state you want, like "keep three copies of my app running," and it works around the clock to make reality match. A copy dies? It starts a fresh one, without being asked. It's just keeping the promise you set.

Here's another way to see it. Old-school automation is like turn-by-turn driving directions: turn left here, straight for two miles, right at the light. Close one road and the whole plan falls apart. Kubernetes is more like a map app on your phone: you hand it the destination, and it works out the route, reroutes around a jam, and still gets you there. You care about where you're going; the tool sweats the turns.

People call this a container orchestrator, which is a fancy way of saying it runs, connects, heals, and updates lots of containers for you. You'll also see the name written K8s: the letter K, then eight letters, then s. It grew out of Google's experience running containers at huge scale, and it behaves the same everywhere. The same app description runs on your laptop, in a company data center, or on Amazon, Google, or Microsoft's cloud, so you aren't locked to one vendor. Learn it once and the skills carry over wherever you work.

What Kubernetes does for you
You provide
a desired state
"keep 3 copies running"
your app in a container
the thing to run
Kubernetes handles
running + restarting
keeps copies alive
scaling + updating
more or fewer, new versions
spreading + healing
survives machine failures
You describe what you want. Kubernetes keeps making it true: running, healing, scaling, and updating your app across many machines.

Where your app actually runs

A busy restaurant kitchen runs on a split of labor. The head chef calls out orders and tracks what's done; the line cooks do the actual cooking. Kubernetes is built the same way, and it doesn't live on a single computer. It ties a group of computers together so they act like one large machine, and that group is called a cluster. Each machine in it is a node, just the word for one computer in the group. Most nodes are workers, the line cooks: they run your app. One machine is the control plane, the head chef. Think of it as the brain: it makes the decisions and remembers what you asked for. You rarely log into a worker yourself; you talk to the brain, and it hands work to the workers.

Talking to the cluster with kubectl

You talk to that brain with a command-line tool called kubectl. A command-line tool is a program you drive by typing text commands instead of clicking buttons. People say "kube-control" or "kube-cuttle," and no one really agrees. Every kubectl command is a request you send to the cluster from your own machine. A good first one lists the machines the cluster is made of.

terminal
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 9m v1.31.0
kind-worker Ready <none> 8m v1.31.0
kind-worker2 Ready <none> 8m v1.31.0

Kubernetes is not a fancy way to run one container on your laptop. It is a control loop that keeps a whole fleet of containers matching the state you declared. You say "three copies of this app, behind this address, with this config." The cluster compares live reality to that wish and nudges things until they match. That is why operators talk about desired state instead of a checklist of start scripts.

On-call, this mental model matters more than memorizing every YAML field. When something is wrong, ask what the desired state says and what the live objects actually look like. The gap between those two views is almost always where the incident lives. Imagine an attacker already has a foothold in one pod on your production cluster: the same desired-state machinery that heals crashes will also recreate anything you delete unless you change the declaration that keeps recreating it.

Prefer reading the API with kubectl get and kubectl describe over guessing from a dashboard screenshot. The API is the source of truth the controllers read. A dashboard is a delayed sketch of that truth.

Try this

Talk to a real (or kind/minikube) cluster and prove you can see nodes and create a throwaway pod. You want Ready nodes and a Running pod so the "desired state" idea stops being abstract.

terminal
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 12d v1.30.0
kind-worker Ready <none> 12d v1.30.0
$ kubectl run demo --image=nginx:1.27 --restart=Never
pod/demo created
$ kubectl get pods demo -o wide
NAME READY STATUS RESTARTS AGE IP NODE
demo 1/1 Running 0 8s 10.244.1.7 kind-worker
$ kubectl delete pod demo
pod "demo" deleted

Takeaway

Kubernetes is a desired-state engine: you declare what should be true, controllers close the gap. Verify with kubectl against the API, not against a hunch — and remember that healing will recreate whatever your declaration still asks for.

kubectl needs a cluster to talk to first
If kubectl get nodes prints something like "The connection to the server localhost:8080 was refused," don't panic. Nothing is broken. It just means kubectl can't find a cluster yet, because you haven't started one. On your own machine, a free tool like kind or minikube brings up a small practice cluster in a couple of minutes. The rest of this course assumes you have one running.

Run something right now

Enough describing it. Let's make Kubernetes run something for real. The command below starts nginx, a small and popular free web server (a program that answers requests coming from web browsers), as a quick throwaway pod named hello. A pod is the smallest unit Kubernetes runs, and it usually holds a single container: your app. When you press enter, the cluster finds a node with room, pulls down the nginx software, and starts it. A few seconds later it's serving.

terminal
$ kubectl run hello --image=nginx
pod/hello created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello 1/1 Running 0 12s

That one-liner is great for a quick poke around. For real work, you write the state you want into a file and apply that file. Then it lives in version control, a system that tracks every change to your files over time, so a teammate can review it and you can run it again exactly the same way later. These files are written in YAML, a plain-text format that describes settings as simple labels, values, and lists. Here's the same web server written out in full, as a pod named web.

pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.27
ports:
- containerPort: 80
terminal
$ kubectl apply -f pod.yaml
pod/web created
$ kubectl apply -f pod.yaml
pod/web unchanged

Run apply a second time and Kubernetes says unchanged. It compared your file to what's already running, found no difference, and did nothing. That's the thermostat from earlier, in one word: you describe what you want, and Kubernetes only acts on the gap between that and reality.

When a pod won't start

Pods don't always come up clean, and learning to read a failure is half the job. The most common first stumble is a typo in the image tag: ask for one that doesn't exist and the pod gets stuck. kubectl get pods flags the trouble in the STATUS column, and kubectl describe pod explains why at the bottom, under a heading called Events.

terminal
$ kubectl run oops --image=nginx:1.99
pod/oops created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
oops 0/1 ImagePullBackOff 0 45s
$ kubectl describe pod oops
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 45s default-scheduler Successfully assigned default/oops to kind-worker
Normal Pulling 18s (x3 over 45s) kubelet Pulling image "nginx:1.99"
Warning Failed 17s (x3 over 44s) kubelet Failed to pull image "nginx:1.99": manifest not found
Warning Failed 17s (x3 over 44s) kubelet Error: ErrImagePull
Normal BackOff 4s (x4 over 44s) kubelet Back-off pulling image "nginx:1.99"

Read the Events from top to bottom like a short story. The scheduler picked a node, the kubelet on that node tried to pull nginx:1.99, and there is no such tag, so it keeps backing off and retrying. That status, ImagePullBackOff, almost always means a wrong image name or tag. Fix it to a real one like nginx:1.27 and the same pod comes up Running.

When you don't need Kubernetes
Kubernetes earns its keep when you run many copies across many machines and can't watch them by hand. It isn't free: it's a large system to learn, set up, and keep patched. For one small app on one server, where a quick restart after a crash is good enough, plain Docker or a single virtual machine is simpler and cheaper. Reach for Kubernetes when the scale or the uptime is worth that overhead, not because it's in fashion.
Quick check
01You told Kubernetes to keep 4 copies of your app running. One copy crashes at 3 a.m. What happens?
Correct — You declared a desired state of 4 copies. Kubernetes constantly compares that target to reality and closes the gap by itself.
Incorrect — That's the manual work Kubernetes exists to remove. You set the target once, and it keeps restoring it without you.
Incorrect — No. The other 3 copies keep serving requests, and a 4th is started automatically within seconds.
02You run kubectl apply -f pod.yaml, then run the exact same command again and Kubernetes prints "pod/web unchanged". What does that tell you about how Kubernetes works?
Correct — apply is declarative, so Kubernetes only acts on the gap between your desired state and reality, like a thermostat that stays quiet when the room is already at target.
Incorrect — apply is not a one-shot create; you can re-run it any time and it updates whatever has drifted from the file.
Incorrect — "unchanged" means nothing was touched at all, so no delete or recreate happened.
Incorrect — an error would be reported as an error; "unchanged" is a success message meaning no work was needed.
03You maintain one small internal tool that runs on a single server. If it crashes, a simple automatic restart is good enough, and it never needs more than one copy. A colleague suggests moving it onto Kubernetes. Based on this lesson, what is the sound call?
Incorrect — the lesson warns against adopting Kubernetes because it is fashionable; it is a large system to learn, set up, and keep patched.
Incorrect — a plain restart on one machine already handles a crash; you do not need an orchestrator just for that.
Correct — Kubernetes earns its keep when you run many copies across many machines or need high uptime; for a single small app the simpler setup is cheaper and easier.
Incorrect — Kubernetes does not shrink an app's footprint; it orchestrates many copies across machines, adding overhead rather than removing it.

Related