在云原生与微服务架构下,一套生产系统往往横跨 Go、Ja va、Python、Node.js 等多种语言运行时,部署形态又散落在容器、Kubernetes、Serverless 之间。要在这样的异构环境里建立统一的可观测性,传统做法是为每种语言挂载侵入式 Agent 或 SDK——改代码、装包、对齐版本、重新发布,每接入一个新服务都是一次工程项目。在快速迭代的研发节奏下,这种“接入即改造”的成本越来越难以承受。
与此同时,AI Agent 应用正从单次 LLM 调用演变为多步编排的复杂工作流——一次用户请求可能触发数十次大模型调用、工具执行(Tool Call)和向量检索,调用链跨越 Agent 编排层、LLM Provider、向量数据库和外部工具,传统 APM 难以完整覆盖,零代码的可观测性方案在 AI 场景同样不可或缺。
eBPF 提供了另一条思路:在 Linux 内核里挂载安全沙箱化的探针,不修改应用、不重启进程,就能观测进出每个进程的网络流量、库函数调用乃至系统调用。基于这一能力,零代码、跨语言、低开销的可观测性方案开始成为现实——OpenTelemetry eBPF Instrumentation(以下简称 OBI)就是 OpenTelemetry 社区给出的官方答案。
作为 OpenTelemetry 官方维护的开源项目,OBI 一句话概括它做的事情:利用 Linux 内核的 eBPF 技术,在不修改任何应用代码的前提下,自动拦截和分析进出应用的网络流量以及 GPU 操作,生成符合 OpenTelemetry 标准的 trace 和 metrics。
你可以把它想象成一个装在操作系统内核里的“透视镜”。无论你的应用使用 Go、Ja va、Python、Node.js 还是 .NET 编写,不管你用什么 HTTP 框架、连接什么数据库、调用哪家大模型——OBI 都能在内核和库函数层面拦截通信,解析协议语义,然后输出标准遥测数据。在 AI 可观测性方面OBI 已内置对 OpenAI、Anthropic、Google Gemini、Qwen(通义千问)四大 GenAI Provider 的协议级追踪,能自动识别 LLM 调用并从响应中提取 Tool Call 信息,同时支持 Rerank 和向量检索(Vector Retrieval)操作的追踪,覆盖 RAG 管线的核心环节。
支持 Linux amd64/arm64 架构,内核要求 5.8 (RHEL 系列可降至 4.18 )。部署方式灵活:可以作为独立进程运行、Docker 容器部署、Kubernetes DaemonSet 部署。

三大支柱:应用监控、网络监控和日志增强
OBI 的核心能力围绕三大可观测性支柱展开:
应用可观测性:分布式追踪(Traces)和 RED Metrics,覆盖 Web、数据库、消息队列、GenAI、GPU 等 15 种主流协议与场景,自动向 JSON 日志注入 trace_id/span_id,实现 Trace-Log 关联。网络可观测性:L3/L4 网络流量监控,TCP/UDP 流量统计,支持 GeoIP、反向 DNS、CIDR 标注,TCP RTT 测量、TCP 连接失败统计,节点级全局指标。日志增强:语言无关地向 JSON 日志透明注入 trace_id 和 span_id,实现 Trace-Log 关联。
协议全景:从 HTTP 到 CUDA,一网打尽
OBI 的核心竞争力在于协议感知型探测——它不仅记录“有一个网络请求”,而是深入理解每个请求的语义。以下是目前支持的完整协议矩阵:
Web 与 RPC

非 Go 语言的跨进程上下文传播通过内核态 tpinjector 的 HPACK 注入统一实现。
数据库

消息队列

