说明:
- 生产执行权限:大多需要
root/sudo;容器内使用需要开启特权、CAP_BPF等权限,银行生产默认禁止特权容器,一般在宿主机节点执行,不要在业务Pod内部跑。- 适用场景:Pixie / DeepFlow / Cilium Hubble 这类eBPF可观测Agent排障,核查JIT状态、程序加载、verifier报错、Map、探针、事件丢包。
- 内核前提:内核开启 BTF、
CONFIG_BPF_JIT=y,/proc/sys/net/core/bpf_jit_enable=1。
一、基础内核参数:JIT开关、BPF全局配置
bash
# 查看 BPF JIT 是否开启
cat /proc/sys/net/core/bpf_jit_enable
# 0=关闭(解释器,CPU高);1=开启;2=开启+输出JIT反汇编调试(生产不要开2)
# 查看JIT硬限制、BPF内存限制
cat /proc/sys/net/core/bpf_jit_harden
# 0:关闭加固;1:中等加固;2:完全加固(部分老eBPF程序加载失败)
# 查看 bpf syscall 最大内存锁(BPF Map会用到)
ulimit -l
# 生产eBPF场景建议调大:/etc/security/limits.conf memlock
# 查看内核编译是否开启BPF/JIT/BTF
zcat /proc/config.gz | grep -E "CONFIG_BPF|CONFIG_BTF|CONFIG_JIT"
# 关键项必须=y:CONFIG_BPF_SYSCALL, CONFIG_BPF_JIT, CONFIG_DEBUG_INFO_BTF
# dmesg 全局内核BPF日志(Verifier报错、JIT编译失败、内核panic预警首选)
dmesg | grep -i bpf
dmesg | grep -i "verifier"
dmesg | grep -i "jit"
dmesg | grep -i "bpf: failed to load program"
二、bpftool 命令(运维核心工具,查看加载的eBPF程序、Map、探针、JIT信息)
bpftool 是内核自带标准工具,优先于BCC,生产环境推荐使用。
2.1 查看当前系统上所有加载的BPF程序
bash
# 列出所有bpf程序
bpftool prog list
# 简洁输出,只看id、类型、挂载点、名称
bpftool prog list --json | jq '.[].name, .[].type, .[].id'
# 查看单个程序详细信息(替换<prog_id>,从上面list拿到id)
bpftool prog show id <prog_id>
# 查看这个程序是否JIT编译成功,JIT指令长度、BTF信息
bpftool prog show id <prog_id> --pretty
# 输出里看:jited: 1 / jited_len 非0 代表JIT编译成功;
# 如果 jited:0 → 走解释器,CPU开销会显著升高,生产红线!
# 导出JIT编译后的原生汇编(排JIT异常,仅debug,生产慎用)
bpftool prog dump jited id <prog_id>
2.2 BPF Map 查看(内核态存储,采集指标、时间戳、连接表)
eBPF采集Agent大量依赖Map保存连接信息、统计计数,Map泄漏会导致内核内存上涨
python
# 列出所有BPF Map
bpftool map list
# 查看map详情
bpftool map show id <map_id>
# dump map内数据(例如连接跟踪表,排查L7解析、连接上下文)
bpftool map dump id <map_id>
# 查看Map占用内存,判断是否内存泄漏
bpftool map show id <map_id> --pretty
2.3 查看挂载点:kprobe / tracepoint / uprobe / tc / xdp
Pixie/DeepFlow大量使用tracepoint+kprobe抓系统调用,这里排查探针是否挂上
bash
# 查看所有BPF挂载链路
bpftool link list
# 查看tracepoint挂载
bpftool tracepoint list
# 查看kprobe
bpftool kprobe list
# 查看uprobe(用户态进程探针)
bpftool uprobe list
2.4 加载/卸载BPF程序
应急场景:eBPF Agent异常,需要手动卸载故障BPF程序,防止内核资源泄漏
python
# 删除指定BPF程序(会连带link一并断开探针)
bpftool prog detach id <prog_id> link_id <link_id>
bpftool prog unload id <prog_id>
# 删除map
bpftool map delete id <map_id>
2.5 BTF 校验(CO-RE关键,国产鲲鹏/海光信创环境高频踩坑)
CO-RE(一次编译到处运行)依赖BTF,无BTF会直接导致eBPF程序加载失败
bash
# 检查内核BTF是否存在
ls /sys/kernel/btf/vmlinux
# 查看BTF信息
bpftool btf dump file /sys/kernel/btf/vmlinux format c
三、bpftrace 命令
bpftrace 基于libbpf,快速写单行eBPF脚本,排查业务延迟、系统调用、网络问题;适合SRE临时定位,不做长期监控采集(长期采集用Pixie/DeepFlow)。
3.1 基础单行示例
less
# 追踪所有进程 read 系统调用,打印进程名、返回值
bpftrace -e 'tracepoint:syscalls:sys_enter_read { @[comm] = count(); }'
# 捕获所有socket connect调用(排查连接建立慢)
bpftrace -e 'tracepoint:syscalls:sys_enter_connect { printf("PID:%d COMM:%s\n", pid, comm); }'
# 捕获TCP建立延迟(非常适合数据库慢连接排查)
bpftrace -e 'kprobe:tcp_connect { @start[tid] = nsecs; } kretprobe:tcp_connect { if (@start[tid]) { $dur = nsecs - @start[tid]; printf("tcp connect duration %dns\n", $dur); delete(@start[tid]); } }'
# 捕获mysql/数据库端口流量(快速验证L7采集能力,验证Pixie能否抓到SQL)
bpftrace -e 'tracepoint:inet:sock_recvmsg { if (args->sk->sk_dport == 3306) { printf("mysql recv pid=%d\n", pid); } }'
# 统计进程系统调用耗时分布(hist直方图)
bpftrace -e 'tracepoint:syscalls:sys_exit_write { @hist[comm] = hist(args->ret); }'
# 查看kprobe挂载失败、BTF缺失报错
bpftrace -e 'kprobe:some_nonexist_func { 1; }'
⚠️ bpftrace 注意:kprobe依赖内核函数符号,内核版本升级就失效;生产长时间运行bpftrace会增加CPU开销,用完即删。
四、Verifier报错排查
Verifier是内核安全校验器,加载eBPF程序第一步,校验失败直接拒绝加载,不会走到JIT。
常见查看方式
bash
# 方式1:dmesg 看verifier详细日志(首选)
dmesg -wH | grep -i verifier
# 方式2:bpftool加载程序时直接打印verifier日志(手动测试bpf程序)
bpftool prog load xxx.bpf.o /sys/fs/bpf/testprog
# 如果失败,终端直接输出verifier错误信息
# 常用verifier报错关键词(运维识别用,不用读完整字节码)
# - invalid access to packet
# - unbounded loop detected 【死循环】
# - pointer arithmetic on packet pointer
# - stack limit exceeded
# - BPF stack is too big
# - cannot read from unreachable stack
五、配套辅助排查命令
5.1 进程/内核资源观测
bash
# 看eBPF Agent(Pixie PEM/DeepFlow Agent)CPU、内存开销
top
htop
pidstat -u -p <agent-pid> 1
# 查看内核软中断、网络栈开销(eBPF TC/XDP会影响softirq)
cat /proc/softirqs
mpstat -P ALL 1
# 查看内核内存,确认BPF Map占用
free -h
slabtop
5.2 网络辅助,验证L7采集、TCP问题
python
# 查看socket连接,和eBPF采集到的连接对比,校验链路还原是否完整
ss -nti
# tcpdump 对照:对比eBPF抓到的流量和tcpdump是否一致(验证协议解析准确性)
tcpdump -i any port 3306
# 查看内核网络丢包
netstat -s
5.3 K8s节点内查看Agent Pod状态(Pixie/DeepFlow DaemonSet)
ini
# 查看节点上eBPF采集Agent Pod状态
kubectl get pods -n pixie -o wide --field-selector spec.nodeName=<node-name>
# 查看Agent容器日志,看探针加载、JIT、verifier报错
kubectl logs -n pixie <pem-pod-name> -c pem
六、应急运维操作清单
目标:eBPF采集异常时优先保障业务,先关停采集
- Agent CPU飙升:先修改采集规则,增加端口过滤、降低采样率;无效则重启Agent Pod
arduino
kubectl delete pod -n pixie <pem-pod>
- 内核dmesg持续bpf报错:卸载BPF程序,或者直接删除Agent Pod,DaemonSet会自动清理挂载的BPF程序(成熟eBPF Agent退出会自动清理探针,异常卡死才需要bpftool手动unload)
- JIT编译失败:检查内核版本、CONFIG_BPF_JIT,确认不是加固模式(bpf_jit_harden=2);信创内核重点核查
- 链路采集不全:检查tracepoint是否可用,端口白名单、协议解析开关;查看Agent日志是否存在协议解析报错
七、排查问题的标准顺序
cat /proc/sys/net/core/bpf_jit_enable→ 确认JIT开启dmesg | grep -i bpf→ 看verifier报错、JIT编译错误、内核警告bpftool prog list→ 确认eBPF程序是否成功加载,jited:1?bpftool link list→ 确认探针是否正常挂载(kprobe/tracepoint)- 查看Agent Pod日志 → 业务侧采集/协议解析报错
- 资源观测:pidstat/top 看Agent CPU开销
- 可选:bpftrace单行脚本做验证测试
八、常见报错关键词速查表
| 报错关键词 | 根因 | 运维对策 |
|---|---|---|
unbounded loop |
Verifier检测死循环,拒绝加载 | eBPF程序bug,升级Agent版本 |
jited:0 |
JIT未生效,解释器模式 | 开启bpf_jit_enable,检查内核CONFIG_BPF_JIT |
BTF not found |
内核缺少BTF | 升级内核或安装kernel-debuginfo,开启DEBUG_INFO_BTF |
kprobe: function not found |
kprobe目标内核符号不存在 | 尽量改用稳定tracepoint;内核版本变更导致符号消失 |
BPF stack limit exceeded |
eBPF程序栈溢出 | Agent版本bug,升级;减少采集字段 |
map create failed |
memlock ulimit太小 | 调大memlock资源限制 |