文章

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 listmax_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 未覆盖跨节点 NATnf_conntrack_max,确认 strict 模式
观测数据”变少”map 满静默丢扩 map / 降采样
高频率 profile 拖慢节点perf 采样开销用完即停

关联知识

学习时间

阶段时间备注
排障实战2026-07-16审计流程、4 个 Walkthrough(网络/Pod/延迟毛刺/conntrack)、生产反模式扩展、常见故障表