Core concepts · Architecture

How a Kubernetes Cluster Actually Works

The mental model everything else builds on. You declare the state you want, and controllers keep working to make it true. This module covers the parts of a cluster and what happens, step by step, when you run kubectl apply.

Module: 04 of 20 Level: Core concepts · Architecture Time: 10 min read Updated:
All modules in this track (20)

In this module, you'll learn to:

  • Explain the reconciliation loop: desired state, actual state, and controllers
  • Name the parts of the control plane and of a worker node, and what each does
  • Trace what happens between kubectl apply and a running container

Before you start: finish Part 1, especially Your First Cluster, where you watched Kubernetes replace a deleted pod. This module explains how that happened. Keep the kind cluster running; the commands at the end use it.

Principle

You describe what you want, and Kubernetes keeps making it true

With a plain server, you give instructions: start this process, copy that file, restart the service. If the process crashes at 3 a.m., it stays down until something or someone restarts it.

Kubernetes works the other way round. You write down the desired state ("three copies of the orders-api image, version 1.4, each with half a CPU"), and you hand it to the cluster. From then on, small programs called controllers keep comparing what you asked for with what's actually running, and fix any difference they find. A crashed container gets replaced. A lost node's pods get rescheduled somewhere else. You never tell the cluster how to recover; you only told it what should exist.

The reconciliation loop behind every Kubernetes feature
Desired statewhat you declared in YAML: "3 replicas of orders-api:1.4"
a controller watches both sides
Actual statewhat is really running right now: 2 healthy pods
the controller sees a difference
Actionstart one more pod to get back to 3
the cluster changes; the controller checks again
this never stops, so drift and failures are corrected automatically

Almost everything in this track is this same loop applied to a different problem. A Deployment controller keeps the right number of pods running. A load balancer controller keeps a cloud load balancer matching your Ingress. Argo CD keeps the cluster matching Git. Once this idea clicks, the rest of Kubernetes stops looking like magic.

Architecture

The control plane decides, the nodes do the work

A cluster has two halves.

The control plane is the brain. It stores the desired state, decides where things should run, and runs the controllers. Its main parts:

  • API server: the front door. Every tool, including kubectl, the nodes, and every controller, reads and writes cluster state only through it.
  • etcd: the database where the API server keeps all cluster state.
  • Scheduler: picks a node for each new pod, based on the resources the pod requests and the rules it sets.
  • Controller manager: runs the built-in controllers (Deployments, ReplicaSets, Jobs, and others).

The worker nodes are the muscle. They're ordinary machines (a Docker container in a local kind cluster, EC2 instances on Amazon EKS) that actually run your containers. Each node runs:

  • kubelet: the node's agent. It asks the API server which pods belong on its node, and makes sure they're running.
  • Container runtime (usually containerd): pulls images and starts containers, the same job Docker does on your laptop.
  • A network plugin (CNI) gives each pod its own IP address, and kube-proxy routes traffic sent to a Service on to the right pods. The networking module covers both.
Flow

What really happens when you run kubectl apply

This is the path a single change takes through a cluster. Knowing it tells you where to look when something doesn't happen: each arrow is a place where things can get stuck.

From kubectl apply to a running container
Youkubectl apply -f deployment.yaml
HTTPS request, carrying your credentials
Control plane
API serverchecks who you are and whether you're allowed, then validates the object
stores the new desired state
etcdnow holds "Deployment orders-api: 3 replicas"
the Deployment and ReplicaSet controllers notice and create 3 Pod objects
Schedulerpicks a node for each pod that has room for its CPU and memory requests
the pod is now assigned to a node
Worker node
kubeletsees a new pod assigned to its node
asks the runtime to start it
containerdpulls the image from the registry and starts the container
the network plugin gives the pod its own IP address
Pod runningreadiness probe passes, and the pod starts receiving traffic

Notice that kubectl apply returns as soon as the API server has stored your change, near the top of the diagram. Everything below it happens afterwards, without you. That's why "the command succeeded" and "the app is running" are two different questions, a point the Incident Triage module returns to.

