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