How it works
The explanation, with examples you can run.
The pieces
Control plane (often managed for you by EKS, GKE or AKS):
- kube-apiserver: the only entry point. It authenticates the caller, checks RBAC, runs admission (defaults, validation, policy) and persists objects. It also serves watches, so components learn about changes as they happen.
- etcd: a consistent, replicated key-value store holding every object. Only the API server talks to it.
- kube-scheduler: picks a node for each pod that does not have one yet.
- kube-controller-manager: runs the built-in controllers (Deployments, ReplicaSets, Jobs, nodes, endpoints, service accounts and more). Cloud integrations live in the cloud-controller-manager.
Every node runs:
- kubelet: watches for pods assigned to its node and asks the container runtime (containerd or CRI-O, through the CRI) to run them, then reports status back.
- kube-proxy (or a CNI plugin that replaces it): programs the node so Service addresses reach pods.
A loop in action
kubectl apply -f deploy.yaml # store the desired statekubectl get deploy web -o jsonpath='{.spec.replicas} wanted, {.status.readyReplicas} ready{"\n"}'# 4 wanted, 4 ready kubectl delete pod -l app=web --wait=false # break the actual statekubectl get pods -l app=web --watch # watch controllers repair itWhat happens after the apply: the Deployment controller sees a new Deployment and creates a ReplicaSet; the ReplicaSet controller sees zero pods where four are wanted and creates four pod objects; the scheduler sees four unscheduled pods and assigns each a node; each kubelet sees a pod for its node and starts the containers; their status flows back up. Each step is a separate loop that only reads and writes objects through the API. None calls another directly.
Why this design
- Self-healing. A crashed node, a killed pod or a lost event does not matter; the next pass of the loop sees the difference and fixes it.
- Declarative changes. You change the spec (a new image tag) and the controllers work out the steps. The same file applied twice changes nothing.
- Extensible. Anyone can add a new object type and a controller for it. Operators are exactly that.
Consequences for you
- Changes are eventually applied.
kubectl applyreturns when the object is stored, not when pods are running; usekubectl rollout statusorkubectl waitto wait for the outcome. - Fight the loop and you lose. Edit a pod owned by a ReplicaSet, or scale a Deployment that an autoscaler manages, and a controller will put it back. Change the owner instead.
- Keep manifests in git and apply them from CI or a GitOps tool such as Argo CD or Flux, so the desired state is reviewed and reproducible.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.