Module 17 — Kubernetes, Explained as Plain Linux
Updated 3 September 2026
Kubernetes looks huge and scary. It has a hundred new words and everyone talks about it like it's rocket science. Here's the secret this module gives you: almost every part of Kubernetes is a Linux idea you already learned — just done by robots, across many machines. A container is a process. A limit is a cgroup. A volume is a mount. Once you can translate the fancy Kubernetes word back into the plain Linux thing underneath, the whole system stops being magic and starts making sense. That's the entire goal here: give you the translation key.
Legend used throughout: 🧠 concept → 🧩 analogy → 🧪 exercise → ✅ expected result (hidden) → 🎯 interview questions (hidden)
This is the victory lap of the whole track — it only makes sense because you did the earlier modules. You need Module 16 — How Containers Work most of all (a container is just a process with namespaces, cgroups, and a root filesystem — Kubernetes runs those), plus Module 2 — The Filesystem (mounts, for volumes), Module 13 — Networking (networking, for Services), Module 8 — Processes (processes), and Module 11 — systemd and Services (systemd keeping a service alive — the same idea as a Deployment). You do not need a Kubernetes cluster to follow along; the exercises run the Linux primitives that Kubernetes uses, right on one Ubuntu machine. The wording here is kept deliberately plain — this module is about understanding, not jargon.
Part A — The one big idea
A1. Kubernetes is a robot that runs Linux processes on many machines
🧠 Start with the one sentence that unlocks everything: a container is just a Linux process (you proved this in Module 16 — How Containers Work — a process with its own namespaces, a cgroup, and its own root filesystem). Kubernetes does not change that at all. Kubernetes is simply a robot that runs lots of those processes across lots of machines, and keeps them alive for you. That's the whole job. Everything else — Pods, Services, Deployments — is just organizing, naming, and automating that one thing.
🧠 The way the robot works is called a control loop, and it's as simple as a thermostat. You tell Kubernetes what you want ("I want 3 copies of my app running"). Kubernetes constantly checks what is actually true right now, compares it to what you asked for, and does whatever it takes to close the gap. One copy crashed? It starts a new one. You asked for 5 instead of 3? It starts 2 more. You never tell it the steps — you tell it the goal, and it works backwards. This "desired state vs actual state, fix the difference, forever" idea is the heart of Kubernetes.
You don't tell a thermostat "turn on the heater for 12 minutes." You tell it the goal: "I want 21°C." It checks the room temperature, compares it to your goal, and turns the heater on or off to close the gap — over and over, all day, without you thinking about it. Kubernetes is a thermostat for running programs: you set the goal ("3 copies alive"), and it keeps nudging reality toward that goal forever.
Where the analogy stops working. A thermostat controls one simple number (temperature). Kubernetes juggles many goals at once — how many copies, how much memory each gets, which machine each lands on, how they find each other — all at the same time. And a thermostat only reacts; Kubernetes also plans ahead (it picks which machine has room before it starts a program). So it's a thermostat with a scheduler and a filing system bolted on — but the core "set a goal, keep reality matching it" instinct is exactly right, and it's the thing to hold onto.
🧪 Exercise A1.1 — Remind yourself a container is just a process (read-only, safe anywhere)
ls /proc/self/ns/ # the namespaces your shell already has — a container is a process with DIFFERENT ones
nproc # how many CPUs this one machine has — a "node" is just a machine like this✅ Expected result — click to reveal
cgroup ipc mnt net pid pid_for_children time time_for_children user uts
2 (from nproc)What to read out of it:
- There's nothing new to install to "see" what Kubernetes is built on — your shell already has namespaces, and this machine already has CPUs and memory. Kubernetes doesn't invent new building blocks; it arranges the ones you already have. (The pid_for_children and time_for_children lines that also appear aren't extra namespace types — they just point to the namespace a newly-forked child would get; there are eight real types: cgroup, ipc, mnt, net, pid, time, user, uts.)
- A container is a process given fresh namespaces (its own view). A node is a machine like this one. Kubernetes is the software that decides which processes run on which machines. Keep that three-word map — process, machine, decider — and every fancy term below hangs off it.
- The rest of this module is just: "what does Kubernetes call each Linux thing, and why?" You already know the Linux things. We're only learning the new names.
A2. A Node is a Linux computer, and the kubelet is just a program on it
🧠 A Node is one Linux computer — a virtual machine in the cloud, or a physical server. A Kubernetes cluster is just a bunch of these Linux machines working together. Nothing exotic: each node runs a normal Linux kernel, exactly like the ones you've been using all track.
🧠 On every node runs one small, important program called the kubelet. Its whole job is: "wait to be told which containers I should be running, then run them." When the kubelet is told to run a container, it hands the work to a container runtime (usually containerd), which does the exact Linux steps you learned in Module 16 — How Containers Work: make new namespaces, set up a cgroup with the resource limits, put the image's files as the root filesystem, and start the process. So "Kubernetes ran my container" really means "the kubelet on some machine asked containerd to unshare + set a cgroup + pivot_root + run a process." Same Linux, one program deep.
Part A — Interview questions
🎯 "What is Kubernetes?" — the opener in almost every Kubernetes interview (GeeksforGeeks, Spacelift, DataCamp 2025–26 sets)
Kubernetes is a container orchestrator: software that runs and manages containers across many machines for you. You tell it the desired state ("run 3 copies of this app, give each 512 MB, keep them reachable"), and its control loops continuously make the real world match that — restarting crashed containers, replacing them on rolling updates, and scheduling them onto machines with room. Underneath, it runs ordinary Linux containers (processes isolated with namespaces and cgroups); Kubernetes adds the automation, scheduling, and networking to run them at scale.
The details that separate candidates: framing it as declarative (you specify the goal, not the steps) and control-loop-driven (desired vs actual, reconciled forever), and being clear that Kubernetes coordinates Linux container primitives rather than replacing them. Saying "it's a thermostat for containers" shows you actually get the model.
🎯 "What is a Node?"
A Node is a single worker machine in a Kubernetes cluster — a VM or physical server running Linux. It runs the kubelet (the agent that starts/stops containers as instructed and reports health back), a container runtime (like containerd, which does the actual namespace/cgroup/rootfs work), and kube-proxy (which programs the node's network rules for Services). The cluster's control plane schedules Pods onto nodes; the nodes are where the containers actually run.
The details that separate candidates: naming the three things on a node (kubelet, runtime, kube-proxy) and what each does, and the key insight that a node is just a Linux box — the containers on it are normal processes you could see with ps and lsns from Module 16 — How Containers Work.
Part B — A Pod is just containers sharing Linux namespaces
B1. What a Pod really is
🧠 The official definition of a Pod is "a group of one or more containers, with shared storage and network resources." That sounds abstract — until you translate it into the Linux you already know. "Shared network" means the containers in a Pod share one network namespace (Module 16 — How Containers Work): they have the same IP address, and they can talk to each other over localhost, because to the kernel they really are in the same network. "Shared storage" means they can share volumes (mounts, Part C). So a Pod is simply: a small team of containers that live in some of the same Linux namespaces.
🧠 A single container is the common case (one Pod, one container). But when you put two containers in one Pod — say, your app plus a little helper that ships its logs — they share that network namespace, which is exactly why the helper can reach the app on localhost with no setup. Behind the scenes, Kubernetes starts a tiny hidden "pause" container first, whose only job is to hold the namespaces open so the real containers can join them. That's the whole trick: a Pod is a shared namespace bag, and the containers climb into it.
Two containers in the same Pod are like two roommates sharing one apartment. They have the same street address (the same IP — mail to the apartment reaches both), they can just shout across the room to talk (that's localhost), and they share the fridge and bathroom (shared volumes). Two containers in different Pods are like people in different apartments: separate addresses, and they have to phone each other (go over the real network). Same building (node), different homes (Pods).
Where the analogy stops working. Roommates choose to live together and can rearrange the furniture; a Pod's containers are placed together by Kubernetes and share a fixed set of namespaces decided for them. And roommates fully share everything in the apartment, whereas Pod containers share only the namespaces Kubernetes wires up (network and chosen volumes) — each still keeps its own filesystem and its own process view unless told otherwise. The "same address, shared kitchen" picture is right; the "they do whatever they want" part isn't.
🧪 Exercise B1.1 — See how "same namespace = can share, different namespace = isolated" (read-only, safe anywhere)
readlink /proc/self/ns/net # the ID of THIS shell's network namespace
readlink /proc/$$/ns/net # same shell, same ID (a namespace is identified by that number)
# Two processes with the SAME net-namespace ID = a Pod (they share an IP, talk on localhost).
# Two processes with DIFFERENT net-namespace IDs = two Pods (separate IPs).✅ Expected result — click to reveal
net:[4026531840]
net:[4026531840]What to read out of it:
- That number in the brackets is the network namespace's identity. Two processes that show the same number are in the same network — same IP, can reach each other on localhost. That is precisely what "containers in one Pod" means at the Linux level.
- Two processes showing different numbers are isolated — separate IPs, must talk over the real network. That's two different Pods. So "are these in the same Pod?" is the same question as "do these processes share a net-namespace ID?" — a thing you can literally check with readlink.
- This is why the classic beginner rule "containers in a Pod talk on localhost, containers in different Pods talk over the network" is true by construction — it falls straight out of the shared-vs-separate network namespace, no Kubernetes magic required.
B2. Careful: a Kubernetes "Namespace" is NOT a Linux namespace
🧠 This is the single most confusing word in the whole ecosystem, so let's clear it up plainly. The word "namespace" means two completely different things depending on where you use it:
🧠 A Linux namespace (from Module 16 — How Containers Work) is a kernel isolation feature — it controls what a process can see (its own processes, its own network). It's low-level plumbing. A Kubernetes Namespace is something totally different: it's just a folder or label for organizing your stuff inside a cluster — a way to keep "team A's things" separate from "team B's things," or "dev" separate from "prod." It's for tidiness and access control, not kernel isolation. You could put all of team-payments' Pods, Services, and configs in a Kubernetes Namespace called payments so they're grouped and named separately from everyone else's.
Part B — Interview questions
🎯 "What is a Pod, and what's the difference between a Pod and a Container?" — GeeksforGeeks Q3 & Q7 ("What is a Pod?", "difference between a Pod and a Container?")
A container is a single running process, isolated with Linux namespaces and cgroups (Module 16 — How Containers Work). A Pod is Kubernetes' smallest deployable unit: one or more containers that share a network namespace (same IP, reach each other on localhost) and can share storage volumes. Kubernetes never schedules a bare container — it always wraps it in a Pod. Usually a Pod holds one container; multi-container Pods are for tightly-coupled helpers (a "sidecar" that ships logs or proxies traffic) that need to share the app's network and files.
The details that separate candidates: explaining the Pod in Linux terms — shared network namespace and volumes, held open by the hidden "pause" container — and knowing when to use a multi-container Pod (tightly coupled helpers) versus separate Pods (independent services). "A Pod is containers sharing some Linux namespaces" is the answer that lands.
🎯 "What is a Namespace in Kubernetes, and why do we use them?" — GeeksforGeeks Q10 (verbatim)
A Kubernetes Namespace is a way to divide one cluster into separate logical groups — a labeled bucket that holds Pods, Services, and other objects so different teams, projects, or environments (dev/staging/prod) don't collide. Names must be unique within a Namespace but can repeat across them, and you can attach resource quotas and access rules per Namespace. It is an organizational tool for multi-team clusters, not a security sandbox at the kernel level.
The details that separate candidates: explicitly distinguishing it from a Linux namespace — "same word, different concept: the Kubernetes one organizes cluster objects; the Linux one isolates a process at the kernel." Interviewers love this question precisely because it catches people who blur the two. Bonus: mention that some cluster-wide objects (Nodes, PersistentVolumes) live outside any Namespace.
Part C — Limits are cgroups, and Volumes are mounts
C1. "Requests" and "limits" are just cgroups
🧠 In a Kubernetes file you'll see something like resources: limits: memory: "512Mi". That looks like special Kubernetes syntax, but it turns into something you already know: when that Pod lands on a node, the kubelet puts its container in a cgroup with a 512 MB memory cap — the exact cgroups from Module 16 — How Containers Work. If the container tries to use more, the same per-cgroup OOM kill you met in Module 14 — Logs, Troubleshooting, and Performance fires and kills it. A CPU limit becomes a cgroup CPU quota. There's no new magic — Kubernetes is just writing cgroup settings for you.
🧠 Two words to keep straight, in plain terms. A request is "the minimum this container needs" — the scheduler uses it to pick a machine that has enough room, and reserves that much. A limit is "the hard ceiling" — the cgroup cap it can't cross. Requests are about where it gets placed; limits are about how much it can grab once running. Set memory limit too low and the container gets OOM-killed (the classic "my Pod keeps restarting").
🧪 Exercise C1.1 — Your own shell is already in a cgroup with a memory cap (read-only, safe anywhere)
cat /proc/self/cgroup | head -3 # which cgroup this process is in
cat /sys/fs/cgroup/memory/memory.limit_in_bytes 2>/dev/null \
|| cat /sys/fs/cgroup/memory.max 2>/dev/null # its memory ceiling (v1 file, then v2 file)
# a K8s "limits.memory: 512Mi" just sets a number like this for your container's cgroup✅ Expected result — click to reveal
9:name=systemd:/
4:memory:/process_api/.../claude-code-bash
0::/
6265896960What to read out of it:
- You don't need Kubernetes to be in a cgroup — every process already is. Reading the memory ceiling gives a real number of bytes. When Kubernetes runs your container with limits.memory: 512Mi, it writes 536870912 into that container's cgroup memory-limit file. Identical mechanism, Kubernetes just fills in the number from your YAML.
- So "my Pod got OOMKilled" translates to plain Linux as: "the process hit its cgroup memory limit and the kernel killed it" — the same event from Module 14 — Logs, Troubleshooting, and Performance, now triggered by a number you wrote in a Kubernetes file.
- requests behave differently: they're mainly a scheduler reservation (which machine has room), and for CPU a request also becomes the cgroup's relative-share setting (cpu.shares/cpu.weight) — but a request is never a hard cap. Only limits become an actual cgroup ceiling. That's why an under-requested but heavy Pod can crowd a node, and an under-limited one can get OOM-killed — two different knobs, two different jobs.
C2. Volumes are just Linux mounts
🧠 A container's own filesystem is throwaway — write to it and the data dies when the container is replaced (Module 16 — How Containers Work). A Volume is Kubernetes' answer, and it's the plainest translation of all: a volume is a Linux mount inside the Pod. Kubernetes mounts some storage into the container's filesystem at a path you choose, exactly like the mounts from Module 2 — The Filesystem. The different kinds of volume are just different things being mounted:
🧠 An emptyDir is a fresh temp folder shared by the containers in a Pod (a scratch space that lives as long as the Pod). A hostPath is a folder from the node itself, mounted in (literally a bind mount from the machine). A PersistentVolume is network/cloud storage mounted in, so the data survives even if the Pod moves to another machine. And ConfigMaps and Secrets are just small files mounted into the container — your config and passwords, delivered as files the app reads. Every one of these is "mount something at a path" — the Linux idea you already have.
A container's own filesystem is like a hotel-room notepad: scribble on it, and it's thrown out when you check out. A volume is like plugging in a USB stick: whatever you save there is yours to keep, and you can unplug it and plug it into a different laptop (a different Pod, even on another machine) and your files are still there. A ConfigMap/Secret is like a USB stick that came pre-loaded with a settings file for the app to read. The container doesn't care where the storage really lives — it just sees a folder that appeared at a path.
Where the analogy stops working. A USB stick is one physical object in one place; a Kubernetes PersistentVolume can be network storage that follows your Pod to whatever machine it lands on — there's no physical stick being carried around, just a mount re-created on the new node pointing at the same remote data. And unlike a USB stick you own, the lifecycle is managed by Kubernetes (it can create, attach, detach, and reclaim the storage automatically). The "keep it on the stick, not the notepad" instinct is right; the "it's a single physical thing" part isn't.
🧪 Exercise C2.1 — A volume is a mount: make one by hand (safe — done inside your own throwaway namespace)
mkdir -p /tmp/poddemo/data /tmp/poddemo/mnt
echo "config from a volume" > /tmp/poddemo/data/app.conf # pretend this is your stored data
unshare --mount --map-root-user sh -c '
mount --bind /tmp/poddemo/data /tmp/poddemo/mnt # "mount the volume into the container"
echo "container now sees the volume at /tmp/poddemo/mnt:"
cat /tmp/poddemo/mnt/app.conf
'
ls /tmp/poddemo/mnt/ # back on the host: the mount is gone✅ Expected result — click to reveal
container now sees the volume at /tmp/poddemo/mnt:
config from a volume
(the last "ls" prints nothing — the mount existed only inside the namespace)What to read out of it:
- Inside the mount namespace, mount --bind made the data appear at /tmp/poddemo/mnt, and the "container" read the file. That is exactly what Kubernetes does when it attaches a volume: it mounts storage into the container's filesystem at your chosen path. "Volume" is just the Kubernetes word for "a mount I set up for you."
- Back on the host, the same path is empty — the mount lived only inside the namespace. This is why a volume is visible inside the Pod but not scattered across the host: it's mounted into the Pod's own mount namespace, the same isolation from Module 2 — The Filesystem and Module 16 — How Containers Work.
- Swap the source of that bind mount and you get the different volume types: a temp dir → emptyDir; a node folder → hostPath; a mounted network disk → PersistentVolume; a folder of config files → ConfigMap. One Linux mechanism, several Kubernetes names.
Part C — Interview questions
🎯 "What are resource requests and limits, and what happens if a container exceeds its memory limit?"
A request is the minimum CPU/memory a container needs; the scheduler uses it to place the Pod on a node with enough capacity and reserves that amount. A limit is the maximum it may use; the node enforces it with a cgroup. If a container exceeds its memory limit, the kernel OOM-kills it (you'll see OOMKilled and a restart). Exceeding a CPU limit doesn't kill it — CPU is compressible, so the container is just throttled (slowed) via its cgroup CPU quota.
The details that separate candidates: knowing limits are enforced by cgroups (the same mechanism from Module 16 — How Containers Work/Module 14 — Logs, Troubleshooting, and Performance), and the crucial asymmetry: over-memory = killed, over-CPU = throttled. Bonus: requests affect scheduling, limits affect runtime — mixing them up is a common mistake.
🎯 "What is a Volume in Kubernetes, and why do you need one?"
A Volume is storage mounted into a Pod at a chosen path, so data can outlive the container (whose own filesystem is ephemeral) and/or be shared between containers in the Pod. Types include emptyDir (temporary, Pod-lifetime scratch), hostPath (a directory from the node), ConfigMap/Secret (config and secrets delivered as mounted files), and PersistentVolume/PersistentVolumeClaim (durable network/cloud storage that survives Pod rescheduling). Underneath, every volume is a Linux mount into the Pod's mount namespace.
The details that separate candidates: explaining why (the container filesystem is throwaway, from Module 16 — How Containers Work) and naming the right type for the job — emptyDir for scratch, PersistentVolume for a database — plus the insight that it's all just mounts. The classic red flag they probe for: storing database data with no PersistentVolume, so it vanishes on reschedule.
Part D — The robots that keep it all running
D1. A Deployment is a supervisor that keeps N copies alive
🧠 A ReplicaSet has one simple job: keep exactly N copies of a Pod running. You say "I want 3," and if one crashes or its machine dies, the ReplicaSet notices "only 2 running, I wanted 3" and starts a replacement. That's the control loop again — desired vs actual, fix the gap. In plain Linux terms it's like systemd restarting a service that crashed (Module 11 — systemd and Services), except it keeps a whole group alive and spread across many machines instead of one service on one box.
🧠 A Deployment wraps a ReplicaSet and adds safe updates. When you change your app to a new version, the Deployment rolls it out gradually — start a few new Pods, wait until they're healthy, remove a few old ones, repeat — so the app never fully goes down, and it can roll back if the new version misbehaves. So: Deployment = "keep N alive and update them safely." Almost everything you run in Kubernetes is a Deployment, precisely because you almost always want both.
A ReplicaSet is like a manager whose rule is "there must always be 3 people at the front desk." Someone calls in sick? The manager pulls in a replacement. Someone goes home? Same. A Deployment is the manager also handling shift changes: to swap the old team for a new one, they bring in a new person, make sure they know the job, then send an old one home — one at a time, so the desk is never left empty. And if the new hires are hopeless, the manager brings the old team back (rollback).
Where the analogy stops working. A human manager reacts on a timescale of minutes and can be talked into exceptions; a controller checks constantly and follows the rule with no negotiation — it will recreate a Pod you deleted "on purpose" because your declared wish still says 3. That's a feature (self-healing), but it surprises beginners who delete a Pod and watch it instantly come back. To actually remove it, you change the desired state (scale to 0 or delete the Deployment), not the Pod — you argue with the goal, not the worker.
D2. Services are DNS + a load balancer; the control plane is the brain
🧠 Pods are disposable — they get created, destroyed, and replaced constantly, and each new Pod gets a new IP address. So you can't hand out a Pod's IP; it won't be valid for long. A Service fixes this by giving a stable name and IP that always points to "whatever Pods are alive right now," and it load-balances requests across them. Under the hood, that's plain Module 13 — Networking: kube-proxy programs iptables/IPVS rules on each node to redirect the Service's IP to a real Pod, and a cluster DNS service turns the Service's name into that IP. A Service is a stable front door; the Pods behind it come and go.
🧠 Finally, the control plane is the "brain" that makes all the decisions and remembers everything: the API server (the front door you send your YAML to), etcd (the database storing the desired state), the scheduler (picks which node each new Pod runs on), and the controllers (the loops that keep reality matching the desired state). The brain decides; the kubelet on each node does the real Linux work (namespaces + cgroups + mounts). That's the entire system.
Diagram source
flowchart TD
U["You: kubectl apply -f app.yaml<br>(desired state: 3 copies, 512Mi each)"] --> API["API server (front door)"]
API <--> ETCD["etcd: stores ALL cluster state<br>(what you asked for + what is true now)"]
SCH["Scheduler: which node has room?"] -.writes Pod→node binding.-> API
KUBELET["kubelet on the chosen node"] -.watches for its Pods.-> API
KUBELET --> RUN["containerd: unshare + cgroup + pivot_root"]
RUN --> PROC["Your app = a Linux process, isolated + limited"]
CTRL["Controllers: is actual == desired?<br>if not, fix it via the API server"] -.watches.-> API
SVC["Service: stable name + IP<br>(kube-proxy iptables + DNS)"] -.routes traffic to.-> PROCPart D — Interview questions
🎯 "What is a ReplicaSet, and what is a Deployment?" — GeeksforGeeks Q8 & Q9 (verbatim)
A ReplicaSet ensures a specified number of identical Pod copies are running at all times — if a Pod or its node fails, the ReplicaSet creates a replacement to get back to the desired count (self-healing via a control loop). A Deployment is a higher-level object that manages ReplicaSets for you and adds rolling updates and rollbacks: to ship a new version it gradually replaces old Pods with new ones while keeping the app available, and can revert if something breaks. In practice you create Deployments, and they create/manage the ReplicaSets underneath.
The details that separate candidates: the layering (Deployment → ReplicaSet → Pods), that a Deployment's value-add is safe rollouts/rollbacks, and framing both as control loops (declare the goal; the controller reconciles). Comparing it to systemd keeping a service alive (Module 11 — systemd and Services), but for a group across machines, shows the Linux connection.
🎯 "What is a Service, and why do you need one if Pods already have IPs?" — GeeksforGeeks Q11 ("What is a Service?")
Because Pod IPs are not stable — Pods are created and destroyed constantly, each getting a new IP — so you can't rely on a Pod's address. A Service provides a stable virtual IP and DNS name that always routes to the currently healthy Pods behind it, and load-balances across them. Types: ClusterIP (reachable only inside the cluster, the default), NodePort (opens a port on every node), and LoadBalancer (provisions an external cloud load balancer). Under the hood it's kube-proxy programming iptables/IPVS plus cluster DNS.
The details that separate candidates: leading with the real problem (ephemeral Pod IPs), naming the three Service types and when to use each, and knowing the implementation is ordinary Linux networking rules + DNS (Module 13 — Networking) — not a mysterious black box. Bonus: a Service selects its Pods by labels.
🎯 "Explain the Kubernetes architecture." — GeeksforGeeks Q1 (verbatim)
Two halves. The control plane (the brain) runs the API server (the entry point for all commands), etcd (a key-value store holding the desired state), the scheduler (assigns new Pods to nodes based on resources), and controllers (control loops that keep actual state matching desired). The worker nodes (the hands) each run the kubelet (starts/stops containers as told, reports health), a container runtime like containerd (does the actual namespace/cgroup/rootfs work), and kube-proxy (network rules for Services). You send desired state to the API server; controllers + scheduler decide; kubelets make it real with plain Linux primitives.
The details that separate candidates: cleanly separating control plane (decides) vs nodes (do the Linux work), naming each component's one job, and connecting the bottom layer back to this whole module — a running Pod is just a process the kubelet started with namespaces, cgroups, and mounts. That closes the loop between "Kubernetes architecture" and "plain Linux."
Part E — Toolkit
E1. The translation key — every Kubernetes word in plain Linux
This one table is the whole module. Learn it and Kubernetes stops being scary.
E2. Capstone — four everyday questions, answered in plain Linux
Try each before opening the answer. These are the "do you really get it?" questions.
🎫 Ticket 1 — "Our Pod keeps restarting every few minutes. kubectl shows OOMKilled. What does that actually mean?"
In plain Linux: the process hit its cgroup memory limit and the kernel killed it. Your Pod has a limits.memory value; Kubernetes turned that into a cgroup memory cap on the container (Part C). The app tried to use more than the cap, so the kernel's OOM killer fired inside that cgroup and killed the process — exactly the event from Module 14 — Logs, Troubleshooting, and Performance and Module 16 — How Containers Work. Then the Deployment's control loop saw "a copy died, I wanted N" and started a fresh one — hence the restart-every-few-minutes cycle.
What to do: decide why it exceeds the limit. If the app genuinely needs more memory, raise limits.memory. If it grows without bound, it's a memory leak — fix it, because raising the limit just delays the next kill. Check actual usage against the limit (kubectl top pod), and make sure the limit has a little headroom. This is the #1 "my Pod keeps restarting" cause, and naming it as a plain cgroup OOM is the answer.
🎫 Ticket 2 — "Two containers in the same Pod talk to each other on localhost. How is that possible if they're separate containers?"
Because containers in one Pod share a single Linux network namespace (Part B, Module 16 — How Containers Work). A network namespace is its own private network stack — one IP, one set of ports, one localhost. When Kubernetes builds a Pod, it puts all the Pod's containers into the same network namespace (held open by the hidden "pause" container). So to the kernel they really are on the same machine's network — container A reaching container B on localhost:8080 is just two processes on one network talking to each other, which needs no routing at all.
The flip side: containers in different Pods are in different network namespaces, so they have different IPs and must talk over the real network (usually via a Service). Strong answer: "same Pod = same net namespace = same localhost; different Pods = different net namespaces = talk over the network." It's the shared-namespace idea, nothing more.
🎫 Ticket 3 — "We restarted a Pod and its data was gone. How do we keep the data next time?"
The app was writing to the container's throwaway filesystem, which is discarded when the container is replaced (Module 16 — How Containers Work). A Pod restart makes a fresh container with a fresh empty filesystem, so anything on it is lost. The fix is a Volume (Part C): storage mounted into the Pod that lives outside the container's lifecycle. For data that must survive restarts and rescheduling to another machine, use a PersistentVolume (durable network/cloud storage) via a PersistentVolumeClaim, mounted at the app's data path.
In plain Linux: a volume is a mount you set up so the important files live on separate storage, not on the disposable container layer. emptyDir survives a container restart within the same Pod but not the Pod's deletion; a PersistentVolume survives both. Strong answer names the throwaway container filesystem as the cause and the right volume type as the fix — and notes databases should basically always use a PersistentVolume.
🎫 Ticket 4 — "A teammate says 'Kubernetes is too complex to ever understand.' Explain the whole thing to them in two minutes, in Linux terms."
"It's simpler than it looks — it's mostly Linux you already know, run by a robot across many machines." A container is just a process with its own view (namespaces), its own limits (a cgroup), and its own files (an image). A Node is just a Linux machine. Kubernetes is a thermostat: you tell it the goal ("run 3 copies, 512 MB each"), and it keeps reality matching that goal — restarting anything that dies. A Pod is a couple of containers sharing a network namespace (same IP, they talk on localhost). A limit is a cgroup. A volume is a mount. A Deployment is a supervisor keeping N copies alive, like systemd for a group. A Service is a stable name and load balancer built from iptables rules and DNS. The control plane is the brain that decides; the kubelet on each machine does the actual Linux work.
Why this is the answer: it replaces a scary pile of jargon with a short list of familiar Linux ideas plus one automation loop. Anyone who understood the earlier modules can follow it. That translation — jargon back to Linux primitive — is the single most valuable thing to carry into a Kubernetes interview or your first real cluster.
E3. Documentation reference
| Kubernetes concept | Plain-Linux equivalent | Reference |
|---|---|---|
| What Kubernetes is | A robot running Linux processes on many machines | Overview · Architecture |
| Pod | Containers sharing a network namespace + volumes | Pods |
| Requests / limits | cgroup caps (memory OOM, CPU throttle) | Resource Management |
| Volume | A Linux mount into the Pod | Volumes |
| Kubernetes Namespace | An organizational label (NOT a Linux namespace) | Namespaces |
| Deployment / ReplicaSet | A supervisor loop keeping N copies alive | Deployments |
| Service | Stable name/IP + load balancer (iptables + DNS) | Service |
E4. Self-assessment
- Finish the sentences: "A container is just a . A node is just a . Kubernetes is a robot that ___."
- What is a control loop? Use a thermostat to explain how Kubernetes keeps 3 copies running.
- What is a Pod, in Linux terms? Why can two containers in one Pod talk on localhost?
- A Kubernetes Namespace and a Linux namespace — what's the difference? (This one catches people.)
- When you set limits.memory: 512Mi, what Linux thing does Kubernetes actually create? What happens if the app exceeds it?
- What is a Volume, really? Name two volume types and what each one mounts.
- What does a Deployment do that a bare Pod doesn't? What Linux tool does its "keep it alive" job remind you of?
- Why do you need a Service if Pods already have IP addresses? What is it built from under the hood?
- Split Kubernetes into "the brain" and "the hands" — name what's in each and what each does.
- Explain Kubernetes to a beginner in under two minutes using only Linux ideas.
E5. Sources
Kubernetes Overview · Cluster Architecture · Pods · Resource Management for Pods and Containers · Volumes · Namespaces · Deployments · Service
Interview questions researched from (published/updated within the last two years):
GeeksforGeeks — Kubernetes Interview Questions (2026) — "What is Kubernetes?", "What is a Pod?", "difference between a Pod and a Container?", "What is a Namespace and why do we use Namespaces?", "What is a ReplicaSet?", "What is a Deployment?", "What is a Service?", "Explain Kubernetes Architecture" (updated Aug 2026). Cross-checked against Spacelift and DataCamp 2026 sets.
Verification note: the Linux primitives shown (namespaces via /proc/self/ns/, the shared-net-namespace idea behind Pods, cgroup memory limits, and the mount --bind "volume" demo inside a mount namespace) were all run on Ubuntu 24.04 and reflect real output. The Kubernetes objects themselves (Pods, Services, Deployments) are described from the official docs, mapped onto those verified Linux mechanisms.