Week 7: Kubernetes Architecture & Your First Cluster

Compose orchestrates containers on one machine. Kubernetes orchestrates them across a fleet — scheduling workloads onto whichever node has room, restarting what crashes, and continuously reconciling reality toward whatever state you declared. This week is entirely architecture: the control plane and node components that make all of that possible, before a single YAML manifest gets written next week.

Module 7 of 17 Week 7 of 18 ~3.5 Hours Hands-on Exercise Included

By the end of this week, you'll be able to

  • Name every control-plane component and explain what it's responsible for
  • Explain the kubelet's role and the declarative reconciliation loop it's part of
  • Spin up a local cluster and run your first kubectl commands against it

1. Why Kubernetes at All

Docker Compose runs containers on a single machine — if that machine dies, every container on it dies with it. Kubernetes exists to answer a harder question: given a fleet of machines and a set of workloads, how do you keep those workloads running, correctly placed, and self-healing, without a human manually SSH-ing anywhere?

the core idea: declarative, reconciled state
# You DECLARE desired state:
"I want 3 replicas of my-app running, each with these resource limits"

# Kubernetes CONTINUOUSLY RECONCILES reality toward that declaration:
- A node crashes, taking one replica down -> Kubernetes notices, schedules a
  replacement on a healthy node, automatically.
- You update the image tag -> Kubernetes rolls out the change gradually,
  replica by replica, without downtime.
- A Pod's health check starts failing -> Kubernetes restarts or replaces it.

# You never imperatively say "start this container on that machine."
# You declare an outcome; a set of control loops keeps making it true.

Every concept in the next eleven weeks — Deployments, Services, HPAs, GitOps — is a variation on this same idea: describe what you want, and let a controller loop keep reality matching it.

Don't reach for Kubernetes too early

A single server running Docker Compose is genuinely the right answer for a lot of small, real projects. Kubernetes' power comes with real operational complexity — it earns its keep once you have multiple services, need genuine high availability, or are scaling a team, not by default on day one.

2. The Control Plane

The control plane is the cluster's "brain" — usually running on dedicated nodes, making global decisions about the cluster (scheduling, responding to events) without running any of your actual application workloads.

control plane components
kube-apiserver         # the front door. EVERYTHING talks to the cluster through
                        # this REST API — kubectl, controllers, even other control
                        # plane components. It's the only component that talks to etcd.

etcd                    # a distributed key-value store — the cluster's single source
                        # of truth. Every object's desired state lives here.

kube-scheduler           # watches for newly-created Pods with no node assigned yet,
                        # and decides which node they should run on based on
                        # resource availability, constraints and affinity rules.

kube-controller-manager  # runs the actual reconciliation loops — the "controllers"
                        # that notice drift between desired and actual state and
                        # act to correct it (e.g. the Deployment controller).

Notice the pattern: the API server is the only component that reads or writes etcd directly. Every other component — the scheduler, the controllers, even kubectl on your laptop — only ever talks to the API server, which is what makes the whole system's access control and auditing tractable.

etcd is the whole cluster's memory

If etcd is lost with no backup, the cluster forgets everything it was ever told to run — every Deployment, Service and Secret definition. Production clusters treat etcd backups with the same seriousness as a production database backup, because that's exactly what it is.

3. Node Components

Every node — a worker machine, physical or virtual — runs a small set of agents that let the control plane actually run workloads on it:

node components
kubelet          # the primary agent on every node. Watches the API server for Pods
                 # assigned to its node, and makes sure their containers are running
                 # and healthy — talking to the container runtime to do so.

container runtime   # containerd (or another CRI-compliant runtime) — actually pulls
                 # images and starts/stops containers, same as in Week 1's Docker
                 # architecture, just driven by kubelet instead of the Docker CLI.

kube-proxy       # maintains network rules on the node so traffic to a Service's
                 # virtual IP gets routed to one of the correct backing Pods,
                 # wherever they're actually running.

Notice kubelet doesn't get told "start container X" directly by a human — it watches the API server for Pods scheduled to its node and reconciles locally, exactly the same declarative pattern as everything else in Kubernetes, just running per-node instead of cluster-wide.

the full request path, end to end
kubectl apply -f deployment.yaml
    -> kube-apiserver validates & writes desired state to etcd
    -> kube-scheduler notices unscheduled Pods, assigns them to nodes
    -> kubelet (on the assigned node) notices new Pods for it, tells containerd
       to pull the image and start the container
    -> kube-proxy updates routing rules so Services can reach the new Pod
