eBPF Course · Lesson 8

The eBPF Observability Toolkit

A map of the tools — from bpftrace one-liners up to turnkey platforms — and how to pick the right one for the question you're actually asking.

🎯 The right tool for "what is this system really doing?"
The one idea

bpftrace is your scalpel for ad-hoc questions; above it sit BCC and libbpf for reusable, packaged tools, and turnkey platforms (Pixie, Parca, Hubble, Beyla) that run eBPF for you across a whole fleet — you choose the layer by the question you're asking.

01 The landscape as layers

Everything you'll meet in eBPF observability is one of three things: a language you type questions in, a library you build tools with, or a product that runs those tools for you. They all sit on top of the same in-kernel eBPF runtime you've been learning about — the verifier, JIT, probes, and maps from the earlier lessons. The difference is purely how much is done for you.

Think of it as a pyramid. At the bottom is the raw machinery; each layer up trades flexibility for convenience. Brendan Gregg, who wrote many of these tools, frames the front-ends exactly this way and recommends most people start near the bottom — bpftrace and BCC — before reaching for anything heavier.

Platforms Pixie · Parca · Hubble · Beyla it runs eBPF for you, fleet-wide Front-ends libbpf (C) · BCC (Python+C) · bpftrace · perf you type or build the questions bpftrace = ad-hoc · BCC/libbpf = reusable tools In-kernel eBPF runtime verifier · JIT · probes (kprobe / tracepoint / uprobe) · maps every layer above compiles down to this more done for you → more control / flexibility →
The eBPF observability stack. You reach down the pyramid for control and one-off precision; you reach up for convenience and fleet-wide, always-on coverage.
💡 The mental shortcut Ask "is this a one-off question, a tool I'll reuse, or something I want running everywhere all the time?" That single question maps directly onto the three layers.

Source: Brendan Gregg — Linux eBPF Tracing Tools, ebpf.io — Get Started.

02 bpftrace — your scalpel for ad-hoc questions

This is the tool the whole course has been built around, so just a quick recap of where it fits. bpftrace is a high-level language for writing tracing programs as one-liners or short scripts. You describe a probe and an action, hit enter, read the output, and move on. Gregg's summary: bpftrace is "for one-liners and short scripts."

# Which processes are opening files, right now?
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args.filename)); }'
Linux-only — copy and try later on a Linux box (needs sudo).

Strengths

Zero setup, instant feedback, expressive enough for histograms and aggregations, perfect for "let me just check…" investigations. The shortest path from a question to an answer.

Limits

It's a one-shot language, not a packaging system. There's no clean way to ship a polished CLI, parse fancy arguments, post-process output, or build a long-running daemon. Once you want those, you've outgrown it.

🎯 Mission fit For 80% of your "what is this thing doing?" moments, bpftrace is the answer. The rest of this lesson is about knowing when it isn't.

Source: bpftrace.org, brendangregg.com/ebpf.html.

03 BCC — a Python + C front-end, and 100+ ready-made tools

BCC (the BPF Compiler Collection, repo iovisor/bcc) is a framework for building eBPF tools where the in-kernel part is written in C and the user-space part — argument parsing, output formatting, looping — is written in Python (or C++/Lua). That split is what lets BCC tools feel like real command-line programs.

But here's the part that matters most for an observability mission: you rarely have to write any of that. BCC ships with a large library of finished, production-grade tools. Gregg notes that between the BCC and bpftrace repositories there are "over 100 tools." On many Linux distributions these are already installed under /usr/share/bcc/tools. A few you'll reach for constantly:

ToolAnswers the question…
execsnoop"What new processes are being launched?" (catches short-lived processes most monitors miss)
opensnoop"Which files is this program opening?"
biolatency"How slow is my disk I/O?" (prints a latency histogram)
tcplife"Which TCP connections happened, and how long did each live?"
# Watch every new process the moment it execs:
sudo execsnoop

# Disk I/O latency as a live histogram:
sudo biolatency

# TCP sessions to local port 80, with duration:
sudo tcplife -L 80
Linux-only — copy and try later on a Linux box (needs sudo). On Debian/Ubuntu the package is bpfcc-tools and commands may be suffixed, e.g. execsnoop-bpfcc.

When to graduate from bpftrace to BCC

Graduate when the question stops being a one-off. If you find yourself pasting the same bpftrace one-liner repeatedly, wishing it had flags, or wanting to hand a teammate a clean command — that's BCC's territory. And before writing anything yourself, check the existing tools first: the answer you want is very often already a one-word command. Gregg's own advice: "If you are looking for tools to run, try BCC then bpftrace."

