2. eBPF 基础:架构、内核钩子、Map 与 Prog 类型、开发环境搭建

2.1 eBPF 整体架构

eBPF(extended Berkeley Packet Filter)是一种在内核虚拟机中安全运行用户自定义程序的技术。其核心架构分为三部分:用户空间、内核验证器与JIT编译器、内核钩子与辅助函数。

架构要点: eBPF 程序通过 bpf() 系统调用加载到内核,经验证器检查安全性后,由 JIT 编译为原生机器码,挂载到指定内核事件点执行。
eBPF 整体架构 用户空间 (User Space) bcc / libbpf / bpftrace / Cilium Agent bpf() 系统调用 内核验证器 (Verifier) + JIT 编译器 安全性检查 | 指令重写 | 原生机器码生成 内核钩子 (Kernel Hooks) kprobes tracepoints XDP TC cgroup perf_event fentry/fexit LSM 辅助函数 (Helper) + eBPF Maps (数据结构)

2.2 内核钩子类型与适用场景

eBPF 程序通过挂载到不同的内核事件点来捕获数据。根据观测深度和性能开销,主要钩子类型如下:

钩子类型触发时机典型用途性能开销
kprobes内核指令级动态插桩函数入口/出口参数捕获中
tracepoints内核静态预定义事件系统调用、调度、网络事件低
XDP网卡驱动层(最早网络包处理点)DDoS防御、负载均衡、包过滤极低
TC (Traffic Control)内核协议栈 ingress/egress流量整形、QoS、网络策略低
fentry/fexitBPF Trampoline 优化的函数入口/出口替代 kprobes,性能更优极低
LSM (Linux Security Module)内核安全决策点自定义安全策略、运行时防护低
选型建议: 网络观测优先选择 XDP 或 TC;函数级调试用 fentry/fexit;静态事件用 tracepoints;动态插桩用 kprobes。

2.3 eBPF Map 与 Prog 类型

eBPF Map 是内核与用户空间共享的数据结构,用于状态存储、事件传递和统计聚合。Prog 是 eBPF 程序本身,不同类型对应不同挂载点和能力。

2.3.1 常用 Map 类型

Map 类型数据结构典型用途
BPF_MAP_TYPE_HASH哈希表键值存储、连接跟踪
BPF_MAP_TYPE_ARRAY数组计数器、固定索引统计
BPF_MAP_TYPE_PERCPU_HASH每CPU哈希无锁高性能统计
BPF_MAP_TYPE_RINGBUF环形缓冲区高效事件流传输(替代 perf_event)
BPF_MAP_TYPE_STACK_TRACE栈跟踪性能分析、调用栈记录

2.3.2 核心 Prog 类型

Prog 类型挂载点返回值含义
BPF_PROG_TYPE_XDP网卡驱动层XDP_DROP / XDP_PASS / XDP_TX
BPF_PROG_TYPE_SCHED_CLSTC 分类器TC_ACT_OK / TC_ACT_SHOT
BPF_PROG_TYPE_KPROBEkprobe 动态插桩无(仅观测)
BPF_PROG_TYPE_TRACEPOINTtracepoint 静态事件无(仅观测)
BPF_PROG_TYPE_CGROUP_SKBcgroup 网络控制0/1 允许/拒绝
eBPF Map 与 Prog 交互关系 内核空间 (Kernel Space) XDP Prog 包处理 TC Prog 流量控制 kprobe Prog 函数观测 BPF_MAP_TYPE_HASH 连接跟踪表 BPF_MAP_TYPE_ARRAY 包计数器 BPF_MAP_TYPE_RINGBUF 事件流输出 用户空间 (bpftool / Cilium Agent / 自定义程序) 通过 bpf() 系统调用读写 Map

2.4 eBPF 开发环境搭建

生产级 eBPF 开发主要使用 bcc(BPF Compiler Collection)和 libbpf 两种框架。bcc 适合快速原型验证,libbpf 适合生产环境部署。

2.4.1 环境依赖

  • 内核版本: ≥ 5.4(推荐 5.10+ 以获得完整特性)
  • 内核配置: 开启 CONFIG_BPF、CONFIG_BPF_SYSCALL、CONFIG_DEBUG_INFO_BTF
  • 工具链: clang ≥ 11、llvm、gcc、make、cmake
  • 库依赖: libelf、libbpf、libpcap(可选)

2.4.2 bcc 安装与验证

# Ubuntu 22.04 安装 bcc
sudo apt-get update
sudo apt-get install -y bpfcc-tools linux-headers-$(uname -r)

# 验证安装:运行 execsnoop 观测新进程
sudo execsnoop-bpfcc

2.4.3 libbpf 开发环境搭建

# 1. 安装 libbpf 开发库
sudo apt-get install -y libbpf-dev

# 2. 编译 CO-RE (Compile Once - Run Everywhere) 程序示例
git clone https://github.com/libbpf/libbpf-bootstrap
cd libbpf-bootstrap/examples/c
make

# 3. 运行最小 BPF 程序
sudo ./minimal
常见问题: 如果遇到 BTF: .BTF section not found 错误,说明内核未开启 CONFIG_DEBUG_INFO_BTF。建议升级到 Ubuntu 22.04+ 或手动编译内核开启该选项。

2.4.4 开发框架对比

特性bcclibbpf
编译方式运行时编译(Python/Lua 包装)预编译 + CO-RE
内核依赖需要内核头文件需要 BTF 信息
部署体积较大(依赖 LLVM 运行时)小(仅二进制 + .o 文件)
性能中等(运行时编译开销)高(预编译 + JIT)
适用场景开发调试、快速原型生产环境、容器化部署
生产建议: Cilium 使用 libbpf + CO-RE 模式,通过 BTF 实现内核无关性。在节点池巡检场景中,推荐使用 libbpf 编写观测程序,确保跨内核版本兼容。