4. eBPF 观测工具链入门:安装与基本使用
在 Kubernetes 网络观测实践中,eBPF 本身是内核子系统,用户需要通过前端工具链来编写、加载和交互。本章聚焦四类主流工具链:bpftrace(快速动态追踪)、BCC(Python/Lua 前端)、libbpf(C 库/CO-RE)以及 cilium/ebpf(Go 库)。掌握它们的安装与基本用法,是构建 K8s 网络观测制品库的基础。
选型建议: 生产环境优先选择 libbpf + CO-RE 或 cilium/ebpf(Go);快速调试用 bpftrace;BCC 适合原型验证但依赖内核头文件。
4.1 工具链全景对比
| 工具链 | 语言 | 内核依赖 | CO-RE 支持 | 典型场景 |
|---|---|---|---|---|
| bpftrace | 脚本语言 | BTF / 内核头文件 | 部分(需 BTF) | 单次诊断、快速追踪 |
| BCC | Python / Lua | 内核头文件(必需) | 否 | 原型验证、教学 |
| libbpf | C | BTF(推荐) | 原生支持 | 生产级 Agent、网络观测 |
| cilium/ebpf | Go | BTF(推荐) | 原生支持 | K8s 网络策略、可观测性 |
4.2 bpftrace:快速动态追踪
bpftrace 是 eBPF 的“awk”,适合在 K8s 节点上快速排查网络延迟、丢包、系统调用异常。
4.2.1 安装
# Ubuntu / Debian
sudo apt-get install -y bpftrace
# CentOS / Rocky Linux 8+
sudo dnf install -y bpftrace
# 验证安装
bpftrace --version
4.2.2 基本使用:追踪 TCP 连接
# 追踪所有 connect() 系统调用,打印目标 IP 和端口
bpftrace -e 'kprobe:tcp_connect { printf("%s:%d -> %s:%d\n", comm, pid, ntop(2, args->sk->__sk_common.skc_daddr), ntohs(args->sk->__sk_common.skc_dport)); }'
实战提示: 在 K8s 节点上运行 bpftrace 需要
CAP_BPF 或 root 权限。建议在 DaemonSet 中以 privileged 容器运行,或使用 securityContext.capabilities.add: ["BPF"]。
4.3 BCC:Python 前端与工具集
BCC 提供丰富的现成工具(如 tcplife、tcpconnect、runqlat),适合快速获取网络和性能指标。
4.3.1 安装
# Ubuntu 20.04+
sudo apt-get install -y bpfcc-tools linux-headers-$(uname -r)
# CentOS 8+
sudo dnf install -y bcc-tools kernel-devel
# 验证工具列表
ls /usr/share/bcc/tools/ | head -20
4.3.2 基本使用:监控 TCP 连接生命周期
# 追踪 TCP 连接建立和关闭,输出 PID、端口、时长
sudo /usr/share/bcc/tools/tcplife
# 输出示例:
# PID COMM LADDR LPORT RADDR RPORT TX_KB RX_KB MS
# 12345 nginx 10.0.0.1 80 10.0.0.2 54321 2 1 45.2
注意: BCC 在编译 eBPF 程序时需要内核头文件。如果内核版本升级或头文件缺失,工具会报错。生产环境建议迁移到 libbpf + CO-RE。
4.4 libbpf:CO-RE 生产级 C 库
libbpf 是内核官方推荐的 eBPF 库,支持 CO-RE(一次编译,到处运行),无需内核头文件,是 K8s 网络观测 Agent 的首选基础库。
4.4.1 安装
# 从源码编译(推荐)
git clone https://github.com/libbpf/libbpf.git
cd libbpf/src
make
sudo make install
# 或通过包管理器(版本可能较旧)
sudo apt-get install -y libbpf-dev
4.4.2 基本使用:编写最小 eBPF 程序
// trace_open.c — 追踪 open() 系统调用
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
char LICENSE[] SEC("license") = "GPL";
SEC("tracepoint/syscalls/sys_enter_open")
int trace_open(struct trace_event_raw_sys_enter *ctx) {
char comm[16];
bpf_get_current_comm(&comm, sizeof(comm));
bpf_printk("PID %d (%s) called open()\n", bpf_get_current_pid_tgid() >> 32, comm);
return 0;
}
# 编译并加载
clang -O2 -g -target bpf -c trace_open.c -o trace_open.o
sudo bpftool prog load trace_open.o /sys/fs/bpf/trace_open
sudo bpftool prog attach /sys/fs/bpf/trace_open tracepoint syscalls sys_enter_open
# 查看输出
sudo cat /sys/kernel/debug/tracing/trace_pipe
4.5 cilium/ebpf:Go 语言生态
cilium/ebpf 是 Cilium 项目维护的纯 Go eBPF 库,无需 CGo,完美融入 K8s Operator、Controller 等 Go 应用。它是构建 K8s 网络观测制品库的核心依赖。
4.5.1 安装
# Go 1.21+ 项目
go get -u github.com/cilium/ebpf
go get -u github.com/cilium/ebpf/cmd/bpf2go
4.5.2 基本使用:Go 程序加载 eBPF 统计网络包
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -cflags "-O2 -g" bpf net_stats.c
package main
import (
"log"
"net"
"github.com/cilium/ebpf/link"
"github.com/cilium/ebpf/rlimit"
)
func main() {
// 允许当前进程锁定内存
if err := rlimit.RemoveMemlock(); err != nil {
log.Fatal(err)
}
// 加载编译好的 eBPF 对象
objs := bpfObjects{}
if err := loadBpfObjects(&objs, nil); err != nil {
log.Fatal(err)
}
defer objs.Close()
// 挂载到 lo 网卡
iface, _ := net.InterfaceByName("lo")
link, err := link.AttachXDP(link.XDPOptions{
Program: objs.XdpStats,
Interface: iface.Index,
})
if err != nil {
log.Fatal(err)
}
defer link.Close()
log.Println("eBPF XDP 程序已加载,开始统计 lo 网卡流量...")
select {}
}
4.6 工具链选择决策树
4.7 安装验证清单
| 工具链 | 验证命令 | 预期输出 |
|---|---|---|
| bpftrace | bpftrace --version |
bpftrace v0.20.x |
| BCC | sudo /usr/share/bcc/tools/tcplife |
实时 TCP 连接事件流 |
| libbpf | pkg-config --modversion libbpf |
1.4.x |
| cilium/ebpf | go list -m github.com/cilium/ebpf |
github.com/cilium/ebpf v0.16.x |
K8s 环境特别提醒: 在容器中运行 eBPF 程序需要
--privileged 或特定 capabilities(BPF、PERFMON、NET_ADMIN)。建议在 DaemonSet 的 securityContext 中显式声明,避免安全策略冲突。