sn sysnerdunderstand it from the kernel up
← curriculum map
Kubernetes
Core · ~120 min · 6 labs
map / The stack / Kubernetes
The stack Core ~120 min requires: Docker

Kubernetes

Kubernetes is a distributed reconcile loop: a database of desired state (etcd) and controllers grinding reality toward it. Every feature is that loop plus a Linux primitive you already know.

Before you start. Install kind (Kubernetes in Docker) and kubectl on a real Linux host. kind create cluster gives you a real multi-component cluster locally, no cloud.
Q1Stand up the control planecore

The control plane is a set of processes: API server (the front door), etcd (the state store), scheduler (placement), controller-manager (the reconcile loops).

Task

Create a cluster and list the control-plane components running as pods.

Verify it yourself
verify
$ kubectl get pods -n kube-system

You'll see etcd, kube-apiserver, kube-scheduler, kube-controller-manager, coredns, and kube-proxy — the whole machine, laid out.

Reveal solution
solution
$ kind create cluster --name gw
$ kubectl get pods -n kube-system
Q2A Pod is a shared network namespacecore

Containers in a Pod share one network namespace (and one IP) held open by a tiny pause container — the same namespace sharing you did with ip netns.

Task

Run a 2-container pod and confirm both see the same IP.

Verify it yourself
verify
$ kubectl exec pod/shared -c a -- hostname -i

Both containers report the same pod IP — because they share one net namespace, just like your hand-wired namespaces.

Reveal solution
solution
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata: {name: shared}
spec:
  containers:
  - {name: a, image: busybox, command: ["sleep","3600"]}
  - {name: b, image: busybox, command: ["sleep","3600"]}
EOF
$ kubectl exec pod/shared -c a -- hostname -i
$ kubectl exec pod/shared -c b -- hostname -i
Q3The reconcile loop, livecore

A Deployment declares "I want N replicas." A controller continuously makes reality match. Delete a pod and watch desired-state win.

Task

Create a 2-replica Deployment, delete a pod, watch it come back.

Verify it yourself
verify
$ kubectl get pods -l app=web

Kill one pod and a replacement appears within seconds — the reconcile loop restoring desired state. This is the idea Terraform shares.

Reveal solution
solution
$ kubectl create deploy web --image=nginx --replicas=2
$ kubectl delete pod -l app=web --field-selector=status.phase=Running | head -1
$ kubectl get pods -l app=web -w
Sponsored

Reach engineers who read the man page

Native, contextual, no tracking — this is how the curriculum stays free.

Q4A Service is iptables (kube-proxy)core

A ClusterIP Service is a virtual IP with no process behind it. kube-proxy programs iptables so packets to that IP get DNAT'd to a real pod — the same netfilter Docker used for -p.

Task

Expose the Deployment and find the iptables rules kube-proxy wrote.

Verify it yourself
verify
$ docker exec gw-control-plane iptables -t nat -L KUBE-SERVICES -n | grep web

The Service ClusterIP appears in the KUBE-SERVICES chain, routing to pod endpoints. Services are netfilter, all the way down.

Reveal solution
solution
$ kubectl expose deploy web --port 80
$ kubectl get svc web
$ docker exec gw-control-plane iptables -t nat -L KUBE-SERVICES -n | grep web
Q5CoreDNS resolves service namescore

Pods find Services by name through cluster DNS (CoreDNS), which maps web.default.svc.cluster.local to the ClusterIP.

Task

From a throwaway pod, resolve the Service name.

Verify it yourself
verify
$ kubectl run t --rm -it --image=busybox --restart=Never -- nslookup web

It resolves web.default.svc.cluster.local to the ClusterIP — DNS + Services working together.

Reveal solution
solution
$ kubectl run t --rm -it --image=busybox --restart=Never -- nslookup web
Q6Break-and-fix — the empty endpointsdebug

A Service sends traffic to Pods matched by its selector. If the selector's labels don't match any ready pod, the Service has zero endpoints and silently blackholes traffic — the single most common K8s networking bug.

Task

Create a Service whose selector matches nothing, see empty endpoints, then fix the labels.

Verify it yourself
verify
$ kubectl get endpoints web2

Endpoints start empty (selector mismatch). Fix the selector to match the pod labels and endpoints populate — traffic flows.

Reveal solution

Always check kubectl get endpoints <svc> first when a Service "doesn't work". Empty endpoints = selector/label mismatch.

solution
$ kubectl create svc clusterip web2 --tcp=80:80   # selector app=web2, but pods are app=web
$ kubectl get endpoints web2   # empty!
$ kubectl label pods -l app=web app=web2 --overwrite
$ kubectl get endpoints web2   # now populated
What you just built

Reconcile loop + etcd + shared namespaces + iptables Services + CoreDNS + CNI — Kubernetes is orchestration over the exact primitives from Linux and Docker. The magic is gone; the understanding stays.