eBPF 排障实战
eBPF 排障实战(应用型)
一、通用确认:节点 eBPF / v2 可用
uname -r # 确认内核 ≥ 5.10(Cilium 完整能力)
ls /sys/fs/bpf # eBPF 虚拟文件系统挂载点存在 = 可用
stat -fc %T /sys/fs/cgroup/ # cgroup2fs = v2(cgroup 级 eBPF 需要,见 [[../cgroup v2 详解]])
bpftool prog list >/dev/null && echo "bpftool OK"
二、bpftool 审计流程(黑盒排查第一步)
bpftool prog list # 1. 有哪些 eBPF 程序在跑?类型/挂载点/加载者
bpftool net # 2. 挂在哪些网卡/hook(xdp/tc)
bpftool map list # 3. map 容量和条目数(排查 map 爆了)
bpftool link list # 4. 程序与 hook 的绑定关系
# 临时摘钩验证"是不是 eBPF 干的"
bpftool net detach xdp dev eth0
三、Cilium 排障命令全集
cilium status --verbose # 整体健康(含 eBPF 程序加载)
cilium connectivity test # 内置连通性测试
cilium endpoint list # Endpoint 与策略状态
cilium bpf lb list # Service→Endpoint 映射
cilium bpf ct list global # conntrack 表
kubectl -n kube-system logs ds/cilium -c cilium-agent # agent 日志
cilium hubble port-forward & # Hubble UI
hubble observe --verdict DROPPED --last 100 # 被策略丢的流量
四、典型 Walkthrough
场景一:节点网络突然变慢,怀疑 Cilium/eBPF
cilium status --verbose # 1. Cilium 整体健康
bpftool prog list | grep -i cilium # 2. eBPF 程序真挂上、有无加载失败
cilium bpf lb list | head # 3. Service 映射完整(对比 kubectl get svc)
cilium hubble port-forward &
hubble observe --verdict DROPPED --last 100 # 4. 是不是策略把流量丢了
bpftool net detach xdp dev eth0 # 5. 怀疑 XDP 丢包,临时卸载验证(恢复后重 attach)
顺序:Cilium 健康 → eBPF 程序存在 → LB 映射正确 → 策略/丢包证据 → 临时摘钩验证。
场景二:某 Pod 偶发卡顿,怀疑存储或 syscall
# 对该 pid 看文件读延迟
bpftrace -e 'kprobe:vfs_read /pid==12345/ { @s=nsecs; }
kretprobe:vfs_read /@s/ { @us=hist((nsecs-@s)/1000); delete(@s); }'
# 同时看 on-CPU 栈热点
bpftrace -e 'profile:hz:99 /pid==12345/ { @[ustack]=count(); }'
vfs_read延迟高 → 存储/文件系统问题(结合 ../大页内存与透明大页详解 与 io 控制器);on-CPU 高但业务空闲 → 锁竞争或 GC。
场景三:P99 延迟毛刺,怀疑调度或中断
# 调度延迟(唤醒→运行)
bpftrace -e 'tracepoint:sched:sched_wakeup { @w[args->pid]=nsecs; }
tracepoint:sched:sched_switch /@w[args->next_pid]/ {
@lat=hist((nsecs-@w[args->next_pid])/1000); delete(@w[args->next_pid]); }'
# 软中断耗时(网络/存储软中断抢 CPU)
softirqs -d 1 # BCC 工具
# 中断亲和性(结合 [[../CPU 隔离与中断亲和性]])
场景四:conntrack 表打满丢包
cilium bpf ct list global | wc -l # 看 Cilium conntrack 条目数
# 若仍很高,说明 KPR 未完全覆盖跨节点 NAT
sysctl net.netfilter.nf_conntrack_max # 结合 [[../网络内核参数调优]] 调大
# 或确认 kubeProxyReplacement=strict 已开
cilium config view | grep kubeProxyReplacement
五、生产注意事项与反模式
| 注意点 | 说明 / 反模式 |
|---|---|
| verifier 报错别硬扛 | 加载失败报 permission denied 或具体拒绝原因(未校验指针、循环无界、栈超 512B)。应用型用现成工具基本不踩,自己写才需读 bpftool prog dump xlated 定位 |
| Map 容量要预估 | percpu_* / ringbuf 满后静默丢弃不报错——观测数据”看起来变少”可能是 map 爆了(bpftool map list 看 max_entries vs 实际) |
| 特权要求 | 加载需 CAP_BPF+CAP_PERFMON(新内核)或 root。容器内跑 bpftrace 要提权,本身是安全隐患 |
| 别随意加载未知程序 | eBPF 能读所有内存、插桩任意内核函数,等同内核级 rootkit。只加载可信来源(Cilium 官方、内核树工具) |
| 升级内核要回归 | eBPF 依赖内核 BPF helper 版本,跨大版本升级后老程序可能加载失败,需随 Cilium 版本一起升 |
| 多程序冲突 | 同一 hook 挂多个程序(如 XDP 有顺序),一个异常可能影响其他;用 bpftool net 看清挂载 |
| perf 采样开销 | profile:hz:99 高频采样有 CPU 开销,生产排障用完即停,勿长期开 |
| 可观测性要闭环 | bpftrace 是临时排障,长期监控接 Hubble + Prometheus(见 ../../k8s/特性详解/K8s 安全加固实战) |
反模式:把 bpftrace 脚本当长期监控(重启丢、无告警);用未校验的第三方 eBPF 二进制(等于给机器装 rootkit);在核心节点长期跑高频率 profile。
六、常见故障表
| 故障现象 | 根因 | 对策 |
|---|---|---|
| Cilium 一直 NotReady | 内核 < 5.10,eBPF 功能不全 | 升级内核 ≥ 5.15 |
| eBPF 程序加载失败 | verifier 拒绝 / helper 不支持 | 看 cilium-agent 日志,升级 Cilium |
| Hubble 无流量数据 | Hubble Relay 未启用 / 端口不通 | cilium hubble enable |
| Service 负载不均 | Maglev 一致性哈希配置 | 查 cilium config loadBalancer.algorithm |
| 启用 KPR 后部分连接异常 | 与 kube-proxy 并存冲突 | 二选一,勿同时开 |
| 节点 conntrack 仍打满 | KPR 未覆盖跨节点 NAT | 调 nf_conntrack_max,确认 strict 模式 |
| 观测数据”变少” | map 满静默丢 | 扩 map / 降采样 |
| 高频率 profile 拖慢节点 | perf 采样开销 | 用完即停 |
关联知识
- eBPF 工具链实战 — bpftool/bpftrace/BCC 命令细节
- eBPF 与 Cilium K8s 实战 — Cilium 排障命令来源
- eBPF 核心机制与安全 — verifier / map 容量的底层原因
- ../网络内核参数调优 — conntrack 调优
- ../CPU 隔离与中断亲和性 — 中断亲和性与软中断排障
学习时间
| 阶段 | 时间 | 备注 |
|---|---|---|
| 排障实战 | 2026-07-16 | 审计流程、4 个 Walkthrough(网络/Pod/延迟毛刺/conntrack)、生产反模式扩展、常见故障表 |