4. Hubble Server 与 Relay:Hubble Server 功能、Relay 数据聚合、gRPC 流式传输

在 Cilium 与 eBPF 的观测体系中,Hubble 组件承担着将内核 eBPF 事件转化为可消费网络流的职责。本章聚焦 Hubble 架构中的两个核心控制面组件:Hubble Server 与 Hubble Relay。前者负责本地节点的事件暴露,后者负责跨节点数据聚合与统一查询入口,两者通过 gRPC 流式传输 实现高效的数据管道。

4.1 Hubble Server:节点级观测引擎

Hubble Server 是一个运行在每个 Kubernetes 节点上的守护进程(通常以 DaemonSet 形式部署)。它直接与 Cilium Agent 通信,从 eBPF Map 和事件管道中读取网络流数据,并将其格式化为结构化的 Flow 对象。

核心职责: 将 eBPF 内核事件转换为可观测的、带标签的网络流元数据,并通过 gRPC 服务暴露给消费者。

4.1.1 主要功能

  • eBPF 事件消费: 通过 Cilium Agent 的 gRPC 接口订阅 eBPF 事件(如 TCP 连接建立、DNS 请求、HTTP 请求等)。
  • 流式封装: 将原始内核事件(如 connect()、sendmsg())封装为 Hubble Flow 对象,包含源/目的 IP、端口、协议、Kubernetes 标签、Verdict(允许/丢弃)等字段。
  • 本地缓存与过滤: 维护一个环形缓冲区(Ring Buffer)用于短期流存储,支持基于标签、IP、端口的实时过滤。
  • gRPC 服务暴露: 在本地节点监听 :4244 端口,提供 Observer 和 Recorder 两个 gRPC 服务。

4.1.2 Hubble Flow 对象结构

字段 类型 说明
time Timestamp 事件发生时间(纳秒精度)
verdict Verdict FORWARDED / DROPPED / ERROR
ethernet Ethernet 源/目的 MAC 地址
IP IP 源/目的 IP、IP 版本、TOS
l4 L4 TCP/UDP 端口、TCP Flags
source Endpoint 源 Pod 名称、命名空间、标签、Service
destination Endpoint 目的 Pod 名称、命名空间、标签、Service
l7 L7 HTTP 方法/路径/状态码、DNS 查询/响应
node_name string 产生该流的节点名称
关键洞察: Hubble Server 输出的 Flow 对象已经包含了 Kubernetes 语义标签(如 k8s:app=frontend),这使得后续的聚合和策略决策可以直接基于业务标签进行,无需二次解析。

4.2 Hubble Relay:跨节点数据聚合层

单个 Hubble Server 只能提供本地节点的网络流视图。在 Kubernetes 集群中,一个 Service 的 Pod 可能分布在多个节点上,因此需要一个全局聚合层——Hubble Relay。Relay 是一个无状态的中心化服务,它连接到所有 Hubble Server,将分散的流数据合并为统一的全局视图。

4.2.1 Relay 数据聚合机制

  • 节点发现: Relay 通过 Kubernetes API 自动发现所有运行 Hubble Server 的节点(通过 Label Selector 或 Endpoint 列表)。
  • 并行订阅: 对每个 Hubble Server 发起 gRPC 流订阅,请求从指定时间戳开始的流数据。
  • 时间戳排序: 接收来自不同节点的流数据后,Relay 在内存中按 time 字段进行全局排序,确保返回给客户端的流序列是时间有序的。
  • 去重与合并: 对于跨节点通信的流(如 Pod A 在 node1 到 Pod B 在 node2),Relay 会合并两端产生的 Flow 记录,避免重复。

4.2.2 单节点 vs 全局视图对比

维度 Hubble Server(单节点) Hubble Relay(全局)
数据范围 仅本节点 eBPF 事件 全集群所有节点事件
查询入口 节点 IP:4244 ClusterIP:4245(统一入口)
排序保证 节点内时间有序 全局时间有序
标签解析 依赖本地缓存 依赖全局 Kubernetes API
适用场景 节点级调试、快速验证 集群级监控、扩缩容决策

4.3 gRPC 流式传输:高效的数据管道

Hubble 全链路采用 gRPC 双向流 作为通信协议。从 Hubble Server 到 Relay,再到 Hubble UI 或 CLI 客户端,数据以流式方式持续推送,避免了轮询开销和连接频繁重建。

4.3.1 流式传输的优势

  • 低延迟: 事件从 eBPF 产生到 Relay 聚合,端到端延迟通常在毫秒级。
  • 背压控制: gRPC 流支持流控(Flow Control),当消费者处理速度跟不上时,生产者会自动降速,防止内存溢出。
  • 断线重连: Relay 与 Hubble Server 之间的 gRPC 连接支持自动重连,并带有指数退避策略,保障高可用。
  • 过滤下推: 客户端可以在 gRPC 请求中携带过滤条件(如 verdict=DROPPED),Relay 会将这些过滤条件下推到 Hubble Server,减少网络传输量。

4.3.2 gRPC 服务定义(简化)

// Observer 服务定义
service Observer {
  // 服务端流式 RPC:客户端发送请求,服务端持续返回 Flow
  rpc GetFlows(GetFlowsRequest) returns (stream Flow);
  
  // 服务端流式 RPC:获取节点状态变更事件
  rpc GetAgentEvents(GetAgentEventsRequest) returns (stream AgentEvent);
}

// 客户端请求示例(通过 hubble CLI)
// hubble observe --since 5m --verdict DROPPED --output json
性能注意事项: 在大型集群(>500 节点)中,Relay 需要处理每秒数十万条 Flow 记录。建议为 Relay 分配足够的 CPU 和内存资源,并启用 gRPC 的 grpc.max_recv_msg_size 参数(默认 4MB,建议调至 16MB 以上)。

4.4 架构总览:从 eBPF 到 Hubble Relay

下图展示了 Hubble 数据从内核 eBPF 到 Relay 聚合的完整路径:

Hubble 数据流架构:eBPF → Hubble Server → Relay → 消费者 Hubble 数据流架构:eBPF → Hubble Server → Relay → 消费者 eBPF 内核事件 XDP / TC Hook connect() / sendmsg() Cilium Agent eBPF Map 读取 事件回调 Hubble Server Flow 封装 gRPC :4244 eBPF 内核事件 节点 2 Cilium Agent 节点 2 Hubble Server 节点 2 eBPF 内核事件 节点 N Cilium Agent 节点 N Hubble Server 节点 N Hubble Relay 全局排序 / 去重 / 聚合 / gRPC :4245 Hubble UI / CLI 扩缩容决策引擎 gRPC 流式传输 双向流 / 背压控制 过滤下推 / 断线重连

4.5 关键设计决策:为什么需要 Relay?

在扩缩容决策场景中,Relay 的存在是必不可少的。以下是直接使用 Hubble Server 与使用 Relay 的对比:

决策场景 直接查询 Hubble Server 通过 Hubble Relay 查询
获取 Service 总流量 需要遍历所有节点,手动合并结果 一次查询返回全局聚合结果
检测跨节点丢包 只能看到本节点丢包,无法关联对端 Relay 合并两端 Flow,可识别双向丢包
节点扩缩容触发 需要为每个节点单独设置阈值 基于全局流量分布,统一决策
运维复杂度 高(需要管理 N 个端点) 低(单一 ClusterIP 入口)
实践建议: 在部署 Hubble 用于生产环境扩缩容时,始终通过 Hubble Relay 的 :4245 端口获取数据。Relay 的全局排序和去重能力是保证扩缩容决策准确性的基础。