协议是怎么被认出来的
OBI 怎么在不解密、不依赖端口约定的情况下判断一段 TCP payload 到底是 MySQL 还是 Redis?核心在 ReadTCPRequestIntoSpan 中,是一个三级瀑布式匹配,按“确定性从高到低”依次尝试,命中即返回:
- 内核已标注(最快):dispatchKernelAssignedProtocol 直接 switch event.ProtocolType。内核常量有明确的映射关系。
- 确定性通用匹配:detectGenericProtocol 会依次尝试 matchSQL、matchFastCGI、matchMongo 等。
- 启发式兜底(最易误判,放最后):detectHeuristicProtocol 会尝试 matchRedis、matchMemcached 等。顺序本身就是 bug 经验的沉淀——例如 HTTP/2 必须排在 MQTT 之前,因为 MQTT 的启发式会误命中 HTTP/2 的连接前导。
几个值得关注的防误判细节:
- SQL:先用可打印 ASCII 前缀过滤,再大小写无关地搜索关键字,最后提取操作与表名。
- Postgres:校验 5 字节消息头、类型字节和长度,还维护 prepared statement 与 portal 的 LRU 缓存。
- HTTP/2 vs gRPC:先进行 RFC 7540 逐帧校验,再通过 content-type 头区分。
语言深度集成:不止于网络层
OBI 的探测分为两个层次。第一层是语言无关的网络级追踪;第二层是运行时特定的深度集成——对特定语言和框架,通过 uprobe 直接挂钩库函数。

Go 没有 ThreadLocal,OBI 怎么串起一次调用?
Go 的 goroutine 会在 OS 线程间漂移,传统 APM 的线程本地存储完全失效。OBI 的解法是在内核里重建 goroutine 的父子血缘:挂钩 runtime.newproc1 记录创建关系;通过 find_parent_goroutine 沿父链向上回溯;再挂 runtime.casgstatus 跟踪状态切换,把上下文绑定到 goroutine。
Python asyncio 单线程多路复用,OBI 怎么区分并发请求?
Python 的 asyncio 事件循环在同一个 OS 线程上交替执行成百上千个协程,传统的“一个线程对应一个请求”假设彻底失效。OBI 的解法是在内核里追踪 CPython 的 Task 和 Context 对象,重建协程的父子归属关系。
核心由四组 uprobe 构成:task_step 追踪事件循环切换;_asyncio_Task___init__ 记录父子关系;PyContext_CopyCurrent 在 Context 被复制时绑定;context_run 在 worker 线程激活 Context 时恢复 Task 身份。三张 BPF Map 协同工作,覆盖 await、create_task、gather 和 to_thread 四种并发模式。
跨进程传播对非 Go 语言是内核态统一完成的
进程内上下文传播是各语言专属的,但跨进程的 traceparent 传播对所有非 Go 语言是统一在内核态由 tpinjector 完成的,三种手法:HTTP/1 头注入、HTTP/2 HPACK 注入、TCP Option 传播。
部署注意:TCP Option kind=25 属于 IANA 未分配编号,部分防火墙、负载均衡器和云平台中间盒可能剥离未知 TCP 选项,导致传播静默失效。建议在目标网络环境中验证 TCP 选项的透传能力,或优先使用 HTTP 头注入方式。
一条 Span 的完整生命周期(数据管线与架构)
内核中抓到的一个字节流,是怎么变成云监控 2.0 中那条 trace 的?这恰恰是 OBI 最硬核的工程部分。OBI 的用户态不是一个大循环,而是一张显式声明、分阶段、可插拔的有向图。

顶层骨架:三条独立 Agent errgroup
入口 RunWithContextInfo 按 Feature Flag 把三大支柱拆成三个互相独立的 goroutine,用 errgroup 绑定。应用可观测这条线又分三步:FindAndInstrument、ReadAndForward、WaitUntilFinished。
管线编排框架:swarm(两阶段启动)
OBI 自研了一套极简的节点编排框架,核心是“先全部实例化、再统一运行”的两阶段语义。
第一阶段实例化所有节点,任何一个失败就整体回滚。第二阶段启动运行,可配置取消超时,如果有节点超时未退出,可以定位到是哪个僵尸节点。
节点间通信:msg.Queue(带死锁探测的扇出队列)
节点之间通过泛型队列传递消息,支持扇出、零成本短路、死锁自检和多生产者关闭等特性。
应用可观测的完整 DAG
整条图被显式拼出来,从 eBPF 探针经过转发器、路由、装饰器,最终扇出到导出器、调试输出和指标管线。两个设计要点:指标按需启动,K8s 装饰器有特殊超时。
内核→用户态的搬运:双 goroutine 对象池的 ringbuf 转发器
这是整条管线的进水口,也是性能最敏感的地方。读/解析分离的生产者-消费者模式,预分配对象池避免 GC 抖动,批量提交配合超时兜底。成百上千个被探测进程共用一个共享 ringbuf。
GPU/CUDA 追踪:覆盖 kernel launch 与显存操作
OBI 还将可观测能力延伸到了 GPU 计算领域。通过 uprobe 挂钩 libcuda.so,它能追踪 NVIDIA CUDA 的核心操作——kernel launch、graph launch、内存分配和内存拷贝。这对于运行 AI 训练/推理任务的 GPU 集群来说非常有价值。

