前言
eBPF 是一种强大的内核技术,允许在内核中安全地执行自定义代码。通过 eBPF,开发者可以在不修改内核源码的情况下,对内核功能进行扩展和监控。eBPF Tracing 利用这一技术,对系统调用、内核函数等进行跟踪,从而实现对应用行为的深入洞察。
与传统的监控方式相比,eBPF Tracing 具有以下优势:
- 无侵入性:无需修改应用代码即可进行监控。
- 高性能:在内核层面执行,减少了对应用性能的影响。
- 细粒度:可以精确到单个系统调用或内核函数的监控。
eBPF(网络)链路实现
实现由三部分构成:
- eBPF 探针程序
- 解析来自 BPF Map 的网络请求数据、线程(协程)跟踪与 eBPF Span 生成
- 链接来自所有节点的汇总 eBPF Span (以下简称 eSpan) 生成链路
eBPF 探针程序
eBPF 探针用于获取程序读写 socket fd 的网络数据,并通过 BPF Map 发送给用户空间的程序进行协议解析。
Linux syscall 函数触发时 eBPF 探针将读取 buf 参数的内容写入 BPF Map,参考 syscall 如下:
写入 BPF Map 的数据将记录触发的 syscall 函数及时间、TCP 连接信息、线程/协程信息以及 Linux syscall 的 buf 参数的部分 payload,以下为结构体:
由第二部分的 Agent 实现 eBPF 探针程序的加载和卸载,工作示意图:
网络请求解析、线程跟踪与 eSpan 生成
DataKit-eBPF 程序从 BPF Map 获取网络数据,解析网络协议,根据进程和线程信息构建线程跟踪模型。
其构成主要包含:
- 采集:
收集来自 BPF Map 的网络数据等;加载 eBPF 探针程序,attach 到相应的 syscall 函数 - 解析:
- 建立进程的线程-网络请求时序模型,通过为应用内关联网络请求(IN/OUT)提供线程跟踪 ID 实现进程内跟踪;
- 检测网络数据里的网络协议,识别到 HTTP、Redis、MySQL 等协议后进入解析模式,并进行网络协议/进程过滤等;
- 解析网络协议,采集网络请求,生成请求数据,附加根据 TCP 序列号生成跨进程网络跟踪 ID、附加 Otel/DDTrace 等的链路传播信息(如果有);
- 生成:
向生成请求数据中注入线程跟踪 ID,进一步生成 eBPF Span 和生成网络请求聚合数据。 - 发送:
由于当前 eBPF Span 中没有建立跨进程调用的父子关系,需要将所有节点的 eSpan 发送至同一个用于 eSpan 链接的 DataKit 或 DataKit-ELinker 服务, 如图:
eSpan 链接
该部分接收来自所有节点的 eSpan 数据,用于建立这些来自多个节点的 eSpan 的跨进程应用调用关系,实现生成完整的链路。
其构成主要包含:
- 接收 eSpan 并缓存 N 个链接周期(该周期可根据单次应用调用链路的总耗时调参)的 eSpan 数据
- 按链接周期取数据,加工 eSpan,根据 eSpan 中的进程内跟踪 ID 和跨进程网络跟踪 ID 完成 eSpan 间的链接
- 采样,该采样为尾部采样;同时,可根据 Otel/DDtrace 等通过网络传播的链路信息中的采样信息进行采样
- 上传 eBPF 链路数据到观测云