KUBERNETES TUTORIAL Cluster anatomy: control plane, nodes & kubectl essentials
Cluster anatomy: control plane, nodes & kubectl essentials
What we're doing
When you hit Start, you're on a real 3-node Kubernetes cluster (anatomy-control-plane + two workers) running the shop app. You'll meet the control-plane components (API server, etcd, scheduler, controller-manager), the node components (kubelet, kube-proxy), inspect a node with describe, practice the core kubectl verbs and output formats, and delete a control-plane pod to watch it come back.
Watch the video first, then run these as you read. kubectl is already set up here; nothing needs sudo. We're still only reading the cluster, no deploying your own app yet.
The mental model: a brain plus workers
A cluster is two kinds of machine. The control plane is the brain: it decides, schedules, and remembers. The worker nodes are the muscle: they run your Pods. You only ever talk to the control plane (through kubectl), never to the workers directly. Hold that picture; everything below is a piece of it.
Step 1: See the machines
kubectl get nodes -o wide
NAME STATUS ROLES VERSION ... CONTAINER-RUNTIME
anatomy-control-plane Ready control-plane v1.31.0 ... containerd://1.7.18
anatomy-worker Ready <none> v1.31.0 ... containerd://1.7.18
anatomy-worker2 Ready <none> v1.31.0 ... containerd://1.7.18
Three nodes. The ROLES column shows one control-plane (the brain) and two workers (<none>). -o wide adds detail like each node's container runtime. You talk to the control plane; the workers run the work.
Step 2: Meet the control plane (the four components)
The control plane is four small programs, each with one job:
| Component | Its one job |
|---|---|
| kube-apiserver | the front door, every command and component talks through it |
| etcd | the cluster's memory, the single source of truth |
| kube-scheduler | picks which node a new Pod runs on |
| kube-controller-manager | runs the loops that keep reality matching what you asked for |
See them as real pods:
kubectl get pods -n kube-system
NAME READY STATUS AGE
coredns-... (x2) 1/1 Running ...
etcd-anatomy-control-plane 1/1 Running ...
kube-apiserver-anatomy-control-plane 1/1 Running ...
kube-controller-manager-anatomy-control-plane 1/1 Running ...
kube-scheduler-anatomy-control-plane 1/1 Running ...
kindnet-... (x3) 1/1 Running ...
kube-proxy-... (x3) 1/1 Running ...
kube-system is the namespace where Kubernetes runs its own machinery. The four components are right there, each ending in -anatomy-control-plane because they run on the control-plane node. coredns is the cluster's internal DNS.
Worth knowing: a lightweight distro like k3s bundles these four into a single process, so you can't see them separately. This cluster uses kind (real upstream Kubernetes) precisely so they show up as real, inspectable pods.
Step 3: Meet the node components
The kube-proxy and kindnet entries above are the per-node parts, three of each, one per node:
- kubelet, the node's agent: takes orders from the API server, runs the assigned Pods, reports health. (It runs as part of the node itself, not as a pod, so it's not in the list.)
- kube-proxy: wires up Service networking on each node.
- container runtime (
containerd): actually pulls images and runs containers.
The rule is always: the control plane decides, the kubelet on each node does.
Step 4: Inspect a node end to end
describe node is the single best way to understand a machine:
kubectl describe node anatomy-worker
Read it section by section:
- Roles / Labels, what kind of node this is.
- Taints, rules about what may run here. The control-plane node has a taint that keeps app Pods off it; workers have none.
- Conditions, the health report.
MemoryPressure/DiskPressure/PIDPressureshould beFalse, andReadyshould beTrue(that's the kubelet saying "I'm healthy"). - Capacity / Allocatable, how much CPU, memory, and how many pods this node can hold.
- System Info, kernel, OS image, container runtime version, kubelet version, the real software on the box.
- Non-terminated Pods, everything running here and what each reserves.
One command, and you know the node's role, health, size, software, and workload.
Step 5: The kubectl essentials
You already know get. Two more verbs complete the core set:
kubectl get pods -n shop # list
kubectl describe pod -n shop <a-web-pod> # zoom into one + its Events
describe shows an Events list at the bottom, always your first stop when something is wrong.
Output formats change how much get shows:
kubectl get pods -n shop -o wide # extra columns (incl. NODE)
kubectl get pod -n shop <name> -o yaml # the entire object, every field
kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.kubeletVersion}' # pluck one field
-o wide, more columns, like which node a Pod is on.-o yaml, the full object exactly as the API server stores it (great for learning what fields exist).-o jsonpath, pulls out a single value, here every node's kubelet version on one line.
And apply, the declarative verb you'll use most:
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml # or a local file.yaml
kubectl get pod nginx # it's there
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml # run again: "unchanged"
apply reads a manifest and makes the cluster match it. Run it twice and the second time reports unchanged, it only applies differences. That declarative loop is how you'll work with Kubernetes from here on. (Just a taste today; real deploying is the next tutorial.)
Step 6: Watch the control plane heal itself
The control-plane components are static pods, their manifests live on the node and the kubelet keeps them alive no matter what. Prove it.
In one terminal, watch:
kubectl get pods -n kube-system -w
In a second terminal, delete the scheduler (use the real name from Step 2):
kubectl delete pod -n kube-system kube-scheduler-anatomy-control-plane
Back in the watch: the scheduler disappears, then within seconds a fresh kube-scheduler-... pod appears and goes Running. You did nothing. The control-plane node's kubelet saw the static-pod manifest, noticed the scheduler was gone, and rebuilt it. Even the brain self-heals. Stop the watch with Ctrl+C.
The pieces you just met
| Where | Component | Job |
|---|---|---|
| Control plane | kube-apiserver | front door for all requests |
| Control plane | etcd | the cluster's memory / source of truth |
| Control plane | kube-scheduler | places new Pods on nodes |
| Control plane | kube-controller-manager | reconcile loops (keep reality == desired) |
| Every node | kubelet | runs assigned Pods, reports health |
| Every node | kube-proxy | Service networking on the node |
| Every node | containerd | pulls images, runs containers |
Cheat sheet
kubectl get nodes -o wide # the machines + roles
kubectl get pods -n kube-system # control-plane + node components
kubectl describe node <name> # one node, end to end
kubectl describe pod -n kube-system <component> # zoom into a component + its events
kubectl get pod <name> -o yaml # the full object
kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.kubeletVersion}' # one field
kubectl apply -f file.yaml # create/update declaratively
kubectl config get-contexts # which cluster am I on (* = current)
The one thing to remember: the control plane decides and remembers (API server, etcd, scheduler, controller-manager); every node runs the work (kubelet, kube-proxy, runtime). One request flows through all of them, and that same loop is what heals your cluster.
Next tutorial, we deploy our own app onto this cluster.
What's next
Start KUBERNETES Suggested tutorials
Keep the momentum going — pick a related topic.