TT Lab
Get started
Learn Learning paths Courses

KCNA — Kubernetes and Cloud Native Associate

Why the Control Plane Is Split This Way

Continue in TT Lab

One-line summary

Kubernetes is not a "system that executes commands" but "a system in which you write down the desired state and controllers bring reality into line with it." The control plane has several pieces because the actors that run this loop were divided by role.

Why this was needed

An imperative system executes "start 3 Pods" and is done. But what if a node dies? Nobody cares, because the command has already finished.

A declarative system stores "I want a state with 3 Pods." Then someone keeps reading the current state, compares it with the desired state, and narrows the difference if they differ. This loop is called the reconciliation loop, and it is the whole of Kubernetes. Everything else is machinery to make this loop safe and scalable.

Seen this way, the separation of components reads naturally. Where do we write the state (etcd)? Who lets others read and write that state (kube-apiserver)? Who runs the loops (kube-controller-manager)? Who runs the special loop that decides which node a Pod goes on (kube-scheduler)? And who actually starts the containers on the node (kubelet)?

How it works

The control plane

Component What it does If it disappears
etcd The only store holding all of the cluster's state The cluster's memory is gone
kube-apiserver The only door to etcd. Authentication, authorization, admission, validation Nobody can read or write anything
kube-controller-manager Dozens of controller loops such as Deployment/ReplicaSet/Node/Endpoint Declarations are stored but nothing happens
kube-scheduler Assigns a node to Pending Pods Pods are created but stay Pending forever

No component touches etcd directly. The scheduler, the controller manager, and kubelet all go through the apiserver. That way authentication, authorization, admission, and audit logging are applied in one place. This is the starting point of the security design that leads into KCSA.

It is also good to know the key structure inside etcd. All resources live under /registry/, namespaced resources take the form /registry/<종류>/<네임스페이스>/<이름> (kind, namespace, name), and cluster-scoped resources take the form /registry/<종류>/<이름> (kind, name). Values are serialized as protobuf by default.

Nodes

The API is made of resources

There is only one way to talk to Kubernetes: CRUD on REST resources. Creating a Deployment and deleting a Pod use exactly the same grammar. With kubectl api-resources you can see the full list of resources this cluster knows, and with kubectl explain you can see what each field means. The habit of asking the cluster directly without opening a documentation site is the fastest, both in the exam room and on the job.

Label selectors: the glue of loose coupling

Kubernetes has almost no direct references like "this Service points to those 3 Pods." Instead you attach labels and pick with selectors. A Service, a ReplicaSet, and a NetworkPolicy all find their targets by selector. That is why a single typo in a selector creates a silent outage: the object is created normally, but it just catches nothing.

What it looks like in practice

This really happened in the author's homelab. One day the cluster did not respond, and dial tcp 10.0.0.111:6443: connect: no route to host appeared. The cause was DHCP: the control plane node's IP had been refreshed from .111 to .120.

Here the separation of components showed up in a visible form. etcd and kube-apiserver tried to bind to the nonexistent address .111, failed, and fell into CrashLoopBackOff, but kube-scheduler and controller-manager bind to 127.0.0.1, so their processes were perfectly alive. They were alive but could do nothing, because without the apiserver the controllers have nothing to read or write.

The decisive evidence was in the certificate. The Subject Alternative Name of apiserver.crt did not include .120. So changing only the IP does not recover things: connecting to an address that is not in the SAN fails TLS verification.

When the same cluster was later expanded to 7 nodes (3 control plane + 4 GPU workers), an even more painful lesson came out. Even though the etcd members were made 3 to have a quorum, controlPlaneEndpoint was hard-coded not to a VIP or DNS but to cp-1's physical IP (10.0.0.120:6443). If cp-1 dies, the etcd quorum is fine at 2/3 and the apiserver processes on the other two nodes are healthy, but kubectl and all 7 kubelets lose access. It is a state where "the control plane is alive but nobody can find the door." Data availability and access availability are entirely separate problems: that is the summary of this incident.

What you will do in the next lab

In the lab right after this, you create the kcna-arch namespace, extract the node list, and ask the cluster about its API directly with kubectl api-resources and kubectl explain. You pick Pods with label selectors, and at the end you create the same Deployment in two ways, imperative and declarative, and check what differs.