Source: github.com/iovisor/bcc, brendangregg.com/ebpf.html.

04 perf — the venerable sampling tool, and how it relates to eBPF

perf predates eBPF by years. It's the standard Linux profiler for sampling (periodically snapshotting what the CPU is doing) and for reading PMCs — Performance Monitoring Counters, the CPU's built-in hardware counters for things like cache misses and instructions retired. You met its sampling style in the last lesson on flame graphs.

How does it relate to eBPF? Two ways, and both are worth keeping straight:

perf as a standalone tool

You can use perf record / perf top with no eBPF at all. It's the classic, battle-tested way to sample stacks and read hardware counters.

perf as plumbing for eBPF

eBPF reuses perf's machinery: perf events are how the kernel delivers sampling interrupts and counter reads, and an eBPF program can attach to a perf event to summarize data in-kernel instead of dumping huge capture files. The two are complementary, not rivals.

💡 Rule of thumb Reach for plain perf when you want classic CPU sampling or hardware counters. Reach for bpftrace/BCC when you want to trace specific events (a syscall, a function entry) and aggregate them cheaply in the kernel. Modern profilers like Parca (next section) blend both.

Source: Brendan Gregg — perf examples, eBPF Docs — perf_event programs.

05 C + libbpf with CO-RE / BTF — portable standalone binaries

This is the bottom-of-the-pyramid layer, and it's where the tools themselves get built. Writing eBPF in C with the libbpf library is explicitly out of scope for this course — but you should understand what it buys you, because it's why the tools above are distributable at all.

A libbpf-based tool compiles to a single self-contained binary: no Python runtime, no on-the-machine compiler, just an executable you can drop onto a server and run. The thing that makes this practical across the messy reality of different kernels is a pair of acronyms worth knowing:

CO-RE — "Compile Once – Run Everywhere"

Compile your eBPF program once on your laptop, and the same binary runs on machines with different kernel versions — no recompiling per host. It does this by embedding relocations that get fixed up at load time to match the actual kernel.

BTF — BPF Type Format

A compact description of the kernel's data-structure layout, baked into modern kernels (roughly 5.2+). CO-RE reads BTF at load time to learn where each field actually lives on this kernel and patches the program accordingly.

The problem CO-RE solves is real and used to be miserable: kernel structs change between versions — a field moves, gets renamed, or shifts offset — so an eBPF program compiled against one kernel could read garbage on another. The old fix was to ship a compiler and recompile on every host (this is, in fact, what BCC historically did). CO-RE + BTF replaces that with one portable binary.

Compile once one binary + relocations Kernel's BTF this host's struct layout Load-time fix-up offsets patched to match Runs everywhere kernel 5.10 ✓ kernel 6.2 ✓ no recompile CO-RE: Compile Once – Run Everywhere
CO-RE pairs your single compiled binary with the target kernel's own BTF, patching struct offsets at load time so one build runs across kernel versions.
💡 Why you care even though you won't write C CO-RE/BTF is why modern eBPF tools are just binaries you download and run instead of fragile per-kernel builds. It's the quiet plumbing that makes the platforms in the next section deployable across a whole fleet.

Source: eBPF Docs — BPF CO-RE, Andrii Nakryiko — BPF CO-RE.

06 Turnkey platforms — eBPF run for you, fleet-wide

At the top of the pyramid are products. You don't type probes or build tools; you deploy an agent (often one per node in a Kubernetes cluster) and it runs eBPF continuously, ships the data to a UI or backend, and gives you dashboards, maps, and queries. The trade-off versus bpftrace is the mirror image: far less control over the exact question, far more coverage with zero per-investigation effort. Each of the following is open source and uses eBPF under the hood.

Pixie

Automatic Kubernetes application observability: deploys to a cluster and uses eBPF to collect metrics, traces, request-level data, and logs with no code changes, queryable via CLI or web UI. A CNCF project.

Parca / Polar Signals

Continuous profiling: an eBPF agent samples CPU (and more) across your whole fleet at low overhead, so you always have flame graphs for "why was this slow last Tuesday?" Open-sourced by, and offered as a hosted service via, Polar Signals.

Cilium / Hubble

Hubble is the network & service observability layer on top of Cilium's eBPF networking — it shows live service-to-service flows, dependency maps, and L3–L7 metrics (DNS, HTTP) plus security events, with no app changes. (Networking is beyond our mission, but it's part of the map.)

Grafana Beyla

Auto-instrumentation: an eBPF agent that watches your services and emits RED metrics (Rate, Errors, Duration) and distributed traces as OpenTelemetry / Prometheus data — across Go, Java, Python, Node, .NET — without touching the application's code.

