Kubernetes Introduction
What Kubernetes is, its core architecture, and getting started with kubectl.
The problem Kubernetes solves
Docker Compose (covered in the Docker tutorials) is enough for running a handful of containers on one machine. Real production systems need more: dozens or hundreds of containers spread across many machines, automatic restart when a container crashes, automatic replacement of an entire machine that dies, rolling out new versions without downtime, and scaling up or down as load changes — all without an engineer manually SSHing anywhere.
Kubernetes (often abbreviated K8s — "K," 8 letters, "s") is a container orchestration system: you describe the desired state of your application ("I want 3 replicas of this container running, always"), and Kubernetes continuously works to make reality match that description, healing it automatically whenever it drifts (a container crashes, a machine goes offline).
This is a fundamentally different way of operating than running docker run commands by hand: instead of imperatively telling the system what to do step by step, you declare an end state, and a control system keeps reconciling toward it indefinitely.
Core architecture, conceptually
A Kubernetes cluster is made up of two kinds of machines (physical or virtual): a small number of control plane nodes, and a larger number of worker nodes that actually run your application containers.
┌───────────────────────── Control Plane ─────────────────────────┐
│ │
│ API Server <---- kubectl / clients talk here │
│ | │
│ Scheduler (decides which node a new Pod should run on) │
│ | │
│ Controller Manager (reconciles desired vs actual state) │
│ | │
│ etcd (stores the entire cluster's desired-state data) │
└─────────────────────────────────────────────────────────────────┘
|
┌─────────────────────┼─────────────────────┐
│ │ │
┌───────▼───────┐ ┌───────▼───────┐ ┌───────▼───────┐
│ Worker Node │ │ Worker Node │ │ Worker Node │
│ kubelet │ │ kubelet │ │ kubelet │
│ [Pod] [Pod] │ │ [Pod] │ │ [Pod] [Pod] │
└────────────────┘ └────────────────┘ └────────────────┘
- API server — the single entry point for everything. Every
kubectlcommand, every internal component, and every automated tool talks to Kubernetes exclusively through this REST API — nothing touchesetcdor the nodes directly. - etcd — a distributed, consistent key-value store holding the cluster's entire desired state (every object you've defined) and current observed state. It's the cluster's single source of truth.
- Scheduler — decides which worker node a newly created Pod should run on, based on resource requirements, available capacity, and constraints.
- Controller manager — runs the reconciliation loops that are Kubernetes' whole philosophy: continuously compare desired state (in
etcd) against actual state (what's really running) and take action to close any gap — for example, if a Pod dies, a controller notices the actual replica count dropped below desired and starts a replacement. - kubelet — an agent running on every worker node, responsible for actually starting, stopping, and monitoring the containers the control plane has assigned to that node.
You never SSH into a node to run a container by hand in normal operation — you describe what you want to the API server, and the scheduler, controller manager, and kubelets carry it out and keep it that way.
kubectl basics
kubectl is the command-line tool for talking to a cluster's API server:
$ kubectl version --client
$ kubectl cluster-info
# List nodes in the cluster
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
node-1 Ready control-plane 30d v1.30.2
node-2 Ready <none> 30d v1.30.2
node-3 Ready <none> 30d v1.30.2
# List running Pods in the current namespace
$ kubectl get pods
# See detailed information and recent events for one Pod (invaluable for debugging)
$ kubectl describe pod my-app-7d8f9c-x2j4k
# Stream a Pod's logs
$ kubectl logs my-app-7d8f9c-x2j4k
# Get a shell inside a running container, for debugging
$ kubectl exec -it my-app-7d8f9c-x2j4k -- /bin/sh
# Apply a YAML file describing desired state — create it if missing, update if it exists
$ kubectl apply -f deployment.yaml
kubectl apply -f is the command you'll run constantly: it's how you tell Kubernetes "here's what I want the cluster to look like," whether you're creating something new or changing something that already exists. The next tutorial, Pods, Deployments, and Services, covers exactly what goes inside that YAML.
Common mistakes
- Thinking of Kubernetes commands as imperative "do this now" instructions the way
docker runis — most real usage is declarative: youapplya YAML description of desired state, and Kubernetes' controllers do the work of getting there and keeping it there. - Trying to manage individual containers directly instead of through Kubernetes objects (Pods, Deployments) — anything created by hand outside the declared desired state will simply be removed or ignored by the reconciliation loop next time it runs.
- Confusing the control plane (which makes decisions) with worker nodes (which actually run your application's containers) — in a managed cluster (e.g., a cloud provider's managed Kubernetes offering), you often don't even have direct access to control plane machines.
Interview questions
Q: What problem does Kubernetes solve that Docker alone doesn't? Docker runs individual containers on a single machine; Kubernetes orchestrates containers across many machines — automatically restarting failed containers, replacing containers on a machine that goes down, rolling out updates without downtime, and scaling the number of running instances based on load, all driven by a declared desired state rather than manual, per-machine commands.
Q: What is the control plane, and what does it do? It's the set of components that make all of a cluster's decisions: the API server (the single entry point every client talks to), etcd (the source of truth for desired and observed cluster state), the scheduler (decides which node runs a new Pod), and the controller manager (continuously reconciles actual state toward desired state). Worker nodes, by contrast, just run the containers the control plane assigns to them.
Q: What does it mean that Kubernetes is "declarative"? Rather than issuing step-by-step imperative commands (start this container, then that one), you describe the desired end state — e.g., "3 replicas of this container should be running" — in a YAML manifest and apply it. Kubernetes' controllers then continuously compare that desired state against what's actually running and take whatever action is needed to close the gap, automatically and repeatedly, without further manual instruction.