2. eBPF 基础:架构、内核钩子、Map 与 Prog 类型、开发环境搭建
2.1 eBPF 整体架构
eBPF(extended Berkeley Packet Filter)是一种在内核虚拟机中安全运行用户自定义程序的技术。其核心架构分为三部分:用户空间、内核验证器与JIT编译器、内核钩子与辅助函数。
架构要点: eBPF 程序通过
bpf() 系统调用加载到内核,经验证器检查安全性后,由 JIT 编译为原生机器码,挂载到指定内核事件点执行。
2.2 内核钩子类型与适用场景
eBPF 程序通过挂载到不同的内核事件点来捕获数据。根据观测深度和性能开销,主要钩子类型如下:
| 钩子类型 | 触发时机 | 典型用途 | 性能开销 |
|---|---|---|---|
| kprobes | 内核指令级动态插桩 | 函数入口/出口参数捕获 | 中 |
| tracepoints | 内核静态预定义事件 | 系统调用、调度、网络事件 | 低 |
| XDP | 网卡驱动层(最早网络包处理点) | DDoS防御、负载均衡、包过滤 | 极低 |
| TC (Traffic Control) | 内核协议栈 ingress/egress | 流量整形、QoS、网络策略 | 低 |
| fentry/fexit | BPF 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_CLS | TC 分类器 | TC_ACT_OK / TC_ACT_SHOT |
BPF_PROG_TYPE_KPROBE | kprobe 动态插桩 | 无(仅观测) |
BPF_PROG_TYPE_TRACEPOINT | tracepoint 静态事件 | 无(仅观测) |
BPF_PROG_TYPE_CGROUP_SKB | cgroup 网络控制 | 0/1 允许/拒绝 |
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 开发框架对比
| 特性 | bcc | libbpf |
|---|---|---|
| 编译方式 | 运行时编译(Python/Lua 包装) | 预编译 + CO-RE |
| 内核依赖 | 需要内核头文件 | 需要 BTF 信息 |
| 部署体积 | 较大(依赖 LLVM 运行时) | 小(仅二进制 + .o 文件) |
| 性能 | 中等(运行时编译开销) | 高(预编译 + JIT) |
| 适用场景 | 开发调试、快速原型 | 生产环境、容器化部署 |
生产建议: Cilium 使用 libbpf + CO-RE 模式,通过 BTF 实现内核无关性。在节点池巡检场景中,推荐使用 libbpf 编写观测程序,确保跨内核版本兼容。