【背景】
做了 15 年云原生,近几年最明显的趋势之一就是可观测栈的「去 SDK 化」:Cilium Hubble 把 L3-L7 流量直接抓出来、Tetragon 把系统调用审计做到零侵入、Pixie 在 K8s 集群里一行注解都不用就出 trace、Datadog/Coroot 把 eBPF 当底层采集引擎……
但我们团队的现实是:核心链路(Java 微服务 + Go 网关)仍然跑着 OTel Java Agent + Go SDK 埋点 + Prometheus + Tempo 这套「传统三件套」,eBPF 只做了两个小场景——Cilium 网络策略审计和节点级 CPU 调度毛刺定位。
这不是技术选型没做,而是反复权衡后「半吊子」的结果。我想抛出来让大家聊聊,到底什么场景该 all-in eBPF、什么场景 SDK 仍然不可替代?
【常见分歧 / 几种做法】
我观察到的大致三类团队:
路线 A:eBPF 打底,SDK 退到「业务语义层」
- eBPF 负责:L4/L7 流量指标、trace 骨架(kernel→userspace 全链)、系统调用审计、cgroup 资源消耗
- SDK 只保留:业务自定义 span(如「订单拆分完成」)、异常采样增强、W3C trace-context 注入
- 代表:不少用 Cilium 做 CNI 的团队,Hubble 出网络面,OTel 出应用面,中间靠 trace_id 缝合
- 痛点:两套 trace 缝合很麻烦,尤其跨语言(Java 的 OpenTelemetry context 和 eBPF 抓的 HTTP header 对不上时)
路线 B:SDK 为主,eBPF 只做安全/合规
- SDK 负责:全链路 trace、业务指标、APM 告警
- eBPF 只负责:Tetragon 系统调用审计、Falco 运行时安全、内核级 panic 追踪
- 代表:金融、政务行业居多,对「内核模块稳定性」有硬性合规要求,不敢让 eBPF 碰业务数据面
- 痛点:SDK 升级周期长(Java Agent 升级要逐服务灰度),新服务接入成本高
路线 C:双轨并行、各管各的,不缝合
- eBPF 出一套「基础设施视图」(节点/CPU/IO/网络)
- SDK 出一套「应用视图」(trace/业务指标)
- 两套数据在 Grafana 里手动对齐时间轴,不自动关联
- 代表:很多「先跑起来再说」的中小团队
- 痛点:排障时要在两套系统之间反复切换,trace_id 和 cgroup_id 对不上
【我的倾向与理由】
我倾向路线 A,但有一个前提条件:内核 ≥ 5.10 且团队有至少 1 人能读 BPF 程序。
理由:
- SDK 的维护成本被严重低估。我们 87 个微服务,Java Agent 从 1.24 升到 1.28 花了 3 周(2 个服务因为自定义 instrumentation 和 Agent 冲突,回滚了 2 次)。每升一个 OTel SDK 小版本,都要全量回归。
- eBPF 的「零侵入」在排障时是杀手锏。去年一次 P99 毛刺,SDK trace 显示某个 span 耗时 320ms 但不知道卡在哪——后来用 eBPF 抓到了
futex_wait在 JVM 锁竞争上阻塞了 280ms,这是 SDK 完全看不到的。 - 但 eBPF 不是万能的。业务语义(「这单是 VIP 客户、走了降级链路」)eBPF 抓不到,SDK 仍然是唯一载体。
所以我的判断是:eBPF 管「机器视角」,SDK 管「业务视角」,两者不是替代关系,是互补关系。 真正的问题不是「选哪个」,而是「怎么把两套数据缝起来」。
【想听大家在什么场景下怎么选】
- 你们团队现在 eBPF 和 SDK 各占多大比重?怎么分工的?
- 内核版本卡在 4.x / 5.4 的团队,eBPF 路线是不是只能等?有没有 workaround(比如 uprobe + perf 的折中方案)?
- trace 缝合你们怎么做的?trace_id 怎么从 SDK 传到 eBPF 侧?(我目前的做法是 eBPF 抓 HTTP header 里的
x-trace-id,但 gRPC 内部调用就抓不到了) - 有没有人踩过 eBPF 程序在生产环境导致节点 OOM / 软中断打满的坑?怎么防?
- 多语言栈(Java + Go + Python 混部)里,eBPF 的「一次部署、全语言覆盖」优势真的兑现了吗,还是各语言 SDK 还是逃不掉?
欢迎贴你们的具体做法、踩坑记录和数字。空对空的「我觉得 eBPF 是未来」就不聊了,我想知道你们今天生产环境里到底怎么跑的。