Linux Kernel & Security

eBPF: Công nghệ Kernel Linux Đang Thay Đổi DevOps & Security

Google, Meta, Netflix, Cloudflare — tất cả đang dùng eBPF để chạy networking, observability và security ở tốc độ kernel. Bài này giải thích đúng cơ chế eBPF hoạt động thế nào, tại sao nó nhanh hơn iptables 10x, và cách bắt đầu ngay hôm nay.

27/06/2026 18 phút đọc Võ Đào Huy Hoàng

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ự

So sánh kernel module vs eBPF
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:

✍️
1. Viết code
C subset hoặc Rust → compile bằng clang/LLVM thành eBPF bytecode
🔍
2. Verifier
Kernel kiểm tra: không loop vô hạn, không memory violation, không crash
3. JIT Compile
Bytecode → native x86/ARM code, tốc độ gần bằng kernel code gốc
🪝
4. Attach Hook
Gắn vào syscall, kprobe, XDP, TC, tracepoint — trigger khi event xảy ra

Hook Points — nơi eBPF được gắn vào

XDP (eXpress Data Path)
Chạy ngay tại NIC driver — trước khi packet vào kernel stack. Nhanh nhất, dùng cho DDoS mitigation. Cloudflare drop hàng triệu packet/s với gần 0% CPU overhead.
TC (Traffic Control)
Sau khi packet vào network stack. Dùng cho NAT, bandwidth shaping. Cilium dùng TC hook để implement Kubernetes networking thay kube-proxy.
kprobes / uprobes
Attach vào bất kỳ kernel function hay user-space function nào. Dùng cho performance profiling. Datadog dùng uprobe để trace Go/Python apps không cần instrumentation.
LSM (Linux Security Modules)
Hook vào security decision points: open file, exec, network connect. Falco và Tetragon dùng LSM để enforce security policy tại kernel level.

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.

Ví dụ: Đếm packets theo source IP (C eBPF)
// Đị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ế

🌐
Use case 1: High-Performance Kubernetes Networking
Cilium thay thế kube-proxy — Google GKE, AWS EKS đang migrate

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
🔒
Use case 2: Runtime Security Detection
Falco (CNCF) detect container escape, crypto mining tại kernel level

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
📊
Use case 3: Zero-Instrumentation APM
Grafana Beylà trace apps không cần sửa code

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
🔒
Security
Runtime protection, compliance
📊
Observability
Tracing, profiling, metrics
💻
Development Tools
Viết & debug eBPF programs

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...)

Recommendation cho team mới bắt đầu

Đừ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)

✅ Pros
  • 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
❌ Cons & Caveats
  • 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 / Not for

✅ 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.

10M+ packets/sec/core XDP
68% latency giảm (Adobe)
90% giảm effort instrumentation
2 min MTTD (Capital One)

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".