eBPF for Observability
eBPF in the Observability Stack
eBPF enables a fundamentally different approach to collecting telemetry: instead of instrumenting applications, you instrument the kernel itself. This gives you visibility into every process on a node without touching a single line of application code.
What eBPF Can Observe
Network Traffic
By hooking into syscalls like send(), recv(), connect(), and accept(), eBPF programs can:
- Capture full HTTP request/response bodies (method, path, headers, status)
- Parse database protocols (SQL queries, Redis commands, gRPC calls)
- Track TCP metrics — retransmits, drops, RTT, connection states
- Monitor DNS queries and resolution times
- Map service-to-service communication without service mesh
CPU Profiling
Using perf events, eBPF can sample CPU stack traces at regular intervals (typically ~100 Hz):
- Captures stack traces from all languages — compiled and interpreted
- Produces flame graphs showing where CPU time is spent
- Overhead is typically < 1% of CPU
- No application restart or recompilation needed
System-Level Metrics
Through tracepoints and kprobes:
- File I/O — read/write latency per file, throughput
- Disk I/O — block device latency, queue depth
- Memory — page faults, allocation patterns, OOM events
- Scheduling — run queue latency, context switches, off-CPU time
- Security — process execution, file access, network connections
eBPF-Based Observability Tools
| Tool | Focus | Description |
|---|---|---|
| Pixie | Full observability | Auto-traces protocols, CPU profiling, network monitoring. In-cluster only. |
| Grafana Alloy | CPU profiling | pyroscope.ebpf component for continuous profiling → Pyroscope |
| Cilium / Hubble | Networking | CNI with eBPF datapath; Hubble provides network flow visibility |
| Tetragon | Security observability | Process lifecycle, file access, network events for runtime security |
| bpftrace | Ad-hoc tracing | One-liner tracing tool for custom eBPF probes |
| kubectl-trace | Kubernetes tracing | Runs bpftrace programs on Kubernetes nodes |
| Inspektor Gadget | Kubernetes debugging | Collection of eBPF tools for K8s troubleshooting |
| Kepler | Energy monitoring | Estimates energy consumption of pods using eBPF + ML |
Kubernetes Requirements
Running eBPF-based tools in Kubernetes is not a simple “deploy and go” — it has specific infrastructure and security requirements:
Node-Level Requirements
| Requirement | Details |
|---|---|
| Linux kernel | 4.15+ minimum, 5.8+ recommended for full feature set (BTF, ring buffers, bpf_link) |
| BTF (BPF Type Format) | Required for CO-RE (Compile Once, Run Everywhere) — check with ls /sys/kernel/btf/vmlinux |
| Kernel headers | Some tools need them at build time; CO-RE-enabled tools avoid this |
| cgroup v2 | Required by some tools (Kepler, newer Cilium); most modern distros default to v2 |
Deployment Model
eBPF tools run as DaemonSets — one pod per node, because eBPF programs attach to the kernel of the node they run on. A single pod cannot observe other nodes.
Security & Privileges
This is the most common blocker. eBPF programs need elevated privileges to load code into the kernel:
| Approach | Capabilities | Trade-off |
|---|---|---|
| Privileged container | Full access (privileged: true) |
Simplest but broadest permissions |
| Fine-grained capabilities | SYS_ADMIN + SYS_RESOURCE + PERFMON + BPF |
More secure, but not all tools support it |
| Unprivileged eBPF | kernel.unprivileged_bpf_disabled=0 |
Very limited — only socket filters, not useful for observability |
# Typical DaemonSet security context for eBPF tools
securityContext:
privileged: true # or use fine-grained capabilities:
# capabilities:
# add: ["SYS_ADMIN", "SYS_RESOURCE", "SYS_PTRACE", "PERFMON", "BPF"]
runAsUser: 0
⚠️ PodSecurityStandards: The
Restrictedprofile blocks eBPF entirely. You need at leastPrivilegedfor eBPF DaemonSets. If your cluster enforces PSS, you’ll need a namespace-level exception for the monitoring namespace.
Volume Mounts
eBPF tools typically need access to host paths:
| Mount | Purpose |
|---|---|
/sys/fs/bpf |
BPF filesystem — for pinned maps and programs |
/sys/kernel/debug |
Debugfs — required for kprobes/uprobes on older kernels |
/proc |
Process information — PID mapping, stack traces |
/var/run/containerd or /var/run/docker |
Container runtime socket — for mapping PIDs to pods/containers |
/etc/os-release |
Kernel version detection |
Managed Kubernetes Considerations
| Provider | Support | Notes |
|---|---|---|
| AKS | ✅ | Ubuntu nodes have BTF; privileged DaemonSets allowed by default |
| GKE | ✅ | Container-Optimized OS has BTF since 5.10+; GKE Dataplane V2 uses Cilium/eBPF natively |
| EKS | ✅ | Amazon Linux 2 needs kernel 5.10+; AL2023 has full BTF support |
| OpenShift | ⚠️ | SCC (Security Context Constraints) block privileged pods by default — need privileged SCC for eBPF namespace |
Common Pitfalls
- Kernel too old — eBPF features are added incrementally; a 4.x kernel may lack ring buffers, BTF, or bpf_link
- Missing BTF — without
/sys/kernel/btf/vmlinux, CO-RE tools won’t start; some cloud images strip BTF to save space - PSP/PSS/SCC blocking — security policies reject privileged pods; must whitelist the monitoring namespace
- ARM nodes — eBPF support on ARM64 is generally good since 5.x, but some tools may not ship ARM binaries
- Windows nodes — eBPF on Windows is experimental and limited; mixed clusters need nodeSelectors to schedule only on Linux nodes
eBPF vs Traditional Instrumentation
| Aspect | eBPF | SDK / Auto-instrumentation |
|---|---|---|
| Code changes | None | SDK integration or agent |
| Language support | All (kernel-level) | Per-language SDK |
| Deployment | DaemonSet on each node | Per-application |
| Data richness | Protocol-level, system-level | Application-level, business logic |
| Custom spans/metrics | Limited | Full control |
| Overhead | < 1% | 1-5% typical |
| Encrypted traffic | Via uprobes on TLS libraries | Captured before encryption (in-process) |
| Retention | Depends on tool | Depends on backend |
When to Use eBPF-Based Observability
- ✅ Polyglot environments — many languages, no single SDK covers all
- ✅ Legacy services — can’t modify source code
- ✅ Network debugging — TCP issues, DNS failures, inter-service traffic
- ✅ Quick wins — instant visibility without development effort
- ✅ Security monitoring — process execution, file access auditing
When SDK Instrumentation Is Better
- ✅ Business-level spans — e.g., “process order”, “validate payment”
- ✅ Custom metrics — application-specific KPIs
- ✅ Cross-cluster traces — distributed trace context propagation
- ✅ Long-term storage — export to backends with configurable retention
- ✅ Fine-grained control — custom attributes, sampling strategies
💡 Best practice: Use eBPF for baseline visibility (network, CPU, system) and complement with OpenTelemetry SDK instrumentation for application-specific observability. The two approaches are complementary, not competing.
eBPF in This Workshop
In this workshop, you will encounter eBPF in two contexts:
- Pixie — uses eBPF to auto-trace protocols, profile CPU, and monitor network traffic across the cluster
- Pyroscope (via Grafana Alloy) — uses eBPF for continuous CPU profiling with
pyroscope.ebpfcomponent running as a privileged DaemonSet