3. Hubble架构解析:Relay、Observer、UI组件、数据流与gRPC接口

Hubble是Cilium生态中负责可观测性的核心组件,它将eBPF在内核层面采集的流数据、指标与事件,通过一套分层架构暴露给运维人员。理解Hubble的组件划分、数据流转以及gRPC接口设计,是进行流量可视化和配额校准故障排查的基础。

3.1 核心组件与职责

Hubble由三个主要组件构成:Observer Agent(通常简称为Observer)、Relay和Hubble UI。它们各自承担不同的职责,协同完成从数据采集到前端展示的全链路。

组件 部署位置 核心职责 关键特性
Observer Agent 每个Kubernetes节点(DaemonSet) 通过本地Unix Socket与Cilium Agent通信,消费eBPF Map中的流事件;提供本地gRPC服务 低延迟、节点级数据源、直接访问内核事件
Relay 集群级Deployment(通常1-2个副本) 聚合所有Observer Agent的数据;实现全局排序、去重与缓存;对外提供统一的gRPC查询接口 水平扩展、无状态、支持多集群联邦
Hubble UI 集群内Deployment或独立部署 基于React的前端应用;通过gRPC-web或REST代理连接Relay;提供服务依赖图、流量表格与时间线 实时刷新、交互式拓扑、支持L3/L4/L7过滤
排查要点: 在配额校准场景中,Observer Agent是数据真实性的第一道关口。如果节点上的eBPF Map被错误清理或Cilium Agent重启,Observer将输出不完整流记录,导致Relay聚合后的配额统计出现偏差。

3.2 数据流全景

数据从内核eBPF程序产生,到最终呈现在UI上,经历了四个主要阶段。下图展示了完整的端到端数据流路径。

Hubble 端到端数据流架构 eBPF 内核程序 Perf Ring Buffer Map 事件推送 Observer Agent 本地gRPC Server 流解析与缓存 Relay 聚合层 全局排序/去重 统一gRPC API Hubble UI 服务依赖图 流量表格 Perf Ring Buffer gRPC Stream gRPC-web / REST 数据流关键路径: 内核 eBPF → Perf Ring Buffer → Observer Agent 本地Socket → gRPC Stream → Relay 聚合 → Hubble UI 展示
故障排查关键点: 数据流中的任何一环出现断裂,都会导致UI上出现数据缺失或延迟。例如,如果Relay无法连接到某个节点的Observer Agent(通常由于网络策略或gRPC端口不通),该节点的所有流量将完全不可见,配额校准将漏算该节点的所有Pod流量。

3.3 gRPC接口详解

Hubble的组件间通信完全基于gRPC协议。Observer Agent和Relay各自暴露一组定义清晰的gRPC服务。理解这些接口的签名和调用方式,对于编写自定义排查工具或调试连接问题至关重要。

3.3.1 Observer Agent 本地gRPC接口

每个节点上的Observer Agent通过Unix Socket(默认路径 /var/run/cilium/hubble.sock)暴露以下核心服务:

  • Observer:提供 GetFlows、GetAgentEvents、GetDebugEvents 等RPC,用于拉取流数据和事件。
  • Peer:提供 Notify RPC,用于向Relay通知本节点的服务变更(如IP地址、服务端口)。
// 使用 hubble CLI 直接查询本地 Observer Agent 示例
# 通过 Unix Socket 获取最近 10 条流记录
hubble observe --server unix:///var/run/cilium/hubble.sock --last 10

# 获取当前节点的服务列表(Peer 服务)
hubble status --server unix:///var/run/cilium/hubble.sock

3.3.2 Relay 统一gRPC接口

Relay对外暴露与Observer Agent相同的 Observer 和 Peer 服务接口,但内部实现了多节点聚合。上层消费者(如Hubble UI或CLI)只需连接Relay,无需关心底层有多少个节点。

RPC 名称 请求参数 响应流 典型用途
GetFlows FlowRequest(包含时间范围、过滤条件、黑名单) GetFlowsResponse 流 实时流量查询、历史回放、配额统计
GetAgentEvents AgentEventRequest GetAgentEventsResponse 流 监控Agent状态变更、启动/停止事件
GetDebugEvents DebugEventRequest GetDebugEventResponse 流 调试eBPF程序、捕获丢包或策略拒绝事件
GetNodes NodeRequest GetNodesResponse 流 获取集群中所有Hubble节点的状态和地址
配额校准常见陷阱: 使用 GetFlows 进行配额统计时,必须注意 FlowRequest 中的 time 字段。如果时间范围设置不当(例如跨越了Relay的缓存窗口),可能导致重复计数或遗漏。建议始终使用 since 和 until 明确指定时间边界,并配合 whitelist 过滤目标Pod的标签。

3.4 组件间通信与连接模型

Hubble的组件间通信采用拉取(Pull)与推送(Push)混合模式。Observer Agent主动从Cilium Agent拉取事件,Relay则通过gRPC Stream从各Observer Agent拉取数据。UI通过gRPC-web或Envoy代理向Relay发起查询。

Hubble 组件间通信模型 K8s Node 1 Cilium Agent Observer Agent Socket: /var/run/... K8s Node N Cilium Agent Observer Agent Socket: /var/run/... Relay gRPC Server 聚合/排序/缓存 Hubble UI gRPC-web Client 服务依赖图 gRPC Stream gRPC Stream gRPC-web
排查连接问题: 当UI显示“No data”或“Connection refused”时,应首先检查Relay Pod的日志,确认其是否成功连接到所有节点的Observer Agent。使用 hubble status 命令可以快速查看Relay视角下的节点连接状态。如果某个节点显示为“Unreachable”,则需要检查该节点上的Observer Agent是否正常运行,以及集群网络策略是否允许Relay访问节点的gRPC端口(默认4244)。

3.5 架构设计对故障排查的影响

Hubble的分层架构在带来灵活性的同时,也引入了额外的故障排查复杂度。以下是几个关键影响点:

  • 数据一致性窗口:Relay对来自不同节点的流事件进行排序和去重,但存在一个时间窗口(默认2秒),在此窗口内的事件可能乱序到达。配额校准查询应容忍微小的计数偏差。
  • 单点故障转移:Relay是无状态的,支持多副本部署。如果某个Relay实例宕机,客户端应自动重连到其他实例。排查时需确认客户端是否配置了正确的负载均衡策略。
  • gRPC流式传输:Observer Agent向Relay推送数据时使用gRPC Server-Sent Streaming。如果网络不稳定导致流中断,Relay会自动重连。但重连期间的数据可能丢失,导致配额统计出现缺口。
实战建议: 在进行eBPF配额校准前,建议先通过 hubble observe --server relay-service:4245 --last 1000 --output json 导出最近1000条流记录,与预期配额进行比对。如果发现计数偏差,应分别查询各节点的Observer Agent(通过 --server node-ip:4244),以定位是哪个节点的数据源出现了问题。