Kubernetes Architecture Explained: Control Plane, Nodes & kubectl
Deep dive into Kubernetes architecture. Learn how the API server, etcd, scheduler, controller manager, kubelet, and kube-proxy work together to run containerised workloads.

Kubernetes is a distributed system — multiple processes running across multiple machines, coordinating to run your workloads reliably. Understanding the architecture isn't just academic: it helps you debug issues, understand error messages, and reason about what happens when things go wrong.
This lesson digs into every major component, how they talk to each other, and how kubectl fits in.
The Two Parts of a Kubernetes Cluster
A Kubernetes cluster has two types of machines:
- Control plane nodes — run the Kubernetes management components; they don't run your application containers (in production)
- Worker nodes — run your application Pods
In a production cluster you'll have multiple control plane nodes for high availability. In development (minikube, kind, Docker Desktop), a single node runs everything.
Control Plane Components
The control plane is the brain of Kubernetes. It stores the desired state, schedules workloads, and constantly works to reconcile the actual state of the cluster with what you've declared.
API Server (kube-apiserver)
The API server is the single entry point for all control plane operations. Every interaction with a Kubernetes cluster goes through it — kubectl commands, internal component communication, and external tooling.
It validates and processes REST API requests, authenticates and authorises every request, reads and writes cluster state to etcd, and notifies other components of state changes. The API server is stateless — all state lives in etcd. You can run multiple replicas for high availability.
etcd
etcd is a distributed key-value store and the single source of truth for all cluster state: what Pods exist, what Deployments are configured, which nodes are registered, what Secrets are stored.
Key properties: strongly consistent (reads always return the latest committed value), distributed (typically runs as a 3 or 5 node cluster for fault tolerance), and watched by other components via the API server.
Back up etcd regularly in production. Losing etcd without a backup means losing the entire cluster state.
Scheduler (kube-scheduler)
When a new Pod is created, it's initially unbound — it exists in etcd but isn't assigned to a node. The scheduler watches for unbound Pods and makes placement decisions based on resource requests (does the node have enough CPU and memory?), node selectors and affinity rules, taints and tolerations, and spread constraints.
Once the scheduler decides, it updates the Pod's nodeName field in etcd via the API server. The kubelet on that node picks it up from there.
Controller Manager (kube-controller-manager)
The controller manager runs a collection of controllers — each is an independent reconciliation loop watching for a specific type of resource and ensuring the cluster matches the desired state.
| Controller | What It Manages |
|---|---|
| ReplicaSet Controller | Ensures the right number of Pod replicas exist |
| Deployment Controller | Manages rollouts and rollbacks |
| Node Controller | Monitors node health; evicts Pods from failed nodes |
| Service Account Controller | Creates default service accounts in new namespaces |
| Job Controller | Manages batch Jobs to completion |
| EndpointSlice Controller | Updates Service endpoints when Pods change |
Worker Node Components
Worker nodes are where your application Pods actually run. Each node runs three main processes.
kubelet
The kubelet is an agent running on every worker node. It watches the API server for Pods scheduled to its node, instructs the container runtime to start, stop, and monitor containers, reports Pod status and node health back to the API server, and runs liveness and readiness probes.
The kubelet speaks to the container runtime via the Container Runtime Interface (CRI). The default runtime in modern Kubernetes is containerd.
kube-proxy
kube-proxy runs on every node and maintains the network routing rules that make Kubernetes Services work. When you create a Service with a virtual IP, kube-proxy programs iptables rules on every node so that traffic to the Service IP is forwarded to the correct Pod IPs. As Pods come and go, kube-proxy updates these rules automatically.
Container Runtime
The container runtime (containerd, CRI-O) is what actually pulls images and starts/stops containers. The kubelet delegates all container operations to it via the CRI.
How It All Works Together: Pod Creation Flow
Here's what happens step-by-step when you run kubectl apply -f deployment.yaml:
1. kubectl → sends YAML to API Server
2. API Server → validates, authenticates, stores desired state in etcd
3. Deployment Controller → watches etcd, sees new Deployment
→ creates ReplicaSet
4. ReplicaSet Controller → watches etcd, sees new ReplicaSet
→ creates 3 Pods (unbound)
5. Scheduler → watches for unbound Pods
→ selects a node for each Pod
→ updates Pod.spec.nodeName in etcd
6. kubelet (on selected node) → watches API server
→ sees Pod assigned to its node
→ tells containerd to pull image + start container
7. kubelet → reports Pod status (Running) back to API server
8. API server → updates Pod status in etcdThis flow — write desired state → controllers reconcile → containers run — is the engine of Kubernetes.
kubectl: The Kubernetes CLI
kubectl is the command-line client for talking to the Kubernetes API server. It reads your cluster's connection details from ~/.kube/config (the kubeconfig file).
Essential kubectl Commands
# Cluster info
kubectl cluster-info
kubectl get nodes
kubectl get nodes -o wide # extra detail including IPs
# Namespaces
kubectl get namespaces
kubectl create namespace staging
# Get resources
kubectl get pods
kubectl get pods -n kube-system # system namespace
kubectl get all # pods, services, deployments, etc.
# Describe (human-readable detail + events)
kubectl describe pod my-pod-xyz
kubectl describe node my-node
# Apply and delete
kubectl apply -f deployment.yaml
kubectl delete -f deployment.yaml
# Logs
kubectl logs my-pod-xyz
kubectl logs -f my-pod-xyz # follow
kubectl logs my-pod-xyz -c api # specific container in multi-container Pod
# Execute commands
kubectl exec -it my-pod-xyz -- bash
# Port forward (for local testing)
kubectl port-forward pod/my-pod-xyz 3000:3000
kubectl port-forward service/my-service 8080:80Kubeconfig
# ~/.kube/config
apiVersion: v1
clusters:
- cluster:
server: https://kubernetes.example.com
name: my-cluster
contexts:
- context:
cluster: my-cluster
user: admin
name: my-cluster-context
current-context: my-cluster-contextSwitch between clusters with:
kubectl config get-contexts
kubectl config use-context my-cluster-contextPrevious: Lesson 6 — What Is Kubernetes? | Next: Lesson 8 — Pods, Deployments & Services
Part of the Docker & Kubernetes Mastery course.
External references:
