2. Cilium 基础架构:eBPF 技术原理、Cilium 数据平面、Cilium 控制平面组件详解

Cilium 的核心竞争力源于其底层技术——eBPF(extended Berkeley Packet Filter)。理解 eBPF 的工作原理是掌握 Cilium 架构的基石。本章将深入剖析 eBPF 技术原理,并详细拆解 Cilium 的数据平面与控制平面组件,帮助您建立完整的架构认知。

2.1 eBPF 技术原理

eBPF 是一项革命性的 Linux 内核技术,它允许用户在无需修改内核源码或加载内核模块的情况下,安全、高效地注入自定义程序。这些程序在内核的沙箱环境中运行,并能在特定事件(如网络数据包到达、系统调用、函数入口/出口)触发时执行。

核心价值: eBPF 将内核从“黑盒”转变为可编程的“乐高积木”,使得网络、安全、可观测性等领域的创新速度大幅提升。

2.1.1 eBPF 程序生命周期

一个 eBPF 程序从编写到生效,通常经历以下四个阶段:

  1. 编写与编译: 开发者使用 C 语言(或 Rust 等)编写 eBPF 程序,然后通过 LLVM/Clang 编译器将其编译为 eBPF 字节码。
  2. 验证: 用户态工具(如 bpftool)通过 bpf() 系统调用将字节码加载到内核。内核中的 eBPF 验证器(Verifier) 会严格检查程序,确保其不会导致内核崩溃、死循环或访问非法内存。
  3. JIT 编译与附加: 验证通过后,内核的 JIT(Just-In-Time)编译器 将 eBPF 字节码转换为当前 CPU 架构的原生机器码,以获得接近原生内核代码的执行效率。随后,程序被附加到指定的事件钩子(Hook)上。
  4. 事件触发与执行: 当内核事件发生时,eBPF 程序被触发执行。它可以通过 eBPF Maps 与用户态程序或其他 eBPF 程序共享数据。
关键组件:eBPF Maps 是内核与用户态之间、以及不同 eBPF 程序之间进行数据交换的关键数据结构。它支持哈希表、数组、环形缓冲区等多种类型,是实现状态共享和统计信息收集的基础。

2.1.2 eBPF 程序类型与钩子

eBPF 支持多种程序类型,每种类型对应不同的内核事件钩子。Cilium 主要利用以下几种:

程序类型 附加钩子 Cilium 用途
XDP 网络驱动层(最早钩子) 高性能数据包过滤、DDoS 防护、负载均衡
TC (Traffic Control) 内核网络协议栈的 ingress/egress 网络策略执行、封装/解封装(VXLAN/Geneve)、重定向
Kprobe/Uprobe 内核/用户态函数入口/出口 可观测性、追踪系统调用、监控应用行为
Socket Filter Socket 层 基于 Socket 的访问控制、带宽管理
eBPF 程序生命周期与架构 1. 编写与编译 C 代码 → LLVM → 字节码 2. 加载与验证 bpf() 系统调用 → Verifier 3. JIT 编译与附加 JIT 编译器 → 附加到钩子 4. 事件触发 内核事件 → 执行 用户空间 (Userspace) 内核空间 (Kernel Space) eBPF Maps 数据共享与状态 钩子 (Hooks) XDP / TC / Kprobe 验证器 (Verifier) 安全检查 JIT 编译器 字节码→机器码 bpf() 系统调用 说明:eBPF 程序在内核沙箱中运行,通过 Maps 与用户态交互,实现安全、高效的可编程性。

2.2 Cilium 数据平面

Cilium 的数据平面完全构建在 eBPF 之上,负责处理集群内所有 Pod 之间的网络流量、网络策略执行、负载均衡以及服务映射。它直接运行在 Linux 内核中,避免了传统 iptables 或 IPVS 方案中频繁的规则遍历和上下文切换,从而实现了极致的性能。

2.2.1 数据平面核心组件

  • eBPF 程序(Datapath BPF Programs): 这是数据平面的执行单元。Cilium 在集群的每个节点上,通过 DaemonSet 部署的 cilium-agent 进程,将一系列 eBPF 程序附加到网络设备(如 eth0、lxc 等)的 XDP 和 TC 钩子上。
  • eBPF Maps(Datapath Maps): 这些 Maps 是数据平面的“配置数据库”。它们存储了网络策略规则、服务端点(Endpoints)、负载均衡后端、IP 地址分配(IPAM)等动态信息。eBPF 程序在执行时,通过查询这些 Maps 来做出转发、过滤或负载均衡决策。
  • 网络封装模式: Cilium 支持多种网络模式,包括:
    • 直接路由(Direct Routing): 性能最佳,要求底层网络支持 Pod IP 路由。
    • 覆盖网络(Overlay): 使用 VXLAN 或 Geneve 封装,对底层网络要求低,易于部署。
    • Native Routing: 利用云厂商的路由表实现 Pod 间通信。
性能关键点: 数据平面的性能瓶颈通常不在于 eBPF 程序本身,而在于 eBPF Maps 的查找效率。合理设计 Maps 的 key 结构(如使用哈希表而非数组)对吞吐量有显著影响。