On a managed service such as Amazon EKS, the control plane half of this diagram is run by the cloud provider and the worker nodes are yours. Kubernetes on Amazon EKS covers exactly where that line falls.

Try it

Look around a cluster

These read-only commands work on any cluster, including a local kind cluster:

# The worker nodes, with their Kubernetes version and internal IPs
kubectl get nodes -o wide

# Everything running in every namespace, including the system pods in kube-system
kubectl get pods -A

# On kind you can see the control plane itself: etcd, the API server,
# the scheduler, and the controller manager all run as pods in kube-system
kubectl get pods -n kube-system -o wide

# Every kind of object the API server knows about
kubectl api-resources

# Watch the reconciliation loop: delete a pod a Deployment owns,
# and a replacement appears within seconds
kubectl get pods -w
Scroll sideways to see the full diagram →
Implementation notes
  • Everything is an API object. Pods, Services, even the rules about who can do what, are records stored through the API server. Tools like Terraform, Helm, and Argo CD are just different ways of writing those records.
  • Nobody talks to etcd or the nodes directly. Even the kubelet on each node gets its instructions from the API server. If the API server is unreachable, running pods keep running, but nothing new can be changed.
  • Keep the model in your head when debugging. A pod stuck in Pending is a scheduler problem, meaning no node has room. ImagePullBackOff happens at the containerd step. A pod that runs but gets no traffic is a readiness or Service problem. The diagram above is the map.
Recap

Key terms

  • Desired state: what you've declared should exist.
  • Controller: a loop that compares desired and actual state, and acts on any difference.
  • API server: the only way in to the cluster, for people, tools, nodes, and controllers.
  • etcd: the database that stores every object.
  • Scheduler: chooses a node for each new pod, based on what the pod requests.
  • kubelet: the agent on each node that starts and watches the pods assigned to it.
Check yourself

Pop quiz

Five questions: three on the ideas in this module, and two scenarios where you apply them. The order changes every time you take it, and 4 out of 5 passes.

5 questions. Decide on your answer to each, then check it.

  1. Scenario

    kubectl apply returns successfully. What does that prove?

    1. The new pods are running and serving traffic
    2. The API server accepted and stored the change
    3. The image was pulled successfully
    4. The scheduler found room on a node
    Show answer

    The API server accepted and stored the change

    apply returns once the API server has stored the desired state. Scheduling, pulling the image, and starting containers all happen afterwards, and any of them can still fail.

  2. Concept

    Which component chooses the node a new pod runs on?

    1. The kubelet
    2. etcd
    3. The scheduler
    4. kube-proxy
    Show answer

    The scheduler

    The scheduler picks a node with enough unreserved capacity for the pod's requests. The kubelet on that node then starts it.

  3. Scenario

    A pod stays in Pending. Where in the flow should you look first?

    1. The container runtime pulling the image
    2. The scheduler, which can't find a node with room
    3. The readiness probe
    4. The API server's authentication
    Show answer

    The scheduler, which can't find a node with room

    Pending means the pod hasn't been placed on a node yet, usually because no node has the CPU or memory it requests. An image problem shows up later, as ImagePullBackOff.

  4. Concept

    How does a kubelet learn which pods it should run?

    1. It watches the API server for pods assigned to its node
    2. The scheduler connects to the node and starts them
    3. It reads etcd directly
    4. Someone runs kubectl on the node
    Show answer

    It watches the API server for pods assigned to its node

    Every component goes through the API server, including the kubelet. Nothing but the API server talks to etcd.

  5. Concept

    Which of these is the reconciliation loop at work?

    1. kubectl logs streaming a container's output
    2. A Deployment replacing a crashed pod without anyone asking
    3. An engineer restarting a server by hand
    4. CI building a new image
    Show answer

    A Deployment replacing a crashed pod without anyone asking

    A controller saw that the actual state (one pod fewer) didn't match the desired state, and fixed it. The same loop drives Deployments, load balancer controllers, and Argo CD.

Questions about this learning path?

I'm happy to go into more detail on any of this: how the pieces fit together, ingress costs, RBAC design, or how I triage incidents.

anupojuprudhvi@gmail.com