fivenines
5/40
Lesson 5 · Foundations

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.

Architecture — a cgroup tree with per-container budgets
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).

Sequence — a container hits its memory ceiling
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.
Next step

See what actually stuck.

Take the practice scenarios now.