2、eBPF基础回顾:eBPF程序类型、eBPF Map、eBPF Hook点,以及eBPF在Cilium/Hubble中的角色
在深入 Hubble 的租户隔离蓝图之前,必须夯实 eBPF 的核心基础。eBPF 并非单一技术,而是一个由程序类型、Map 和 Hook 点构成的运行时体系。Cilium 和 Hubble 正是利用这一体系,在无需修改内核的前提下,实现了可编程的网络、可观测性与安全策略。
2.1 eBPF 程序类型:定义能力边界
eBPF 程序类型决定了程序可以挂载到哪个内核子系统,以及可以访问哪些内核数据结构。在 Cilium/Hubble 的上下文中,以下类型最为关键:
| 程序类型 | 触发点 | Cilium/Hubble 中的用途 |
|---|---|---|
BPF_PROG_TYPE_XDP |
网卡驱动层(最早) | DDoS 防护、负载均衡、早期丢包 |
BPF_PROG_TYPE_SCHED_CLS |
TC(Traffic Control)入/出方向 | L3/L4 网络策略、封装/解封装(VXLAN/Geneve) |
BPF_PROG_TYPE_CGROUP_SOCK |
cgroup 套接字操作 | Pod 级别的连接跟踪与策略过滤 |
BPF_PROG_TYPE_KPROBE |
内核函数动态插桩 | Hubble 的 TCP 事件监控、DNS 解析追踪 |
BPF_PROG_TYPE_TRACING |
内核函数/迭代器 | Hubble 的 HTTP/gRPC 协议解析(通过迭代器遍历 socket) |
BPF_PROG_TYPE_PERF_EVENT |
硬件/软件性能计数器 | Hubble 的延迟直方图与丢包采样 |
关键认知: XDP 和 TC 是 Cilium 数据平面的主力,负责“执行”策略;而 kprobe 和 tracing 是 Hubble 观测平面的主力,负责“观察”流量。两者通过 eBPF Map 共享状态。
2.2 eBPF Map:内核态与用户态的共享内存
eBPF Map 是内核态 eBPF 程序与用户态控制平面(如 Cilium Agent)之间的通信桥梁。Map 的类型决定了数据结构和访问模式。
- 哈希表(BPF_MAP_TYPE_HASH): 用于存储连接跟踪表、策略规则映射(Endpoint IP → Policy ID)。
- 数组(BPF_MAP_TYPE_ARRAY): 用于固定大小的统计计数器、全局配置标志。
- LRU 哈希(BPF_MAP_TYPE_LRU_HASH): 用于有容量上限的连接跟踪,自动淘汰旧条目。
- Per-CPU 数组(BPF_MAP_TYPE_PERCPU_ARRAY): 用于无锁统计,每个 CPU 核独立累加,减少锁竞争。
- 环形缓冲区/性能缓冲区(BPF_MAP_TYPE_RINGBUF / PERF_EVENT_ARRAY): Hubble 将采集到的网络事件(如 TCP 状态变化、DNS 响应)通过此类 Map 高效推送至用户态。
租户隔离中的 Map 角色: 每个租户(或每个节点)拥有独立的 Map 实例,或通过 Map 中的 Key 字段(如
tenant_id)进行隔离。Cilium 通过 bpf_map_lookup_elem 在数据路径中快速查找策略,确保租户 A 的流量不会匹配到租户 B 的规则。
2.3 eBPF Hook 点:数据路径的锚点
Hook 点决定了 eBPF 程序在内核中的执行位置。Cilium 利用多个 Hook 点构建了完整的网络生命周期视图。
- XDP Hook: 位于网卡驱动之后、协议栈之前。适合高速丢包和重定向,延迟最低。
- TC Ingress/Egress Hook: 位于协议栈内部,可以访问 sk_buff 结构。Cilium 在此执行 L3/L4 策略和隧道封装。
- cgroup/sock Hook: 在进程(Pod)进行 connect/sendmsg/recvmsg 系统调用时触发。Cilium 在此实现 socket-level 策略,绕过 iptables。
- kprobe/kretprobe Hook: 动态插桩到内核函数入口和返回点。Hubble 在此捕获
tcp_connect、tcp_close、dns_query等事件。 - Tracepoint Hook: 静态定义的跟踪点,稳定性优于 kprobe。Hubble 用于捕获
sys_enter/sys_exit系统调用。
2.4 eBPF 在 Cilium 中的角色:数据平面与控制平面
Cilium 将 eBPF 作为其核心执行引擎,替代了传统的 iptables 和 ipvs。其角色可以概括为:
- 网络策略执行: 在 TC 和 XDP 点加载 eBPF 程序,实现 L3/L4/L7 的允许/拒绝规则。每个策略规则对应一个 eBPF Map 条目。
- 服务负载均衡: 使用 eBPF 实现高效的 Maglev 或随机一致性哈希,将 ClusterIP 流量分发到后端 Pod。
- 隧道封装: 在 TC 点通过 eBPF 程序进行 VXLAN/Geneve 报文的封装与解封装,实现 Overlay 网络。
- 加密与认证: 集成 WireGuard 或 IPsec,通过 eBPF 在数据路径中直接处理加密。
2.5 eBPF 在 Hubble 中的角色:观测平面
Hubble 是 Cilium 的分布式观测层,其核心能力完全构建在 eBPF 之上:
| 观测能力 | 使用的 eBPF 技术 | 实现机制 |
|---|---|---|
| 网络流日志 | kprobe + Perf Ring Buffer | 在 tcp_connect/tcp_close 处插桩,记录五元组和时间戳 |
| DNS 监控 | kprobe + Map | 在 __udp_recvmsg 处解析 DNS 请求/响应,提取域名 |
| HTTP 指标 | BPF_PROG_TYPE_TRACING + Socket Iter | 遍历进程 socket,解析 HTTP 头部,统计延迟和状态码 |
| 丢包与重传 | Tracepoint + Per-CPU 计数器 | 挂载 tcp_retransmit_skb 和 kfree_skb 跟踪点 |
| 服务拓扑 | Map 聚合 | 从连接跟踪 Map 中读取活跃连接,构建服务依赖图 |
性能注意事项: Hubble 的 kprobe 程序应尽量精简,避免在观测路径中执行复杂逻辑。建议将数据采集(轻量级)与数据解析(用户态)分离,以降低对数据平面延迟的影响。
2.6 小结:eBPF 是 Cilium/Hubble 的基石
理解 eBPF 的程序类型、Map 和 Hook 点,是掌握 Hubble 租户隔离蓝图的先决条件。Cilium 利用 eBPF 在数据平面实现高性能策略执行,而 Hubble 则在观测平面利用 eBPF 实现零侵扰的流量监控。两者通过 eBPF Map 共享状态,构成了一个完整的、可编程的云原生网络栈。