⚠️ Don't conflate these They are not interchangeable. Pixie = broad K8s app telemetry. Parca = profiling specifically. Hubble = network flows. Beyla = auto metrics+traces. Picking by buzzword instead of by question is the most common platform mistake.

Sources: px.dev (Pixie), parca.dev, github.com/cilium/hubble, grafana.com/docs/beyla.

07 The decision guide — pick by the question

Strip everything above down to a single reflex: match the shape of your question to a layer.

What's the shape of the question? one-off "let me check…" reusable CLI / tool always-on, fleet-wide bpftrace one-liner, instant answer, then move on BCC or libbpf check existing BCC tools first; build with libbpf if shipping a binary A platform Pixie · Parca · Hubble · Beyla deploy once, runs continuously
The whole toolkit in one reflex: ad-hoc → bpftrace; reusable tool → BCC/libbpf; always-on across a fleet → a platform.
Your situationReach forEffortScope
"Let me just check what's opening these files."bpftraceSecondsOne host, one question, now
"I keep needing this — give me a real command."BCC tool (often already exists)LowOne host, repeatable
"Ship a single portable binary to many servers."libbpf + CO-REHigh (writes C)Many hosts, one tool
"Always-on app telemetry across a K8s cluster."PixieDeploy onceFleet, continuous
"Always-on CPU profiles I can look back at."ParcaDeploy onceFleet, continuous
"See live service-to-service network flows."Hubble (Cilium)Deploy onceFleet, continuous
"Auto metrics + traces, no app changes."BeylaDeploy onceFleet, continuous

A couple of BCC invocations to keep in your back pocket for the "reusable tool" row — copy them for later:

# "Who is launching processes on this box?"
sudo execsnoop

# "How long do my TCP connections live, with bytes moved?"
sudo tcplife
Linux-only — copy and try later on a Linux box (needs sudo; package bpfcc-tools on Debian/Ubuntu).
🎯 Mission fit You don't need to install a platform to be effective. For your spare-time, "what is this doing?" learning, bpftrace plus a handful of BCC tools covers almost everything — the platforms are simply what the same eBPF foundation looks like when a team needs it running everywhere, forever.

08 Check yourself

You're debugging one server and want a quick, one-off answer to "which processes are calling this syscall right now?" Which tool fits best?
What does CO-RE (with BTF) primarily give you?
Which statement correctly pairs the platforms with what they're for?
What's the key difference between bpftrace and BCC?

09 Flashcards

Q: In one line, what is bpftrace for?
A: A high-level language for ad-hoc tracing — one-liners and short scripts you type to answer a question right now, then move on. The scalpel at the bottom-middle of the pyramid.
Q: What is BCC, and why is it valuable even if you never write code?
A: The BPF Compiler Collection — a Python+C framework for building reusable eBPF tools. Crucially, it ships a large library of finished tools (execsnoop, opensnoop, biolatency, tcplife, …); between BCC and bpftrace there are 100+ ready to run.
Q: How does perf relate to eBPF?
A: perf is the classic Linux sampling/PMC (hardware-counter) profiler. It works standalone, and it's also plumbing for eBPF: perf events deliver sampling interrupts and counter reads that eBPF programs can attach to and summarize in-kernel. Complementary, not rivals.
Q: What does libbpf give you that bpftrace and BCC don't?
A: A way to build a single self-contained binary — no Python, no on-host compiler — that you can drop onto servers and run. It's how distributable eBPF tools are made (the C-writing layer that's out of scope for this course).
Q: What do CO-RE and BTF mean, and what problem do they solve?
A: CO-RE = "Compile Once – Run Everywhere." BTF = BPF Type Format, a description of kernel struct layouts baked into modern kernels (~5.2+). Together they let one compiled binary run across different kernel versions by patching struct offsets at load time — solving the old problem of recompiling per kernel.
Q: Which platform is for continuous CPU profiling across a fleet?
A: Parca (open-sourced by Polar Signals) — an eBPF agent that continuously samples profiles across your infrastructure at low overhead, so you always have flame graphs to look back at.
Q: Which platform is for network/service-flow observability, and what is it built on?
A: Hubble — the network, service, and security observability layer built on top of Cilium's eBPF networking. It shows live service-to-service flows, dependency maps, and L3–L7 metrics with no app changes.
👩‍🏫 I'm your teacher — ask me anything

Want to go deeper on any layer? Ask me things like "walk me through what an execsnoop run actually prints, line by line" or "why would I pick Beyla over Parca if I already have Prometheus?" — or have me turn one of these BCC tools into the equivalent bpftrace one-liner so you can see the trade-off concretely.