No component here is Docker-specific

Kubernetes talks to nodes through the CRI (Container Runtime Interface) — containerd, CRI-O or others all work. Modern Kubernetes doesn't require "Docker" installed anywhere in the cluster; it needs a CRI-compliant runtime, which is often containerd running underneath, the same one from Week 1's architecture diagram.

4. Your First Local Cluster

You don't need a cloud account to learn Kubernetes — Minikube and kind (Kubernetes IN Docker) both run a real, fully-functional cluster locally.

starting a local cluster
# Option A: Minikube
minikube start
kubectl get nodes

# Option B: kind
kind create cluster --name learning
kubectl cluster-info
kubectl — your primary interface to everything ahead
kubectl get nodes                # list every node in the cluster
kubectl get pods -A              # list every Pod in every namespace ("-A" = all namespaces)
kubectl cluster-info             # confirm you're actually talking to the cluster
kubectl version                  # client and server (control plane) version
kubectl config current-context   # which cluster kubectl is currently pointed at

That last command matters more than it looks — kubectl can be pointed at any cluster you have credentials for, local or cloud. Always confirm your current context before running anything, especially once you're managing more than one cluster.

Looking ahead

Every remaining week in this course runs against this local cluster — there's no need for a cloud account until you choose to deploy for real. The same manifests you write locally are exactly what you'd apply to a managed cloud cluster (EKS, GKE, AKS) later.

5. Hands-on Exercise

Hands-on

Stand up a local cluster and explore it entirely with kubectl

Get comfortable navigating a cluster before you ever write a manifest — you'll be using these exact commands constantly for the rest of this course.

Part 1 — Set up:

  1. Install Minikube or kind, and kubectl, and start a local cluster.
  2. Run kubectl get nodes -o wide — note how many nodes you have and their status.
  3. Run kubectl get pods -A and identify at least three system Pods already running in the kube-system namespace — these are Kubernetes' own control-plane and networking components running as regular Pods on your cluster.
  4. Pick one of those system Pods and run kubectl describe pod <name> -n kube-system — skim the output for the Pod's status, container image, and recent Events.
Hint

Kubernetes runs many of its own components (like kube-proxy and CoreDNS) as Pods inside the cluster itself — this is a great, real illustration that Kubernetes largely "eats its own dog food" rather than being magic infrastructure outside the Pod model.

Part 2 — Trace a component to its role:

  1. Run an imperative test Pod (a shortcut you'll retire once Week 8 introduces manifests): kubectl run test-nginx --image=nginx.
  2. Immediately run kubectl get pods repeatedly (or add --watch) and observe the Pod moving through statuses — Pending, ContainerCreating, Running.
  3. Run kubectl describe pod test-nginx and find the "Node" field — this tells you which specific node the scheduler placed it on, and the Events section at the bottom shows the actual sequence: scheduled, image pulled, container started.
  4. Delete it: kubectl delete pod test-nginx. Write one paragraph, in your own words, tracing exactly which control-plane and node components were involved from the moment you ran kubectl run to the Pod reaching Running status.
Hint

The Events section at the bottom of kubectl describe output is one of the most useful debugging tools in all of Kubernetes — get in the habit of checking it first whenever something isn't behaving as expected, in this exercise and every week after.

6. Knowledge Check

Four quick questions. Expand each to check your answer.

Q1

What's the ONE component that reads and writes directly to etcd?

The kube-apiserver. Every other component — kubectl, the scheduler, controllers, even other control-plane pieces — interacts with cluster state exclusively through the API server, never touching etcd directly. This centralizes access control and auditing.

Q2

What decides WHICH node a new Pod gets placed on?

The kube-scheduler. It watches for Pods that have been created but not yet assigned a node, and picks a suitable one based on available resources, constraints and affinity/anti-affinity rules — the Pod itself never specifies its node directly under normal use.

Q3

What is the kubelet's job on a node?

It watches the API server for Pods assigned to its own node, and works with the local container runtime to make sure those Pods' containers are actually running and healthy — reconciling the node's real state toward what's been declared, the same declarative pattern used cluster-wide.

Q4

Does a modern Kubernetes cluster require Docker specifically to be installed on its nodes?

No. Kubernetes talks to nodes through the CRI (Container Runtime Interface), which any compliant runtime can implement — containerd and CRI-O are both common, and often don't involve the Docker daemon at all. Images built with docker build still work fine, since they're OCI-compliant regardless of which runtime eventually runs them.