The cluster: control plane & nodes
The two halves of every cluster.
A busy restaurant runs on a split you can see from the door. Out front, someone takes your order, writes it down, and keeps track of what has been cooked and what is still waiting. Back in the kitchen, the cooks make the food. Neither side does the other's job. They stay in sync by passing tickets back and forth. A Kubernetes cluster is built the same way. The word cluster means a group of computers, real or virtual, that Kubernetes ties together so you can treat them as one big machine.
Two halves, two jobs
Every cluster splits into two roles. The control plane is the front of the restaurant. It decides, and it remembers. The worker nodes are the kitchen. They run your actual programs. A node is one machine in the cluster, and a worker node is a machine whose whole purpose is running your apps. A practice cluster on your laptop might have one machine wearing both hats at once. A real production cluster can spread the same two roles across dozens or hundreds of machines. The split is about jobs, not about how many computers you own.
Your apps run as containers. A container is a program packed up with everything it needs, so it behaves the same on your laptop and on a server in a data centre. Kubernetes never hands you a bare container, though. It wraps one or more containers in a Pod, the smallest unit Kubernetes will schedule and start. Most Pods hold a single container, so for now you can read one Pod as one running program: a small box with your container inside it.
Here is where almost every beginner trips. You do not log into the worker machines to start your apps. You talk to the control plane and nothing else, and it arranges for the workers to do the work. Want three copies of your app running at all times? You say that to the control plane, and it works out where and how. The tool you use for that conversation is kubectl (say it "kube control"), the command-line program that carries your requests to the cluster. It gets a lesson of its own next.
kubectl get nodes
NAME STATUS ROLES AGE VERSIONcp-1 Ready control-plane 9d v1.31.0worker-1 Ready <none> 9d v1.31.0worker-2 Ready <none> 9d v1.31.0
Read that output top to bottom. The machine cp-1 carries the control-plane role, so that one is the brain. The two workers show <none> under ROLES, which means they are ordinary worker machines with no special duty beyond running your apps. Ready means the machine is healthy and available for work. AGE is how long it has been part of the cluster, and VERSION is the Kubernetes version it runs. You talk to cp-1. It tells worker-1 and worker-2 what to run.
What the control plane is made of
You do not need to memorize the internals yet, but a short tour makes the rest of the course easier. The control plane is a handful of small programs working together. The API server is the single front door, and every request goes through it, including yours. (API stands for Application Programming Interface, a formal name for the doorway one program uses to talk to another.) Behind that door sits a store called etcd, the cluster's memory: a written record of everything that is supposed to exist. The scheduler is the host with the seating chart, deciding which worker node each new Pod lands on. The controllers behave like a thermostat. A thermostat compares the room against the temperature you set and turns on the heat when the two do not match. Controllers do exactly that for the cluster, over and over, comparing what is actually running against what you asked for and closing any gap. A Pod dies at 3am, a controller sees the gap, a replacement starts. Nobody gets paged.
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGEcoredns-7db6d8ff4d-abcde 1/1 Running 0 9detcd-cp-1 1/1 Running 0 9dkube-apiserver-cp-1 1/1 Running 0 9dkube-controller-manager-cp-1 1/1 Running 0 9dkube-proxy-2xk9p 1/1 Running 0 9dkube-scheduler-cp-1 1/1 Running 0 9d
The -n kube-system part points kubectl at kube-system, the built-in area where Kubernetes keeps its own internal Pods. Every control-plane piece runs as a Pod in there: kube-apiserver, etcd, kube-scheduler and kube-controller-manager, plus coredns (the cluster's own DNS, or Domain Name System, the phone book that turns names into addresses) and kube-proxy for networking. One heads-up. On a managed cluster from a cloud provider, the control-plane entries are missing from this list, because the provider runs the control plane for you and keeps it out of sight.
What a worker node does all day
Each worker runs a small agent called the kubelet. The kubelet is the cook reading the order ticket. It takes instructions from the control plane, starts the containers it is told to start, watches them, and reports their health back up the line. Beside it, a networking piece wires the Pods together so they can reach each other and the outside world. That is the whole job. Workers wait for orders and carry them out.
That steady reporting doubles as the cluster's early-warning system. When a worker reboots, fills its disk, or falls off the network, its kubelet goes quiet, and the control plane notices the silence. Run the same command on a bad day and the machine tells on itself:
kubectl get nodes
NAME STATUS ROLES AGE VERSIONcp-1 Ready control-plane 9d v1.31.0worker-1 Ready <none> 9d v1.31.0worker-2 NotReady <none> 9d v1.31.0
worker-2 has gone NotReady. To find out why, ask that node to describe itself. The Conditions and Events near the bottom of the output spell it out in plain words:
kubectl describe node worker-2
Name: worker-2Conditions:Type Status Reason Message---- ------ ------ -------Ready Unknown NodeStatusUnknown Kubelet stopped posting node status.Events:Type Reason Age From Message---- ------ ---- ---- -------Normal NodeNotReady 3m node-controller Node worker-2 status is now: NodeNotReady
Status Unknown, with the message "Kubelet stopped posting node status", means the machine went quiet and the control plane can no longer trust what is happening on it. Look at who raised the event: node-controller. That is one of those thermostat controllers acting on its own, with no human involved. After a short grace period it moves worker-2's Pods onto the healthy nodes, so your app keeps serving traffic while you go and work out whether that box rebooted or filled its disk.
kubectl cluster-info
Kubernetes control plane is running at https://192.168.49.2:8443CoreDNS is running at https://192.168.49.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxyTo further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
That address is the API server, the front door you send everything to. Notice there is one URL for the whole cluster, not one per machine. You never point kubectl at a worker. Send your request to that single address and the control plane takes over: it writes down what you asked for, the scheduler picks a node, and the kubelet on that node starts your containers. You describe the goal. The cluster works out the steps.
Every cluster has two jobs: decide, and do. The control plane (API server, etcd, scheduler, controller manager) decides. The worker nodes run the kubelet, a container runtime (the software that actually starts and stops containers) and usually a network agent, and they do. When something breaks, the first useful question is which half owns the symptom. Answer that and you stop firing off random kubectl commands and hoping.
etcd is the durable memory of the cluster, but only the API server is allowed to talk to it. Everything else goes through the API: kubectl, the controllers, the kubelets on every node. That is why a sick API server feels like the whole world is on fire even when your apps are still serving. It is also why protecting and backing up that one path is worth far more of your attention than any pretty dashboard.
Say your production cluster shows every node Ready but Pods sitting in Pending. That usually points at the scheduler or at plain capacity, not at "Kubernetes is down". Read the node conditions and the events first. Rebooting control-plane virtual machines in a panic is how a small problem turns into a real outage.
Try this
Map your own cluster. List the nodes with their roles and conditions, then list the control-plane Pods in kube-system, and you can see exactly who lives where.
$ kubectl get nodes -o wideNAME STATUS ROLES AGE VERSION INTERNAL-IPkind-control-plane Ready control-plane 12d v1.30.0 172.18.0.2kind-worker Ready <none> 12d v1.30.0 172.18.0.3$ kubectl get pods -n kube-system -o wide | head -20NAME READY STATUS NODEcoredns-... 1/1 Running kind-control-planeetcd-kind-control-plane 1/1 Running kind-control-planekube-apiserver-kind-control-plane 1/1 Running kind-control-planekube-controller-manager-kind-control-plane 1/1 Running kind-control-planekube-scheduler-kind-control-plane 1/1 Running kind-control-planekube-proxy-... 1/1 Running kind-worker$ kubectl describe node kind-worker | Select-String -Pattern 'Conditions:|Ready|MemoryPressure|DiskPressure' -Context 0,6Ready True
Takeaway
Control plane decides, nodes execute. When a symptom shows up, name the half that owns it before you touch anything. A Pod stuck in Pending is a scheduling question. A node stuck at NotReady is a kubelet question. A kubectl command that hangs is an API server question. Aim at that one layer instead of rebooting machines and hoping the symptom goes away.