eBPF (extended Berkeley Packet Filter) has become one of the most important technologies in Linux-based infrastructure, yet most people who rely on it don’t know it’s running under the hood. If you use Cilium, Falco, Datadog, Cloudflare’s network stack, or modern BCC/bpftrace tooling — you’re using eBPF. Here’s the actual story.
What eBPF Is
eBPF is a runtime in the Linux kernel that allows you to run sandboxed programs in response to kernel events — without modifying kernel source code or loading kernel modules. The programs are bytecode that the kernel’s JIT compiler translates to native machine code, and they run at near-native performance.
The key insight: instead of modifying the kernel to observe or change behavior, you inject verified programs that run when specific events happen. The kernel verifies the program won’t crash or corrupt memory before running it.
Events that can trigger eBPF programs include:
- Network packet arrival/departure (where it started)
- System calls (any syscall)
- Kernel function entry/exit (kprobes)
- User-space function entry/exit (uprobes)
- Hardware performance counters
- Tracepoints throughout the kernel
This makes eBPF a general-purpose observability and enforcement substrate — far beyond its origins in packet filtering.
The Networking Use Case (Cilium)
The most mature use of eBPF in Kubernetes is Cilium — a CNI (Container Network Interface) that replaces iptables with eBPF programs for routing and policy enforcement:
# Cilium NetworkPolicy using identity-based rules
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
Why this matters over iptables:
- Performance: iptables uses linear rule chains. eBPF uses hash maps — O(1) lookups regardless of the number of rules. At scale (thousands of services, millions of connections), this difference is enormous.
- Identity-aware: Rather than matching on IP addresses (which change constantly in Kubernetes), Cilium uses cryptographic identities tied to pod labels.
- Observability baked in: Cilium Hubble gives you connection-level flow visibility across the cluster as a byproduct of how the datapath works.
Security with eBPF: Falco and Runtime Security
Traditional security tools work by monitoring syscall auditing or kernel logs. eBPF enables a lower-overhead, more granular approach:
# Install Falco with eBPF driver
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
--set driver.kind=ebpf \
--namespace falco \
--create-namespace
With eBPF, Falco can intercept every syscall with near-zero overhead and apply rules in kernel space:
# Custom Falco rule: detect container escape attempts
- rule: Container Escape via nsenter
desc: Process attempting to enter namespaces of another process
condition: >
spawned_process and
proc.name = "nsenter" and
container and
not proc.pname in (allowed_tools)
output: >
Container escape attempt (user=%user.name ns=%container.name
command=%proc.cmdline pid=%proc.pid)
priority: CRITICAL
tags: [container, escape, mitre_privilege_escalation]
The eBPF driver means Falco gets kernel-level visibility without the overhead of the older kernel module approach.
Observability: Seeing Inside Applications Without Code Changes
This is where eBPF gets genuinely remarkable. With uprobes (user-space probes), you can trace inside any running application — without source code changes, without recompilation, without restarts:
# Trace all HTTP requests in a running Go application
# No application changes needed
bpftrace -e '
uprobe:/proc/$(pgrep myapp)/exe:net/http.(*Transport).roundTrip
{
printf("HTTP request: %s\n", str(arg0));
}
'
This works because eBPF can hook into userspace code at specific function addresses. OpenTelemetry’s eBPF-based automatic instrumentation uses this to generate traces without requiring developers to instrument their code.
# OpenTelemetry eBPF-based auto-instrumentation in Kubernetes
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: auto-instrumentation
spec:
exporter:
endpoint: http://otel-collector:4317
propagators:
- tracecontext
- baggage
java:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:latest
nodejs:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-nodejs:latest
python:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-python:latest
Performance Analysis: The bpftrace Toolkit
For performance analysis on Kubernetes nodes, bpftrace and BCC tools give you capabilities that used to require kernel expertise:
# Top 10 slowest disk I/O operations
bpftrace -e '
tracepoint:block:block_rq_complete
{
@usecs[args->comm] = hist((nsecs - @start[args->sector]) / 1000);
delete(@start[args->sector]);
}
tracepoint:block:block_rq_issue
{
@start[args->sector] = nsecs;
}
END { clear(@start); }
'
# Trace all TCP connections with latency
tcplife -L 4000-8000 # From BCC tools, filter by port range
# Install BCC tools on Rocky Linux 9
dnf install bcc-tools
export PATH=$PATH:/usr/share/bcc/tools
# Useful BCC tools for Kubernetes operators
opensnoop # Trace open() syscalls - see what files are being accessed
execsnoop # Trace new process execution - spot unexpected processes
tcpretrans # Trace TCP retransmissions - network quality
biolatency # Block I/O latency histogram
runqlat # CPU scheduler run queue latency
eBPF in the Kubernetes Security Landscape
The combination of eBPF-powered security tools is becoming the standard approach for Kubernetes security:
| Layer | Tool | eBPF Use |
|---|---|---|
| Network policy | Cilium | Kernel-space packet filtering |
| Runtime security | Falco | Syscall interception |
| Service mesh | Cilium Mesh | Zero-overhead mTLS in kernel |
| Observability | Hubble | Connection-level flow data |
| Profiling | Parca/Pyroscope | Continuous CPU profiling |
The advantage over the previous generation (iptables, kernel modules, sidecar proxies) is that eBPF operates at kernel level, meaning:
- Lower overhead than userspace sidecar proxies
- Less attack surface than kernel modules (verified programs)
- No application code changes required
The Limits of eBPF
It’s not magic:
- Complexity: Writing eBPF programs requires kernel internals knowledge. The high-level tools (Cilium, Falco) abstract this, but debugging requires deeper expertise.
- Kernel version requirements: Many eBPF features require kernel 5.x or later. Rocky Linux 9 ships with kernel 5.14, which supports most production eBPF use cases.
- Verifier constraints: The kernel verifier rejects programs with unbounded loops, certain memory access patterns, and programs that are too large. This is a safety feature, but it constrains what you can express.
- Not universally portable: eBPF programs are often architecture-specific and kernel-version-specific. BTF (BPF Type Format) and CO-RE (Compile Once, Run Everywhere) are solving this, but it adds complexity.
# Check eBPF support on your nodes
uname -r # Should be 5.14+ for full feature support
bpftool feature probe # List available eBPF features
Conclusion
eBPF has gone from networking curiosity to the foundational layer of modern Linux observability, security, and networking. If you’re running Kubernetes, you’re almost certainly relying on eBPF already. Understanding what it is and how it works helps you make better decisions about your CNI, security tooling, and observability stack.
The trajectory is clear: iptables are out, kernel modules are out, sidecar proxies are being questioned. eBPF-native tooling is the direction the ecosystem is moving. Now is the time to understand it.