GPU 追踪的配置非常简单:OTEL_EBPF_CUDA_MODE=auto 会自动检测系统是否有 CUDA 库并开启追踪。CUDA 事件经由与网络 Span 同一套泛型转发器进入处理管线,天然共享相同的批量提交、背压控制与优雅关闭机制,无需为 GPU 单独维护一条搬运逻辑。
网络层观测:流量、关联与质量
除了应用级的分布式追踪,OBI 还提供了网络级的可观测能力。
网络流量监控 (NetO11y)
基于 TC 钩子捕获 L3/L4 网络包,解析 IPv4/IPv6 和 TCP/UDP 头部,生成网络流量指标。数据管线支持丰富的装饰能力。典型场景包括异常外联发现、跨可用区流量突增定位、服务依赖发现。

统计指标 (StatsO11y)
通过 kprobe/tracepoint 采集节点级的 TCP RTT 和 TCP 连接失败次数,帮助你监控底层网络质量。典型场景包括网络拥塞快速定界、交换机/网段故障定位。

日志增强:内核拦截 透明注入 trace_id
OBI 的日志增强是语言无关的能力——只要应用往 stdout/stderr 或 pipe 写 JSON 格式的日志,OBI 就能在内核层面拦截并透明地注入 trace_id 和 span_id。应用代码零修改,日志文件里就自动多出 Trace 关联字段。
实现原理是通过 kprobe 挂钩 tty_write 和 pipe_write 两个内核函数。当写操作触发时,BPF 程序从用户态缓冲区读取原始日志内容,获取当前线程/协程的 trace context,然后将原始日志擦除,并将事件送往用户态。需要留意的是,bpf_probe_write_user 存在两个风险:内核擦零到用户态写回之间存在时间窗口,部分安全加固内核可能禁用该函数。
用户态处理器接收事件后,尝试解析 JSON 并注入字段,非 JSON 则原样写回。几个工程亮点:内核侧预记录当前 fd、异步写入器保证日志行序、避免与应用自身的 span 冲突。
在云监控 2.0 中使用 OBI(OpenTelemetry 无侵入监控)
阿里云云监控 2.0 是面向云原生时代重构的统一可观测平台,原生基于 OpenTelemetry 协议构建。OBI 解决了“如何让存量与异构应用零成本接入这个底座”的最后一公里——尤其适合多语言混部、老系统改造受限、以及对生产环境侵入性敏感的场景。
一键接入
通过云监控 2.0 接入中心,选择 OpenTelemetry 无侵入监控,选择集群一键接入。

应用详情
接入后,你可以看到应用的请求数、错误数和耗时,以及接口的调用详情。

调用链分析
在调用链分析可以看到完整的 Trace 链路,让问题一目了然。

网络监控
以“源服务→目标服务”链路为核心视角,实时展示 K8s 集群中微服务间的网络流量速率与 TCP 往返时延,用于网络质量巡检、延迟异常定位和流量分布分析。

为了更好的使用 OBI 的能力,通过云监控 2.0 的接入中心可以实现一键的接入,接下来我们将逐步补充 AI Agent 可观测能力、更多的网络监控能力到 OBI 中,欢迎大家一起共建。