2.2.2 数据包处理流程

当一个 Pod 发送数据包到另一个 Pod 时,Cilium 的数据平面会执行以下关键步骤:

  1. XDP 入口: 数据包到达宿主机网卡,XDP 程序首先被触发。它执行早期过滤(如丢弃恶意流量)或负载均衡决策。
  2. TC Ingress 策略检查: 数据包进入内核协议栈后,TC Ingress 钩子上的 eBPF 程序被触发。它查询 策略 Map,根据源/目的 Pod 的标签(Identity)判断是否允许通信。
  3. 服务负载均衡: 如果目的 IP 是 ClusterIP,eBPF 程序会查询 服务 Map,将 ClusterIP 替换为选中的后端 Pod IP。
  4. 封装/路由: 根据网络模式,eBPF 程序决定是直接路由还是进行 VXLAN/Geneve 封装。
  5. TC Egress 转发: 数据包从宿主机网卡发出前,TC Egress 程序执行最终的封装和发送操作。
Cilium 数据平面数据包处理流程 源 Pod XDP 入口 TC Ingress 策略 服务负载均衡 封装 / 路由 TC Egress 转发 目标 Pod 关键 Maps 查询 • 策略 Map (Policy Map):存储基于 Identity 的允许/拒绝规则。 • 服务 Map (Service Map):存储 ClusterIP 到后端 Pod IP 的映射关系。 • 端点 Map (Endpoint Map):存储本地 Pod 的元数据(如 IP、Identity、安全标识)。 • IP 缓存 Map (IP Cache Map):用于快速查找目的 IP 对应的节点和封装信息。

2.3 Cilium 控制平面组件

控制平面负责管理数据平面的状态,包括策略分发、身份管理、服务发现以及集群间通信。Cilium 的控制平面由多个微服务组件构成,它们协同工作,确保数据平面始终处于正确的配置状态。

2.3.1 核心控制平面组件

组件名称 部署方式 核心职责
cilium-agent DaemonSet(每个节点一个) 管理本地 eBPF 程序与 Maps;与 Kubernetes API Server 交互,监听 Pod、Service、NetworkPolicy 等资源变化;执行本地策略;管理本地端点。
cilium-operator Deployment(通常 2 个副本) 处理集群级别的任务:IP 地址管理(IPAM)、Service 的负载均衡后端同步、多集群网络(Cluster Mesh)的隧道端点管理、以及处理 CiliumNetworkPolicy 的全局状态。
KVStore(可选) 外部依赖(如 etcd) 在 KVStore 模式下,用于存储集群节点信息、身份(Identity)分配、以及全局策略状态。在 CRD 模式(默认)下,此角色由 Kubernetes API Server 承担。
hubble-relay Deployment Hubble 可观测性组件的核心,负责聚合集群中所有 cilium-agent 上报的流量事件,并提供统一的 API 查询接口。
clustermesh-apiserver Deployment(多集群场景) 用于多集群网络(Cluster Mesh)场景,负责在多个 Kubernetes 集群之间同步服务、端点、身份等信息。

2.3.2 控制平面工作流程:以网络策略为例

当您创建一个 CiliumNetworkPolicy 资源时,控制平面会执行以下步骤:

  1. API Server 接收: Kubernetes API Server 接收到新的 CiliumNetworkPolicy 对象。
  2. cilium-agent 监听: 每个节点上的 cilium-agent 通过 Watch 机制感知到策略变化。
  3. 策略解析与 Identity 解析: cilium-agent 解析策略规则,将其中引用的 Kubernetes 标签(如 app: frontend)转换为 Cilium 内部使用的 Security Identity(一个 24 位的数字 ID)。
  4. eBPF Maps 更新: cilium-agent 将解析后的策略规则(以 Identity 对 Identity 的形式)写入本地的 策略 Map。
  5. 数据平面生效: 后续到达该节点的数据包,其 eBPF 程序会查询更新后的策略 Map,并立即执行新的允许/拒绝规则。
架构优势: 控制平面与数据平面分离的设计,使得策略变更无需重启任何数据平面组件或中断现有连接。eBPF Maps 的原子更新特性保证了策略切换的平滑性。

2.3.3 身份管理(Identity Management)

Cilium 使用 Security Identity 而非传统的 IP 地址作为网络策略的基石。每个 Pod 或一组具有相同标签的 Pod 会被分配一个唯一的 Identity。这种设计带来了以下好处:

  • 策略简化: 策略规则基于标签,而非 IP 地址,使得策略定义与 Pod 的生命周期解耦。
  • 性能提升: eBPF Maps 中存储的是固定长度的 Identity(24 位),查找效率远高于变长的 IP 地址或 CIDR 范围。
  • 安全性增强: 即使 Pod 的 IP 地址发生变化,其 Identity 保持不变,策略依然有效,避免了 IP 地址变化带来的安全漏洞。

Identity 的分配由 cilium-agent 或 cilium-operator 负责,并存储在 KVStore 或 Kubernetes CRD 中,确保集群范围内的一致性。