eBPF: Programs in the Kernel
Kernel hooks, programs and maps without rebooting: what eBPF does, modelled honestly.
An interactive Kubernetes lesson: 23 steps, about 35 minutes, on a live simulation in your browser.
Friday night. A botnet is testing stolen cards against the shop's checkout api. Your plan: drop traffic from abusive addresses before it reaches any pod. That decision has to happen in the kernel, on the packet path.
Two Deployments serve the shop: web takes orders and api charges cards. The green stream between them is your baseline. It stays green through this whole lesson, which is the point: kernel work must never disturb it.
What you will learn
The old world
- The shop needs the kernel to change: eBPF runs your code inside the kernel at hook points, so policy decisions happen where the packets and syscalls already are.
- Kernel modules and reboots: A kernel module is full-trust code welded to one kernel build: it can crash the node and it must be rebuilt on every upgrade.
- What a filter fix costs: Without eBPF every kernel change is a rollout of reboots. That price is what the rest of the lesson removes.
Programs and maps
- Two halves: code and state: An eBPF program is event-driven kernel code: it sleeps until its hook fires, decides, and returns.
- Maps remember across events: Programs are stateless logic, maps are the state: the program decides per event, the map remembers across events.
- Unload the program, keep the map?: Pin a map and it outlives the program: unload the code, keep the state, reattach the next build to the same path.
Hooks that matter
- Drop at the earliest point: Drop as early as you can: every layer a bad packet climbs is work you paid for and used for nothing.
- The drop program in C
- Three speeds of XDP: Same XDP program, three prices: native in the driver, generic after allocation, offload on the NIC. Check which you bought.
- tc shapes what leaves: XDP guards the way in, tc polices the way out: ingress drops what should never arrive, egress shapes what you send.
- kprobes watch processes: kprobes and tracepoints turn syscalls into events: who ran what, in which container, in order.
- How events reach userspace: Events travel kernel to userspace through per-CPU ring buffers: no locks, timestamp merge on read, drops counted instead of blocking.
The verifier
- Untrusted code, checked first: The verifier proves safety before running: bounded steps, checked memory, no path it has not walked.
- A loop the verifier accepts
- Break it: an unbounded loop
Stable in production
- One binary, many kernels: CO-RE plus BTF separates what you access from where it sits: one binary, relocated at load onto each kernel.
- Filter where the data is: Decide where the data already is: a nanosecond in the kernel beats a copied event and a busy core.
- Break it: the map fills up
- Drill: list programs
- Drill: dump the map
- When eBPF is the wrong tool: eBPF observes and enforces at the kernel boundary; application decisions stay where you can test and roll them back.
Recap & playground
- Cheat sheet
- Playground