CKA Road Trip: K8s Components — What Each One Does
K8s is not a monolith. It's separate processes, each owning one job, talking to each other over HTTP.
The Components
etcd — the database. Stores every object in the cluster as key-value pairs. Every other component is stateless — they read/write etcd and that's where reality lives. If etcd dies, the cluster loses its mind.
kube-apiserver — the only door into etcd. Nobody talks to etcd directly except the API server. Everything — kubectl, kubelet, controller manager, scheduler — talks through here. It handles auth, validation, then reads/writes etcd.
kube-controller-manager — the reconciliation engine. Watches the API server in a loop: desired state vs actual state, gap found → fix it. ReplicaSet wants 3 pods, 1 exists → create 2 more. Does not actually run containers.
kube-scheduler — decides which node a pod runs on. Sees an unassigned pod, picks a node based on resources/taints/affinity, writes that assignment to the API server. That's it. Doesn't create the pod either.
kubelet — the agent on every node. Watches the API server for pods assigned to its node. When it sees one, it tells the container runtime to run it. The only component that touches real Linux processes. Also manages static pods from /etc/kubernetes/manifests/ with zero dependency on the API server.
kubectl — not a cluster component. A CLI on your machine that sends HTTP requests to the API server. k get pods = GET request to the API server. Nothing more.
The Flow: kubectl create deployment
kubectl → API server → etcd (deployment stored)
↓
controller manager sees new deployment
creates ReplicaSet → creates pod objects (no node assigned yet)
↓
scheduler sees unassigned pods
picks a node → writes assignment to API server → etcd
↓
kubelet on that node sees pod assigned to it
tells containerd → container starts running
Every arrow is an HTTP call to the API server. Nobody talks to anyone else directly.
The One Thing That Makes It Click
API server + etcd = single source of truth. Every other component watches that source and reacts to it. They're all independently running processes that agree on one shared database. Restart the controller manager — no state lost, because state lives in etcd, not in the process.