Skip to content

What Is Kubernetes?

Kubernetes is a container orchestrator that keeps a cluster’s actual state matching the state you declared, automatically and continuously.

The problem: containers don’t scale themselves

Section titled “The problem: containers don’t scale themselves”

A single docker run command works great on one laptop or one server. The trouble starts the moment you need more than one host, or more than one container, or any resilience at all. If the process inside a container crashes, nothing restarts it unless you notice and act. If you want to run five copies of a web server behind a single address, you have to wire that up yourself. If you want to roll out a new image version without downtime, you have to script the sequence of stopping old containers and starting new ones, in the right order, on the right hosts.

Terminal window
docker run -d --name web nginx
# if this container's process dies, nothing brings it back automatically —
# you have to notice, then run `docker run` again by hand
# and there is no built-in way to run five of these behind one address

None of that is a criticism of Docker — a container runtime’s job is to run containers, not to decide how many should exist, where they should live, or what to do when one dies. Orchestration is a separate problem: given a fleet of machines and a set of workloads, keep the right number of healthy instances running, spread across the right hosts, reachable by name, and able to be updated safely. That is the problem Kubernetes was built to solve.

Declarative desired state and the reconciliation loop

Section titled “Declarative desired state and the reconciliation loop”

Kubernetes was born out of Google’s internal experience running containers at massive scale with a system called Borg, and it is now a graduated project of the Cloud Native Computing Foundation (CNCF) — open source, vendor-neutral, and run by a large community rather than a single company.

The central idea, and the one you will see repeated throughout this course in every module, is this: you do not tell Kubernetes how to do something step by step. You declare the desired state — “I want three replicas of this container image, listening on this port” — and a set of background processes called controllers continuously watch the cluster and take whatever actions are needed to make the actual state match what you declared. This is the reconciliation loop, and it runs forever, not just once at creation time. If a Pod dies, a controller notices the actual state has drifted from the desired state and creates a replacement. If you edit the desired replica count, a controller notices the difference and creates or removes Pods to match.

Compare the same “run nginx, keep three replicas healthy” goal expressed declaratively as a Kubernetes Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.31
ports:
- containerPort: 80

You send this manifest to the cluster once. From then on, if a replica crashes, gets evicted, or the node it was on disappears, a controller creates a new Pod to bring the count back to three — with no further action from you. Rolling out a new image is just as declarative: change image: nginx:1.31 to a newer tag and re-apply; the Deployment controller replaces Pods gradually, on its own.

Proving the reconciliation loop, with real timestamps

Section titled “Proving the reconciliation loop, with real timestamps”

That last claim — “a controller creates a replacement, with no further action from you” — is not a promise to take on faith. On a real Deployment with 3 replicas already running, deleting one Pod by hand and immediately checking creation timestamps:

$ kubectl get pods -l app=web -o custom-columns='NAME:.metadata.name,CREATED:.metadata.creationTimestamp'
NAME CREATED
web-69d5569566-fmcq2 2026-09-26T08:33:54Z
web-69d5569566-gcqh4 2026-09-26T08:33:54Z
...
$ kubectl delete pod web-69d5569566-fmcq2
pod "web-69d5569566-fmcq2" deleted
$ kubectl get pods -l app=web -o custom-columns='NAME:.metadata.name,STATUS:.status.phase,CREATED:.metadata.creationTimestamp'
NAME STATUS CREATED
web-69d5569566-45pp7 Running 2026-09-26T08:35:08Z
web-69d5569566-gcqh4 Running 2026-09-26T08:33:54Z
...

The delete and the replacement’s creationTimestamp are the same second. Nobody ran a second command — the ReplicaSet controller’s watch (proven in the next lesson) noticed the actual replica count drop from 3 to 2 and immediately created a new Pod to bring it back to the declared 3. This is the reconciliation loop from a level below the analogy: not “Kubernetes eventually notices,” but a controller reacting inside the same second, provably, on a real cluster.

A Kubernetes cluster has two kinds of machines. The control plane is the brain of the cluster — it stores the desired state, makes scheduling decisions, and runs the controllers that drive reconciliation; the next lesson goes into its components in depth, including how those controllers actually watch for change and where the state itself, etcd, physically lives. The nodes are the workers — the machines (physical or virtual) that actually run your containers, packaged inside Kubernetes’s smallest deployable unit, the Pod, introduced properly in the workloads module.

It is easy to over-credit an orchestrator once you have seen it self-heal a crashed Pod. A few boundaries worth being precise about, since a generated architecture proposal will sometimes blur them:

  • Not a PaaS. Kubernetes schedules and runs containers you already built; it does not build your application, manage your source repository, or decide your deployment pipeline for you — that is the job of a CI/CD system layered on top (this course covers that layering in the GitOps module).
  • No built-in CI. There is no “run my test suite” primitive anywhere in Kubernetes itself — a Job or CronJob can run a container that happens to execute tests, but the pipeline that decides when to build, test, and deploy is external tooling, not a cluster feature.
  • The in-tree Ingress API is frozen, not actively evolving. The course’s own deep review already verified this: the networking.k8s.io Ingress API is effectively frozen in favor of the newer Gateway API, and ingress-nginx itself is being retired (March 2026) — new work in this space targets Gateway API, not new Ingress features.

