eBPF in 2026: The Technology Reshaping Linux Networking, Security, and Observability
on Ebpf, Linux, Networking, Security, Observability, Cloud, Kubernetes
eBPF in 2026: The Technology Reshaping Linux Networking, Security, and Observability
If you’ve used Cilium, Falco, Pixie, or Tetragon in the last few years, you’ve been using eBPF — even if you didn’t know it. Once a niche kernel hacking technique, eBPF has become foundational infrastructure. This post explains what it is, why it matters, and how to start using it.
Photo by Brett Sayles on Unsplash
What Is eBPF?
eBPF (extended Berkeley Packet Filter) lets you run sandboxed programs inside the Linux kernel without modifying kernel source code or loading kernel modules. The kernel verifies these programs before running them, guaranteeing safety.
Think of it as: a programmable hook into the kernel that is safe, fast, and doesn’t require a reboot.
The original BPF was created in 1992 for packet filtering (the tcpdump use case). “Extended” BPF arrived in Linux 3.18 (2014) and turned it into a general-purpose in-kernel VM. By 2020, it had JIT compilation on all major architectures. By 2026, it’s the de facto standard for:
- Networking: CNI plugins, load balancing, firewalling
- Security: Runtime threat detection, policy enforcement
- Observability: Low-overhead tracing without instrumentation
How eBPF Works
User Space Kernel Space
----------- ------------
eBPF bytecode ──────► Verifier (safety check)
│
JIT Compiler
│
eBPF Program ◄── Hook point (kprobe, tracepoint, XDP...)
│
eBPF Maps ◄────────────────────────────────────────
User app reads ◄───────────── │ │
maps for data └── Executes on kernel events, writes to maps ──┘
Key components:
- eBPF Programs: Written in restricted C (or Rust), compiled to eBPF bytecode
- Verifier: Kernel-level static analysis — ensures no infinite loops, no unsafe memory access
- JIT Compiler: Translates bytecode to native machine code for near-native performance
- eBPF Maps: Shared key-value stores between kernel programs and user space
- Hook Points: Where programs attach — XDP, tc, kprobes, uprobes, tracepoints, LSM hooks
Use Case 1: High-Performance Networking with XDP
XDP (eXpress Data Path) lets you process packets before the kernel’s networking stack — at the driver level. This enables line-rate packet processing in software.
// Simple XDP program to drop all packets from a specific IP
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <bpf/bpf_helpers.h>
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, __u32); // IP address
__type(value, __u8); // blocklist flag
__uint(max_entries, 1024);
} blocklist SEC(".maps");
SEC("xdp")
int xdp_filter(struct xdp_md *ctx) {
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
if ((void *)(eth + 1) > data_end)
return XDP_PASS;
if (eth->h_proto != __constant_htons(ETH_P_IP))
return XDP_PASS;
struct iphdr *ip = (void *)(eth + 1);
if ((void *)(ip + 1) > data_end)
return XDP_PASS;
__u8 *blocked = bpf_map_lookup_elem(&blocklist, &ip->saddr);
if (blocked && *blocked)
return XDP_DROP;
return XDP_PASS;
}
char LICENSE[] SEC("license") = "GPL";
Load it:
ip link set dev eth0 xdp obj filter.o sec xdp
This drops packets before they even reach the kernel’s network stack — achieving 10-100x better performance than iptables for the same operation.
Cilium uses XDP extensively for Kubernetes networking. It replaces kube-proxy entirely, implementing Service load-balancing in eBPF at the XDP layer.
Use Case 2: Zero-Overhead Observability
Traditional observability requires instrumenting your code or running sidecar proxies. eBPF enables zero-instrumentation observability — you get data without changing your application at all.
# bcc (BPF Compiler Collection) Python example
# Traces all HTTP requests across all processes without any app changes
from bcc import BPF
program = """
#include <uapi/linux/ptrace.h>
int trace_read(struct pt_regs *ctx) {
char buf[128];
u32 pid = bpf_get_current_pid_tgid() >> 32;
bpf_probe_read_user(buf, sizeof(buf), (void *)PT_REGS_PARM2(ctx));
// Filter for HTTP methods
if (buf[0] == 'G' && buf[1] == 'E' && buf[2] == 'T' ||
buf[0] == 'P' && buf[1] == 'O' && buf[2] == 'S') {
bpf_trace_printk("PID %d: %s\\n", pid, buf);
}
return 0;
}
"""
b = BPF(text=program)
b.attach_uprobe(name="c", sym="read", fn_name="trace_read")
print("Tracing HTTP reads... Ctrl+C to stop")
b.trace_print()
Tools built on this principle:
- Pixie: Full-body request tracing for Kubernetes, zero instrumentation
- Hubble: Network flow visibility for Cilium
- Pyroscope + eBPF: Continuous profiling without code changes
- Parca: Always-on profiling at 1% CPU overhead
Use Case 3: Runtime Security with LSM Hooks
eBPF + Linux Security Module (LSM) hooks enable runtime security policies that are:
- Applied without rebooting
- Updated without downtime
- Capable of blocking, not just alerting
Tetragon by Cilium is the production implementation:
# Tetragon policy: Block access to /etc/passwd from non-root
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: "block-passwd-access"
spec:
kprobes:
- call: "security_file_open"
syscall: false
args:
- index: 0
type: "file"
selectors:
- matchArgs:
- index: 0
operator: "Postfix"
values:
- "/etc/passwd"
matchCapabilities:
- type: Effective
operator: NotIn
values:
- "CAP_SETUID"
matchActions:
- action: Sigkill
When a non-privileged process tries to open /etc/passwd, the kernel kills it immediately. No userspace daemon in the hot path. This is fundamentally different from seccomp — you can match on file paths, network connections, and process ancestry.
Use Case 4: Service Mesh Without Sidecars
The traditional service mesh model (Istio, Linkerd) injects a proxy sidecar into every pod. This adds:
- ~50ms latency per hop
- Memory overhead per pod
- Complex certificate management
eBPF-based service mesh (Cilium Service Mesh, Merbridge) implements mTLS, traffic policy, and observability in the kernel:
Traditional: eBPF-based:
App → Sidecar proxy → App → eBPF socket hook →
Network → Sidecar → Network (kernel) →
App App
Benchmark results from Cilium’s 2026 report:
- Latency: 3.8ms (eBPF) vs 12.4ms (sidecar) at P99
- CPU: 0.3 cores/node (eBPF) vs 1.2 cores/node (sidecar)
- Memory: 45MB/node (eBPF) vs 180MB/node (sidecar)
Getting Started
Option 1: Use Existing eBPF-based Tools
The easiest path — these already run eBPF under the hood:
# Install Cilium (Kubernetes CNI + network policy)
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium --namespace kube-system
# Install Tetragon (runtime security)
helm install tetragon cilium/tetragon --namespace kube-system
# Install Pixie (observability)
px deploy
Option 2: Write eBPF Programs with libbpf
For custom use cases:
# Install libbpf and clang
apt install clang llvm libelf-dev linux-headers-$(uname -r)
# Compile
clang -O2 -target bpf -c my_program.c -o my_program.o
# Load with bpftool
bpftool prog load my_program.o /sys/fs/bpf/my_program
bpftool net attach xdp pinned /sys/fs/bpf/my_program dev eth0
Option 3: Use eBPF-go or libbpf-rs
For production Go or Rust programs:
// eBPF-go example
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang Filter filter.c
func main() {
objs := FilterObjects{}
if err := LoadFilterObjects(&objs, nil); err != nil {
log.Fatal(err)
}
defer objs.Close()
link, err := link.AttachXDP(link.XDPOptions{
Program: objs.XdpFilter,
Interface: iface.Index,
})
if err != nil {
log.Fatal(err)
}
defer link.Close()
// Read from maps, update blocklist, etc.
}
Limitations and Gotchas
Kernel version requirements: Many features require Linux 5.8+. Check
CONFIG_BPF_SYSCALL,CONFIG_DEBUG_INFO_BTF.Verifier complexity: The verifier rejects valid-looking programs. Loops require bounded iteration counts. The error messages are… cryptic.
BTF (BPF Type Format): Required for CO-RE (Compile Once, Run Everywhere). Most modern distros ship with BTF enabled, but check
/sys/kernel/btf/vmlinux.Not for Windows: eBPF for Windows exists but is immature. eBPF is fundamentally a Linux technology.
Security of eBPF itself: eBPF programs with
CAP_BPFcapability can read kernel memory. Compromised eBPF is very powerful. Audit what you load.
The 2026 Landscape
eBPF has crossed the chasm. It’s no longer “interesting kernel tech” — it’s infrastructure:
- Every major cloud CNI (Cilium, Calico, AWS VPC CNI) now uses eBPF
- Kubernetes 1.33 includes eBPF-accelerated service proxy as stable
- Falco 2.0 moved its core detection engine to eBPF
- Linux 6.9 extended eBPF capabilities for socket policy and HID devices
If you’re building or operating cloud infrastructure in 2026 and don’t understand eBPF, you’re increasingly flying blind. The observability, security, and networking tools you rely on are built on it.
Start with bpftrace for ad-hoc kernel debugging. Move to bcc for more structured programs. Use libbpf + CO-RE for production code. And take the eBPF.io tour — it’s the best introduction available.
Photo by Chris Ried on Unsplash
The kernel is programmable now. Use it.
이 글이 도움이 되셨다면 공감 및 광고 클릭을 부탁드립니다 :)
