eBPF 采集存储与可观测性统一架构趋势

可观测性架构在过去五年经历了从"分治"到"统一"的深刻转变。各信号(指标、日志、追踪、Profiling)从独立的专用后端走向共享存储与统一数据模型,而 eBPF 作为新一代采集手段,为这一转变提供了前所未有的数据深度与广度。本文将聚焦四个维度:eBPF 采集存储设计、统一存储架构(LGTM 分治 vs ClickHouse 统一)、OpenTelemetry 统一数据模型、以及对象存储与存算分离的演进方向。

本文从存储架构视角审视 eBPF 在可观测性中的角色——数据采到后存哪、怎么存、存算分离如何演进。如需了解 eBPF 采集侧的实现细节(CO-RE、libbpf、Aya、协议解析、OOM 追踪),请参阅 eBPF 系列

新手类比:eBPF 就像在高速公路上装了智能摄像头——不用修改任何车辆(内核代码),就能在检查点采集所有车辆的数据。传统监控需要在每辆车上安装传感器(修改应用代码),而 eBPF 在路面(内核)层面捕获一切,对经过的车辆完全透明。

下方动画展示 eBPF 数据如何从内核态流向用户态:

eBPF 数据流:从内核态到用户态内核态(Kernel Space)用户态(User Space)数据包/系统调用eBPF 程序(kprobe/tracepoint)Ring Buffer / Map(内核内存)用户态 Agent(PEM / Hubble)后端存储(ClickHouse 等)对比传统方案:应用需手动埋点 SDK,无法感知内核事件;eBPF 在内核态自动捕获,无需修改应用代码

动画说明:上方动画展示 eBPF 数据管道:网络数据包或系统调用触发 eBPF 程序(通过 kprobe/tracepoint 挂载),数据写入内核 Ring Buffer,用户态 Agent 通过 mmap 读取后发送到后端。关键对比:传统插桩需要应用层 SDK 修改且无法看到内核事件,而 eBPF 在内核层透明捕获一切。

Userspace应用 & 可观测性 AgentAgenteBPF Hook Points内核事件拦截点kprobe函数入口/出口tracepoint内核跟踪事件XDP网络驱动层TC流量控制eBPF Programs & MapseBPF 虚拟机 & 共享 Maps
内核事件 eBPF Hook eBPF Program Map Userspace

eBPF 采集存储

eBPF 将采集能力下推到内核态,带来前所未有的细粒度数据,但也是数据量的爆炸式增长。本节分析三个典型 eBPF 可观测性方案的存储设计。

Pixie — 基于 eBPF 的无侵入可观测性平台

Pixie 平台由三大组件构成[E1]Vizier(数据平面,部署在被监控集群)、Cloud(控制平面)、Vizier Operator(Kubernetes Operator)。

关键存储特点[E1][E3]

  • 数据不出集群:采集数据存储在集群节点内存中,默认不发送到任何中心化后端
  • PEM 通过 eBPF 在内核态采集数据,本地内存短期存储(最长 24h),是所有集群数据的主要存储位置
  • 多级管道架构:eBPF 采集 → PEM 预处理与聚合 → Kelvin 节点级到集群级聚合 → Query Broker 结果合并
mermaid
flowchart TD
    PEM["PEM<br/>eBPF 采集 + 本地内存 24h"]
    K["Kelvin<br/>集群级聚合"]
    QB["Query Broker<br/>结果合并"]
    Cloud["Cloud<br/>控制平面"]

    PEM --> K
    K --> QB
    Cloud -.->|不存储数据| PEM
    Cloud -.->|不存储数据| K

    style PEM fill:#4CAF50,color:#fff
    style K fill:#2196F3,color:#fff
    style QB fill:#9C27B0,color:#fff

图 1:Pixie “采集即计算"架构。PEM(绿色)通过 eBPF 在内核态采集数据并存储在本地内存中,最长保留 24 小时。Kelvin(蓝色)执行集群级聚合,Query Broker(紫色)合并查询结果。Cloud 控制平面不存储数据,体现了"数据不出集群"的设计原则——只有查询结果而非原始数据被传输。

架构趋势洞察:Pixie 体现了"采集即计算"的设计——数据聚合在采集侧(PEM/Kelvin)完成,只有查询结果而非原始数据被传输[E1][E2]