When reviewing a generated architecture proposal or a claim about what Kubernetes handles automatically, check for:

  • “Kubernetes will build and deploy my code from git” presented as a built-in feature — proven above, Kubernetes runs containers you hand it; the build-and-deploy pipeline is always a separate tool (a CI system, Argo CD/Flux for GitOps) layered on top, never a cluster primitive.
  • A generated diagram or plan that puts a test suite directly “in Kubernetes” with no separate CI system — proven above, there is no built-in CI primitive; a Job running npm test is just a Job, not a substitute for a pipeline that decides when to run it and what to do with the result.
  • A recommendation to build new traffic-routing features on the classic Ingress API going forward — proven in the deep review this course is built on, Ingress is frozen and ingress-nginx is being retired; new work belongs on the Gateway API instead.
  • “The reconciliation loop runs periodically, roughly every few seconds/minutes” as an explanation of how self-healing works — proven above with real same-second timestamps, the actual trigger is a watched state change, not a timer.

🐛 Spot the bug

## Proposed architecture (from a generated onboarding doc)
"Kubernetes will run our CI pipeline: on every git push, the cluster
detects the new commit, builds the Docker image, runs our test suite,
and updates the Ingress rules automatically -- no separate CI/CD tool needed."
Show the answer

None of this is something Kubernetes does on its own. Proven above: Kubernetes’s job is reconciling the containers and objects you declare toward their desired state — it has no concept of “a git push,” no built-in image builder, and no test runner. Detecting a new commit and triggering a build is the job of a CI system (GitHub Actions, GitLab CI, Jenkins, …); getting the result of that build applied to the cluster declaratively is the job of a GitOps tool (Argo CD, Flux) sitting on top of kubectl apply/server-side apply, not a Kubernetes feature. And “updates the Ingress rules automatically” doubles the mistake: even setting aside that this whole pipeline is external tooling, new routing work in a 1.37 cluster should target the Gateway API, since the classic Ingress API is frozen and ingress-nginx is being retired. The honest architecture has three separate, real systems: a CI tool building and testing, a GitOps tool applying manifests, and Kubernetes reconciling what those manifests declare — never one system doing all three.

flowchart LR
  you["You declare desired state (YAML)"] --> api["API server stores it"]
  api --> ctrl["Controllers watch & reconcile"]
  ctrl --> actual["Actual cluster state converges"]
Desired state flows in, actual state converges toward it

Every feature this course covers, in every later module, is an instance of exactly one idea: something declares desired state, and a controller drives actual state toward it forever. A ReplicaSet’s “3 replicas” and a HorizontalPodAutoscaler’s target CPU percentage are the same pattern at different layers — this lesson just proves the pattern once, with a stopwatch, so that “the Deployment controller replaces Pods gradually, on its own” in the next module reads as a fact you have already seen happen, not a claim to take on faith.

ChoiceBenefitCost
Declarative desired state + reconciliationSelf-healing is automatic and continuous, proven above with real same-second timestamps; you describe the goal, not the stepsYou give up fine-grained control over the exact sequence of operations — a controller decides how, not just whether
Kubernetes as “just” an orchestrator (no built-in CI/PaaS)Composable — bring any CI tool, any GitOps tool, any image builder you already useMore moving parts to wire together yourself; nothing ships batteries-included for the full path from git push to running Pod
Gateway API over the frozen Ingress API for new workActively evolving, more expressive routing (proven true in the course’s own deep review)Existing Ingress-based setups need a deliberate migration, not an automatic upgrade
  • “Kubernetes builds and deploys your code from a git push.” Proven above: it reconciles containers and objects you declare; a CI system builds the image, a GitOps tool applies the result — Kubernetes itself does neither.
  • “The reconciliation loop runs on a timer, checking every few seconds.” Proven above with real timestamps: a deleted Pod’s replacement was created the same second, driven by a watch on the actual change, not a polling interval.
  • “Kubernetes is basically a PaaS like Heroku, just more complex.” Proven above: a PaaS decides how to build and deploy your app for you; Kubernetes only runs the containers and objects you already declared — the deploy pipeline is always a separate layer you bring yourself.
  • “Ingress is still where new routing features land.” Proven in this course’s deep review: the classic Ingress API is frozen and ingress-nginx is being retired (March 2026) — new routing work targets the Gateway API.
What problem does a container orchestrator solve that plain docker run does not?
What does declarative mean in the Kubernetes context?
In one sentence, what does a reconciliation (control) loop do?
A Kubernetes cluster is made up of which two parts?
What does the replacement Pod's creation timestamp, landing in the same second as the delete, actually prove?
$ kubectl get pods -l app=web -o custom-columns=NAME:.metadata.name,CREATED:.metadata.creationTimestamp
web-...-fmcq2   2026-09-26T08:33:54Z
$ kubectl delete pod web-...-fmcq2
pod deleted
$ kubectl get pods -l app=web -o custom-columns=NAME:.metadata.name,CREATED:.metadata.creationTimestamp
web-...-45pp7   2026-09-26T08:35:08Z
Which of these is something Kubernetes genuinely does NOT provide out of the box?