1. Vấn đề trước khi có eBPF
Hãy tưởng tượng bạn cần monitor toàn bộ network traffic của 500 container trên Kubernetes — xem chính xác pod nào đang gọi đến đâu, packet nào bị drop, latency p99 từng service. Cách truyền thống là gì?
- ❌ tcpdump / libpcap — copy toàn bộ packet lên userspace, tốn CPU 15-30%, không scale được
- ❌ iptables — rule-based, O(n) lookup, 10,000 rules = latency tăng hàng chục ms, không có visibility
- ❌ Kernel module — phải viết C, compile lại, reboot, kernel panic nếu bug → không ai dám dùng ở production
- ❌ Sidecar proxy (Istio) — mỗi pod thêm 1 Envoy, tốn 50-100MB RAM/pod, thêm 1ms latency/hop
Bài toán cốt lõi: Kernel Linux có quyền kiểm soát toàn bộ hệ thống (network, process, memory), nhưng muốn thêm logic vào kernel thì phải viết kernel module — nguy hiểm, chậm phát triển, không an toàn. eBPF giải quyết đúng bài toán này: chạy code tùy chỉnh bên trong kernel, an toàn, hiệu năng native.
2. eBPF là gì? Cơ chế thực sự
| Tiêu chí | An toàn | eBPF |
|---|---|---|
| An toàn | ❌ Kernel panic nếu bug | ✅ Verifier kiểm tra trước khi load |
| Deploy | ❌ Recompile + reboot | ✅ Load tại runtime, không reboot |
| Hiệu năng | ✅ Native | ✅ JIT-compiled, gần native |
| Versioning | ❌ Tied to kernel version | ✅ Portable với BTF/CO-RE |
| Khó | ❌ Rất khó (kernel API) | ⚠ Trung bình (C subset + tools) |
Điểm then chốt: eBPF dùng một verifier — trước khi load program vào kernel, verifier kiểm tra toàn bộ control flow, đảm bảo chương trình không thể gây crash, loop vô hạn, hay truy cập memory trái phép. Nếu pass verifier → JIT compiler biên dịch thành native machine code → chạy nhanh như kernel code gốc.
3. Kiến trúc — eBPF hoạt động thế nào
Một eBPF program đi qua pipeline sau trước khi thực thi:
Hook Points — nơi eBPF được gắn vào
eBPF Maps — cách truyền data giữa kernel ↔ userspace
eBPF programs không có state — mỗi lần trigger là một lần chạy độc lập. Để lưu và chia sẻ data, eBPF dùng Maps — key-value store sống trong kernel memory, đọc được từ userspace.
// Định nghĩa Map: key = src IP, value = packet count
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key, __u32); // source IP
__type(value, __u64); // packet count
} packet_count SEC(".maps");
// XDP program — chạy khi packet đến NIC
SEC("xdp")
int count_packets(struct xdp_md *ctx) {
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct iphdr *ip = data + sizeof(struct ethhdr);
if ((void *)(ip + 1) > data_end) return XDP_PASS;
__u32 src_ip = ip->saddr;
__u64 *count = bpf_map_lookup_elem(&packet_count, &src_ip);
if (count)
__sync_fetch_and_add(count, 1);
elsẽ {
__u64 one = 1;
bpf_map_update_elem(&packet_count, &src_ip, &one, BPF_ANY);
}
return XDP_PASS;
}
Từ userspace (Python/Go/Rust), bạn đọc map này ra để hiển thị stats. Đây là pattern cơ bản: kernel collects → userspace displays.
4. 3 Use cases thực tế
Vấn đề: kube-proxy dùng iptables để route traffic. Cluster 1000 nodes + 10,000 services = ~100,000 iptables rules. Mỗi connection traversẽ toàn bộ chain → latency tăng tuyến tính.
Cilium giải quyết: Thay iptables bằng eBPF programs dùng hash map O(1) lookup. Adobe (50,000 pods): latency p99 giảm 68%, throughput tăng 40% sau migrate.
$ helm install cilium cilium/cilium --namespace kube-system \
--set kubeProxyReplacement=strict \
--set k8sServiceHost= \
--set k8sServicePort=6443
Vấn đề: Container escape attack — attacker compromisẽ pod rồi exec shell sang pod khác. Tools userspace-based có thể bị bypass qua syscall trực tiếp.
Falco + eBPF: Hook vào syscall entry points trong kernel. Nếu nginx container gọi execve("/bin/bash") → alert ngay lập tức. Capital One giảm Mean Time to Detect từ 24h xuống 2 phút.
# Falco rule: detect shell spawn trong container
- rule: Terminal shell in container
condition: spawned_process and container and shell_procs and proc.tty != 0
priority: WARNING
Vấn đề: Tracing microservices yêu cầu thêm SDK vào từng service. 200 services × 5 ngôn ngữ = không thực tế.
Grafana Beyla: Dùng uprobe attach vào Go runtime, Python interpreter, Node.js — tự động capture HTTP requests, DB queries, gRPC calls không cần thêm một dòng code. Shopify deploy Beylà trên 3,000 services, giảm 90% instrumentation effort, overhead <2% CPU.
$ helm install beylà grafana/beylà \
--set beyla.config.discovery.services[0].name="*" \
--set otel.metrics.endpoint=http://otel-collector:4318
# Không restart app, không sửa Dockerfile
5. Hệ sinh thái công cụ eBPF (2026)
Thay vì viết eBPF C từ con số 0, 99% use cases dùng high-level tools. Dưới đây là stack thực tế đang dùng ở production:
Networking — CNI, load balancing, service mesh
Cilium — CNI standard cho k8s, replace kube-proxy, implement NetworkPolicy, L7 visibility
Katran — Facebook/Meta layer-4 load balancer, XDP-based, 10M pps/core
Envoy + eBPF — data plane acceleration cho service mesh
Kube-router — kube-proxy replacement nhẹ hơn Cilium
Security — Runtime protection, compliance
Falco (CNCF graduated) — syscall-level threat detection, rules engine linh hoạt
Tetragon (Isovalent) — security observability + enforcement, file integrity monitoring
Tracee (Aqua Security) — runtime security, container forensic
KubeArmor — LSM-based policy enforcement cho k8s (AppArmor/SELinux alternative)
Observability — Tracing, profiling, metrics
Grafana Beyla — zero-code auto-instrumentation, eBPF uprobe-based
Pixie (New Relic) — auto-telemetry cho k8s, không cần sidecar
Parca — continuous profiling, flame graphs từ eBPF sampling
bpftrace — high-level tracing language, one-liners cho debug production
Development Tools — Viết & debug eBPF programs
libbpf + bpftool — kernel official toolchain, C API, CO-RE support
Aya — Rust library để viết eBPF programs, type-safe, modern
eunomia-bpf — Wasm-based eBPF, chạy portable trên mọi kernel version
bcc — Python frontend cho eBPF, rich tool set (opensnoop, execsnoop, biosnoop...)
Đừng viết eBPF C ngay. Bắt đầu với bpftrace (one-liner debug), sau đó bcc tools (có sẵn 100+ tools), mới đến Aya (Rust) khi cần custom program. Cilium/Falco/Beylà đã cover 90% use cases infra.
6. Getting Started — Cài và chạy ngay hôm nay
Yêu cầu hệ thống
- ✅ Linux kernel ≥ 5.10 (BTF + CO-RE support tốt)
- ✅ Kernel headers:
apt install linux-headers-$(uname -r) - ✅ Clang/LLVM ≥ 12:
apt install clang llvm libbpf-dev - ✅ bpftrace/bcc (optional):
apt install bpftrace bpfcc-tools
Demo 1: bpftrace one-liners (không cần code)
# Trace tất cả file opens
$ sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }'
# Xem latency của read() syscall
$ sudo bpftrace -e 'kprobe:vfs_read { @start[tid] = nsecs; } kretprobe:vfs_read /@start[tid]/ { @ns = hist(nsecs - @start[tid]); delete(@start[tid]); }'
# Đếm process execution
$ sudo bpftrace -e 'tracepoint:sched:sched_process_exec { @[comm] = count(); }'
Demo 2: Viết eBPF program bằng Aya (Rust) — 50 lines
Tạo project count packets per IP bằng XDP:
# 1. Cài toolchain
$ cargo install cargo-bpf bpf-linker
$ rustup target add bpfel-unknown-none
# 2. Tạo project
$ cargo new --bin my-ebpf && cd my-ebpf
$ cargo bpf new xdp_counter
# 3. Code eBPF (src/bpf/xdp_counter.bpf.rs)
use aya_bpf::{bindings::xdp_action, macros::xdp, programs::XdpContext};
use aya_log_ebpf::info;
#[xdp(name="xdp_counter")]
pub fn xdp_counter(ctx: XdpContext) -> u32 {
match try_count(ctx) {
Ok(ret) => ret,
Err(_) => xdp_action::XDP_ABORTED,
}
}
fn try_count(ctx: XdpContext) -> Result<u32, u32> {
info!(&ctx, "Received packet");
Ok(xdp_action::XDP_PASS)
}
# 4. Build & load
$ cargo bpf build --release
$ sudo cargo run --release
# 5. Xem log kernel
$ sudo cat /sys/kernel/debug/tracing/trace_pipe
Demo 3: Deploy Cilium + Hubble UI (visualize network flows)
# Cài Cilium CLI
$ curl -L --remote-name-all https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz
$ sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
# Install Cilium CNI + Hubble UI
$ cilium install --version 1.15.0 \
--set kubeProxyReplacement=strict \
--set hubble.ui.enabled=true \
--set hubble.metrics.enabled="{dns,drop,tcp,flow,port-distribution,icmp,http}"
# Port-forward Hubble UI
$ cilium hubble ui
# Mở http://localhost:12000 — xem real-time network graph giữa pods!
7. Pros & Cons thực tế (2026 production view)
- Hiệu năng kernel-level — XDP process 10M+ packets/sec/core, 0-copy
- Zero instrumentation — trace apps Go/Python/Java không sửa code (Beyla, Pixie)
- An toàn — Verifier đảm bảo không crash kernel, memory safe by design
- CO-RE (Compile Once Run Everywhere) — binary eBPF chạy trên kernel 5.10+ không rebuild
- Deep visibility — thấy được syscall, packet, CPU, memory, lock contention từ kernel
- Dynamic — load/unload programs runtime, không reboot, không restart app
- Learning curvề dốc — kernel concepts, verifier restrictions, C subset limitations
- Kernel version dependency — features mới cần kernel 5.15+ (BTF), 6.0+ (kfuncs), RHEL 8/9 cần backport
- Verifier reject — code phức tạp dễ bị reject, phải restructure logic để pass verification
- Debug khó — không có debugger truyền thống, dùng trace_pipe/bpftool, log từ kernel
- Privileged access — cần CAP_BPF + CAP_SYS_ADMIN (root), security team thường restrict
- Memory limit — maps giới hạn size, programs giới hạn 4096 instructions (tăng được qua tail calls)
✅ BEST FOR:
- Kubernetes networking at scale (Cilium)
- Runtime security monitoring (Falco)
- Zero-code APM (Beyla, Pixie)
- Performance profiling production (Parca)
- DDoS mitigation at NIC level (XDP)
❌ NOT FOR:
- Simple firewall rules (dùng iptables/nftables)
- Team không có Linux kernel background
- Kernel < 5.10 (không BTF/CO-RE)
- Quick scripts — dùng bpftrace thay eBPF C
- User-space logic có thể giải quyết tốt
💻 Code Example: eBPF XDP Program
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
SEC("xdp")
int count_packets(struct xdp_md *ctx) {
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;
// Count packets by protocol
u32 proto = eth->h_proto;
u64 *count = bpf_map_lookup_elem(&packet_count, &proto);
if (count) __sync_fetch_and_add(count, 1);
return XDP_PASS;
}
6. Kết luận — eBPF đã sẵn sàng cho production
eBPF không còn là "future technology" — nó đang chạy production tại Google, Meta, Netflix, Cloudflare, Adobe, Capital One, Shopify ngay hôm nay. Linux kernel 6.x trở đi có sẵn BTF, CO-RE, kfuncs — mọi feature cần thiết cho eBPF portable đã ổn định.
Nếu bạn là System/Network/Security Engineer — eBPF là skill bắt buộc 2026. Bắt đầu hôm nay: cài bpftrace, chạy vài one-liner, sau đó deploy Cilium lên dev cluster. 1 tuần sau bạn sẽ hiểu tại sao kernel team nói "eBPF is eating the world".