Cgroups: The Meters
In one sentence: Namespaces control what a container can see; control groups (cgroups) control what it can use — CPU, memory, disk I/O, process count — via a kernel-managed hierarchy of limits.
You already know
- From Lesson 4: namespaces build walls around visibility, one wall per resource.
- From Lesson 2's sequence: the engine "applies resource limits (cgroups)" right after creating namespaces.
A tree of budgets
Cgroups form a tree. Each node carries resource budgets — memory ceiling, CPU weight or quota, I/O bandwidth, max PIDs — and every process belongs to exactly one node. Children can never exceed their parent's budget, which gives you delegation for free: give all containers a shared parent with 8 GB, and no misbehaving child can starve the host even if its own limit is generous. The engine's job is bookkeeping only — it creates a node per container and writes the limits; the kernel enforces them on every allocation and every scheduler tick.
flowchart TB ROOT["root cgroup
(all host resources)"] SYS["system.slice
sshd, journald …"] MD["minidock.slice
budget: 8 GB, 6 CPU"] C1["container A
mem 2 GB · cpu 1.0"] C2["container B
mem 4 GB · cpu 2.0"] C3["container C
mem 1 GB · cpu 0.5"] ROOT --> SYS ROOT --> MD MD --> C1 MD --> C2 MD --> C3
What enforcement feels like
Limits differ in personality. CPU limits throttle: exceed your quota and the scheduler simply stops running you until the next period — the app gets slow, not dead. Memory limits kill: when a cgroup's usage hits its ceiling and nothing can be reclaimed, the kernel's OOM killer terminates a process inside that cgroup (and only that cgroup — the blast radius is the budget node, never the host).
sequenceDiagram participant E as Engine participant K as Kernel (cgroups) participant C as Container B E->>K: create node, write mem.max = 4 GB E->>K: place container B's process in node C->>K: allocate… allocate… (usage 3.9 GB) C->>K: allocate 200 MB K->>K: over ceiling, nothing reclaimable K->>C: OOM-kill process inside this cgroup only K-->>E: event: container B OOM-killed note over E: engine records exit reason
(Lesson 21 decides whether to restart)
Anchor these
- Namespaces = visibility, cgroups = consumption. A container needs both.
- Budgets form a tree; children can't outspend parents — blast radius is contained by design.
- CPU overuse throttles; memory overuse kills. The engine writes budgets, the kernel enforces.
See what actually stuck.
Take the practice scenarios now.