Cilium/Hubble — eBPF 网络可观测性

Hubble 构建在 Cilium 与 eBPF 之上,其 server 组件嵌入式运行在 Cilium Agent 中[E5]

Flow 日志存储:用户态 Ring Buffer[E5]

  • Hubble 将 Cilium event monitor 的监控事件存入用户态 ring buffer 结构
  • ring buffer 在内存中存储可配置数量的事件,buffer 满后覆盖最旧事件(FIFO 覆盖)
  • 无锁设计:内部 buffer 长度是 2^n,采用原子操作而非锁机制

eBPF 数据采集特点

eBPF 采集的数据量极大,因此降量是核心挑战[E10]

机制特点适用场景
eBPF Ring Bufferkernel 5.8+,单 buffer 多 CPU 共享,内存效率高高吞吐事件流(推荐)
Perf Event每 CPU 独立 buffer兼容性场景
Hash Map用于计数器等聚合状态内核态聚合

内核态聚合策略[E10]:在内核计算摘要而非流式传输原始事件、智能采样。这一策略在 Pixie、Hubble、Inspektor Gadget 中均有体现——采集侧聚合 + 短期内存存储 + 按需查询传输结果


统一存储架构(LGTM 分治 vs ClickHouse 统一)

Grafana Stack 的"分治"架构

Grafana Stack 采用每个信号类型一个专用后端的架构:Mimir(指标)、Loki(日志)、Tempo(追踪)、Pyroscope(持续性能剖析)[E11][E12]。各后端共享对象存储但数据库引擎独立。

mermaid
flowchart TD
    Mimir["Mimir<br/>Metrics"]
    Loki["Loki<br/>Logs"]
    Tempo["Tempo<br/>Traces"]
    Pyro["Pyroscope<br/>Profiling"]
    G["Grafana<br/>UI 关联层"]

    Mimir --> G
    Loki --> G
    Tempo --> G
    Pyro --> G

    style Mimir fill:#2196F3,color:#fff
    style Loki fill:#FF9800,color:#fff
    style Tempo fill:#f44336,color:#fff
    style Pyro fill:#9C27B0,color:#fff

图 2a:Grafana LGTM 分治架构。每种信号类型对应专用后端——Mimir(蓝)、Loki(橙)、Tempo(红)、Pyroscope(紫)。各后端共享对象存储但数据库引擎彼此独立。跨信号关联发生在可视化层(Grafana)而非存储层[E16]

ClickHouse 作为统一可观测性存储

ClickHouse 已成为可观测性存储引擎的事实标准,核心论点是"可观测性是数据分析问题,应像对待数据分析一样对待它”[E16]

mermaid
flowchart TD
    GCH["Grafana"]
    CH["ClickHouse<br/>统一列存"]
    Signals["指标 / 日志 / 追踪<br/>/ Profiling"]

    CH --> GCH
    Signals --> CH

    style CH fill:#4CAF50,color:#fff
    style GCH fill:#2196F3,color:#fff

图 2b:ClickHouse 统一存储架构。所有信号共用单一列存引擎,关联在存储层通过标准 SQL JOIN 实现[E18],避免了多库之间的数据冗余与 ETL 开销。

列存优势[E16]

特性对可观测性的价值
压缩日志/trace 平均压缩 14 倍
快速聚合GROUP BY 聚合响应快
快速线性扫描可扫描数十 GB/s(压缩态),替代倒排索引
高基数列存从根本上解决高基数问题[E17]
SQL降低学习成本

5 步成本优化技术栈[E16]

  1. 编解码器链式组合:Delta/DoubleDelta + ZSTD,约 50% 存储削减
  2. 分层存储:热数据 NVMe SSD,7 天后迁移 S3
  3. 主键优化ORDER BY (toStartOfMinute(Timestamp), Service)
  4. 物化视图预聚合:数据到达时预计算聚合
  5. 异步插入:服务端缓冲,省去 Kafka

