Architecture and the Control Plane¶
What You'll Learn¶
- What each control-plane and node component actually does, and which single component talks to etcd
- The control-loop / reconciliation pattern that every controller in Kubernetes follows
- How a
kubectl applytravels from your terminal to a running container
Why This Matters¶
Nearly every confusing Kubernetes symptom — a pod stuck Pending, a rollout that won't progress, a Service with no endpoints — resolves to "which component was supposed to act here, and did it?" You can't debug that without knowing which of the six or seven moving parts owns which job. This page is the map everything else in these docs assumes you have.
Mental Model: Control Plane vs. Worker Nodes¶
A Kubernetes cluster splits into two kinds of machines. The control plane makes cluster-wide decisions (what should run, where); worker nodes actually run your containers.
flowchart TB
subgraph CP["Control Plane"]
API["kube-apiserver"]
ETCD[("etcd")]
SCHED["kube-scheduler"]
CM["kube-controller-manager"]
API <--> ETCD
SCHED --> API
CM --> API
end
subgraph N1["Worker Node"]
KL1["kubelet"]
KP1["kube-proxy"]
CRI1["Container Runtime (containerd/CRI-O)"]
KL1 --> CRI1
end
subgraph N2["Worker Node"]
KL2["kubelet"]
KP2["kube-proxy"]
CRI2["Container Runtime (containerd/CRI-O)"]
KL2 --> CRI2
end
U["You / kubectl"] -->|"HTTPS + auth"| API
API <--> KL1
API <--> KL2
Control Plane Components¶
| Component | Role | One thing worth remembering |
|---|---|---|
| kube-apiserver | The front door — a REST API that validates and processes every request (kubectl, controllers, kubelets all go through it) |
It is the only control-plane component that talks to etcd directly; everything else goes through it |
| etcd | A distributed, strongly consistent key-value store holding all cluster state | It's the cluster's single source of truth — losing it without a backup means losing the cluster's memory of everything |
| kube-scheduler | Watches for newly created Pods with no assigned node, and picks one based on resource requests, affinity/anti-affinity, taints/tolerations, and constraints | It only decides the node — it never runs anything itself |
| kube-controller-manager | Runs the built-in controllers (Node, ReplicaSet, Endpoints, Job, ServiceAccount, and more) as a single binary, each running its own reconciliation loop | "Controller" here means any loop that watches actual state and pushes it toward desired state |
| cloud-controller-manager | Talks to your cloud provider's API for cloud-specific logic (provisioning LoadBalancer Services, attaching cloud disks, tagging nodes) | Only present on cloud-managed clusters; local clusters (minikube, kind) typically don't run one |
Worker Node Components¶
| Component | Role | One thing worth remembering |
|---|---|---|
| kubelet | The agent on every node; makes sure the containers described in the PodSpecs it's been assigned are actually running, and reports node/pod status back to the API server | It talks to the container runtime through the CRI — it does not run containers itself |
| kube-proxy | Maintains the network rules (iptables or IPVS) on each node that implement the Service abstraction — routing traffic for a Service's virtual IP to one of its backing Pods | You'll see this again in Services |
| Container runtime | The software that actually pulls images and starts/stops containers — containerd and CRI-O are the common choices today |
Talks to the kubelet via the Container Runtime Interface (CRI), a plugin API that lets Kubernetes stay runtime-agnostic |
The CRI matters because it's why Kubernetes isn't "a Docker orchestrator" — any runtime that implements the CRI works, which is why Docker Engine itself was removed as a direct Kubernetes runtime in v1.24 (images built by Docker still run fine everywhere, since they're standard OCI images; what changed is which daemon runs them on the node).
The Control-Loop / Reconciliation Mental Model¶
Every controller in Kubernetes — built-in or custom — follows the same shape:
- Watch the API server for objects it cares about (e.g., Deployments, or Pods with a specific label).
- Compare the object's desired state (
spec) against its observed actual state (status). - Act — create, delete, or update objects to close the gap (e.g., create a missing Pod, delete an extra one).
- Repeat, forever, reacting to every change and also re-checking periodically as a safety net.
This is the mechanism behind the claim in What Is Kubernetes? that reconciliation is continuous: there is no "done" state for a controller — it keeps watching for as long as the cluster runs.
Following One kubectl apply¶
kubectlsends an authenticated HTTPS request to kube-apiserver.- The API server runs authentication, authorization (RBAC), and admission control, then persists the object to etcd.
- The Deployment controller (inside kube-controller-manager) notices the new/changed Deployment and creates a matching ReplicaSet.
- The ReplicaSet controller notices it's short of Pods and creates Pod objects — still with no node assigned.
- kube-scheduler notices unscheduled Pods, picks a node for each, and writes that assignment back through the API server.
- The kubelet on the chosen node notices a Pod has been assigned to it, and asks the container runtime (via the CRI) to pull the image and start the container.
- The kubelet reports the Pod's status back to the API server; kube-proxy on every node updates its rules so the Pod is reachable through any Service that selects it.
Every arrow in that sequence is a watch-compare-act loop, not a single script running top to bottom.
Common Mistakes¶
- Assuming any component other than kube-apiserver talks to etcd directly — none does; it's a deliberate single point of access for consistency and security.
- Confusing the scheduler's job (picking a node) with the kubelet's job (actually starting the container) — a Pod can be
Scheduledand still fail to start. - Forgetting that kube-proxy runs on every node, not just a control-plane node — without it, Services on that node's Pods wouldn't be reachable.
Interview Questions¶
- Walk through what happens, component by component, from
kubectl applyto a running container. - Which component is the only one that talks directly to etcd, and why does that matter?
- What is the Container Runtime Interface, and why did its introduction matter for Kubernetes's design?
See Interview Prep for full answers.
Next¶
Continue to Installing kubectl and a Local Cluster to get a real cluster running and kubectl talking to it.