DevOps Peach

Docker & Kubernetes · Kubernetes Architecture · Lesson 3 of 5

The control plane

kube-apiserver is the only door into the cluster; etcd stores state; the scheduler picks nodes; the controller-manager pulls the cluster to the desired state.

Practice interactively →

flowchart TB
  K["kubectl / client"] --> API["kube-apiserver"]
  API <--> E[("etcd")]
  S["kube-scheduler"] <--> API
  CM["kube-controller-manager"] <--> API
  CCM["cloud-controller-manager"] <--> API
  API <--> KL["kubelet on the nodes"]
Component Role
kube-apiserver The only REST API into the control plane. Every client and component goes through it; it handles authentication, authorization, validation and admission control
etcd A consistent key-value store holding all cluster state; uses Raft between members. Only the apiserver talks to etcd directly
kube-scheduler Picks a node for new pods without one, based on resource requests, constraints, affinity… It only assigns the node; the kubelet on that node runs the containers
kube-controller-manager Runs the control loops (Deployment, ReplicaSet, Node, Job…), watches state through the apiserver and fixes drift
cloud-controller-manager Cloud-specific integration: nodes, routes, Services of type LoadBalancer

On a kubeadm cluster these components run as static pods in the kube-system namespace. On EKS/GKE/AKS the provider manages them and they are not visible.

A Pending pod with the event 0/3 nodes are available: 3 Insufficient cpu is the scheduler talking: no node has enough CPU for the request.

kubectl get componentstatuses has been deprecated since Kubernetes 1.19; look at the pods in kube-system or the apiserver /readyz endpoint instead.

Command Meaning
kubectl cluster-info Address of the apiserver and core services
kubectl get pods -n kube-system System pods: apiserver, etcd, scheduler, CoreDNS…

The path of an API request

kubectl apply → authentication → authorization (RBAC) → mutating admission
→ schema validation → validating admission → stored in etcd → watchers notified

Components never call each other directly. The scheduler, controllers, and kubelets watch the apiserver for changes and react, which is why the system keeps working even if one component restarts: it simply resumes watching.

How the scheduler decides

Scheduling has two phases. Filtering removes nodes that cannot run the pod (not enough CPU or memory, taints without a matching toleration, a nodeSelector that does not match). Scoring ranks the remaining nodes, for example preferring spread across zones or nodes that already have the image. The best-scoring node is written into the pod's spec.nodeName.

High availability

A production control plane runs three (or five) apiservers behind a load balancer and an etcd cluster with an odd number of members, so it survives a failure. The scheduler and controller-manager run several copies, but only one is active at a time thanks to leader election.

Protecting etcd

etcd holds the entire cluster state, including Secrets. On self-managed clusters, back it up regularly:

ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-2026-01-15.db \
  --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key

Encrypting Secrets at rest in etcd is a separate setting worth enabling.

Ways to run a cluster

Option Use
kind, minikube, k3d Local learning on a laptop
kubeadm Building a standard cluster yourself on VMs
k3s Lightweight distribution for edge devices and small servers
EKS, AKS, GKE Managed control plane in the cloud

Components follow a version skew policy: kubelets may lag the apiserver by a few minor versions but must never be newer, so upgrade the control plane first.

Practice interactively →