大规模实践验证:据 ClickHouse 官方 playbook,Anthropic、OpenAI、Tesla、Didi、Shopee 等采用 ClickHouse(注:以下案例数据来源为 ClickHouse 营销材料,未经独立核实)——Tesla 构建千万级行/秒摄入平台;OpenAI 将查询从分钟级降至毫秒级;Didi 从 ES 迁移实现 30% 成本下降+4 倍查询提速[E16]

核心结论(3 源交叉验证):统一列存替代分治多库是明确趋势。ClickHouse 官方文档[E18]、ClickStack playbook[E16]、Parseable 对比[E19]均确认:单引擎统一存储消除数据重复、原生支持高基数、降低 TCO。


OpenTelemetry 统一数据模型

统一信号架构

OpenTelemetry 客户端按信号(Signal) 组织——每个信号提供一种专门的可观测能力(tracing、metrics、logs、baggage),信号间共享上下文传播子系统但功能独立[E25]

OTLP 数据结构以 Resource + InstrumentationScope + Signal 的统一层级组织[E26][E25]

mermaid
flowchart TD
    Resource["Resource<br/>service.name, k8s.pod.name"]
    Scope["InstrumentationScope<br/>库名 + 版本"]
    Metrics["Metrics"]
    Logs["Logs"]
    Traces["Traces"]
    Profiles["Profiles"]

    Resource --> Scope
    Scope --> Metrics
    Scope --> Logs
    Scope --> Traces
    Scope --> Profiles

    style Resource fill:#9C27B0,color:#fff
    style Scope fill:#2196F3,color:#fff
    style Metrics fill:#4CAF50,color:#fff
    style Logs fill:#4CAF50,color:#fff
    style Traces fill:#4CAF50,color:#fff
    style Profiles fill:#4CAF50,color:#fff

图 3:OpenTelemetry 统一数据模型。Resource(紫色)捕获实体信息(service.name、k8s.pod.name),InstrumentationScope(蓝色)标识仪表化库,Metrics、Logs、Traces、Profiles 四大信号(绿色)共享统一的 Resource 与 InstrumentationScope 层级,实现跨信号的实体关联。

  • Resource:捕获遥测所记录实体信息,可描述整个实体层级(云主机到容器到应用)
  • InstrumentationScope:标识产生遥测的仪表化库
  • Signal:Metrics/Logs/Traces/Profiles 四大信号共享统一的 Resource 与 InstrumentationScope

Profiles 信号(第四支柱):已成为 OpenTelemetry 的第四信号。profile 可记录采样时哪些 span 处于活跃状态,实现 profile 与 tracing 的关联[E27]

Exemplar 机制

Exemplar 是连接指标与 trace 的桥梁:将指标数据点关联到示例 trace_id,使从延迟尖峰可直接跳转到代表性 trace[E28][E29]

跨信号关联存储设计

mermaid
flowchart TD
    Exemplar["Metrics → Traces<br/>Exemplar(trace_id)"]
    TraceID["Logs → Traces<br/>trace_id 注入"]
    SpanProfile["Profiles → Traces<br/>活跃 span 记录"]
    Unified["统一基础<br/>Resource +<br/>InstrumentationScope"]

    Unified --> Exemplar
    Unified --> TraceID
    Unified --> SpanProfile

    style Exemplar fill:#2196F3,color:#fff
    style TraceID fill:#FF9800,color:#fff
    style SpanProfile fill:#4CAF50,color:#fff
    style Unified fill:#9C27B0,color:#fff

图 4:跨信号关联机制。三条关联链路均建立在统一基础上:Metrics 通过 Exemplar 携带 trace_id 关联到 Traces(蓝);Logs 通过结构化日志注入 trace_id/span_id(橙);Profiles 记录采样时活跃 span(绿)。统一基础(紫)确保所有信号共享相同的 Resource + InstrumentationScope 模型。

关联链路机制存储设计要求
Metrics → TracesExemplar(trace_id/span_id 附加到指标点)指标存储需支持 exemplar 字段存储与查询
Logs → Traces结构化日志注入 trace_id/span_id 关联 ID日志存储需支持 trace_id 索引
Profiles → TracesProfile 记录采样时活跃 spanprofile 存储需关联 span 上下文
统一基础Resource(实体层级)+ InstrumentationScope(库标识)所有信号共享相同 Resource 模型

存储层设计模式对比:LGTM 分库模式关联在可视化层通过复杂 join 实现;ClickHouse 统一存储模式用标准 SQL JOIN 在存储层原生关联[E16][E18]

核心结论(3 源交叉验证):跨信号关联正从"UI 层 join"演进到"存储层原生关联"。OTel 规范[E25][E29]、ClickHouse 文档[E18]、社区实践[E28]共同确认。


对象存储与计算存储分离

对象存储(S3/GCS/Azure Blob)在可观测性中的角色从"归档冷存储"升级为主存储后端[E12][E14]

  • Tempo:trace 数据最终持久化到对象存储[E14]
  • Mimir:基于 Prometheus TSDB block 持久化到对象存储[E13]
  • Loki:采用 Thanos Object Storage Client 对齐存储配置[E12]
  • ClickHouse:分层存储策略将冷数据迁移到 S3[E16]

Tempo 3.0 是计算存储分离的典型范例[E14]:写读解耦、Kafka 作为持久 WAL、对象存储连接读写路径。

mermaid
sequenceDiagram
    participant WP as WritePath
    participant K as Kafka(WAL)
    participant OS as ObjectStorage
    participant RP as ReadPath

    WP->>K: 持久 WAL
    K->>OS: Block-builder 写入
    RP->>OS: 冷数据查询
    RP->>K: 热数据(Live-store)查询

图 5:Tempo 3.0 存算分离写读模型。WritePath 将数据写入 Kafka 作为持久化 WAL,Block-builder 异步消费并构建 block 写入对象存储。ReadPath 对冷数据直接查询对象存储,对热数据从 Kafka(Live-store)读取,实现写读路径的完全解耦。


来源

[E1] [官方] Pixie Architecture: https://docs.px.dev/reference/architecture/

[E2] [二级资料] Pixie 组件详解: https://blog.csdn.net/gitblog_00394/article/details/150926117

[E3] [二级资料] Pixie vizier-pem pod running out of memory: https://knowledge.newrelic.com/s/article/4408761257623

[E5] [官方] Hubble internals (Cilium docs): https://docs.cilium.io/en/latest/internals/hubble/

[E10] [二级资料] eBPF Observability Architecture: https://calmops.com/software-engineering/ebpf-observability-architecture-next-generation-monitoring/

[E11] [官方] Grafana: The open and composable observability platform: https://grafana.com/

[E12] [官方] Grafana Loki 3.4: Standardized storage config: https://grafanacon.org/blog/2025/02/13/grafana-loki-3.4-standardized-storage-config-sizing-guidance-and-promtail-merging-into-alloy/

[E13] [官方] Grafana Mimir architecture: https://grafana.com/docs/mimir/v3.0.x/get-started/about-grafana-mimir-architecture/

[E14] [官方] About the Tempo architecture: https://grafana.com/docs/tempo/next/reference-tempo-architecture/about-tempo-architecture/

[E16] [官方] How to engineer cost-efficient open source observability with ClickHouse (ClickStack): https://clickhouse.com/resources/engineering/observability-cost-optimization-playbook

[E17] [二级资料] The high-cardinality trap: https://clickhouse.com/resources/engineering/high-cardinality-slow-observability-challenge

[E18] [官方] Использование ClickHouse для обеспечения наблюдаемости: https://clickhouse.com/docs/ru/use-cases/observability/introduction

[E19] [二级资料] ClickHouse vs Parseable: https://www.parseable.com/blog/clickhouse-vs-parseable

[E25] [官方] OpenTelemetry — Overview (specs): https://opentelemetry.io/docs/specs/otel/overview/

[E26] [二级资料] OpenTelemetry 实战:云原生可观测性三大支柱统一标准: https://blog.csdn.net/xyghehehehehe/article/details/159112652

[E27] [二级资料] What is OpenTelemetry? (Dash0): https://www.dash0.com/knowledge/what-is-opentelemetry

[E28] [二级资料] Semantics First: Correlating Signals with OpenTelemetry: https://www.thequietkernel.com/engineering/system-engineering/30-09-2025-obs-semantics/

[E29] [官方] Using exemplars (OpenTelemetry .NET metrics docs): https://opentelemetry.io/pt/docs/languages/dotnet/metrics/exemplars/