2. Cilium 基础架构:eBPF 技术原理、Cilium 数据平面、Cilium 控制平面组件详解
Cilium 的核心竞争力源于其底层技术——eBPF(extended Berkeley Packet Filter)。理解 eBPF 的工作原理是掌握 Cilium 架构的基石。本章将深入剖析 eBPF 技术原理,并详细拆解 Cilium 的数据平面与控制平面组件,帮助您建立完整的架构认知。
2.1 eBPF 技术原理
eBPF 是一项革命性的 Linux 内核技术,它允许用户在无需修改内核源码或加载内核模块的情况下,安全、高效地注入自定义程序。这些程序在内核的沙箱环境中运行,并能在特定事件(如网络数据包到达、系统调用、函数入口/出口)触发时执行。
2.1.1 eBPF 程序生命周期
一个 eBPF 程序从编写到生效,通常经历以下四个阶段:
- 编写与编译: 开发者使用 C 语言(或 Rust 等)编写 eBPF 程序,然后通过 LLVM/Clang 编译器将其编译为 eBPF 字节码。
- 验证: 用户态工具(如
bpftool)通过bpf()系统调用将字节码加载到内核。内核中的 eBPF 验证器(Verifier) 会严格检查程序,确保其不会导致内核崩溃、死循环或访问非法内存。 - JIT 编译与附加: 验证通过后,内核的 JIT(Just-In-Time)编译器 将 eBPF 字节码转换为当前 CPU 架构的原生机器码,以获得接近原生内核代码的执行效率。随后,程序被附加到指定的事件钩子(Hook)上。
- 事件触发与执行: 当内核事件发生时,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 的访问控制、带宽管理 |
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 间通信。
2.2.2 数据包处理流程
当一个 Pod 发送数据包到另一个 Pod 时,Cilium 的数据平面会执行以下关键步骤:
- XDP 入口: 数据包到达宿主机网卡,XDP 程序首先被触发。它执行早期过滤(如丢弃恶意流量)或负载均衡决策。
- TC Ingress 策略检查: 数据包进入内核协议栈后,TC Ingress 钩子上的 eBPF 程序被触发。它查询 策略 Map,根据源/目的 Pod 的标签(Identity)判断是否允许通信。
- 服务负载均衡: 如果目的 IP 是 ClusterIP,eBPF 程序会查询 服务 Map,将 ClusterIP 替换为选中的后端 Pod IP。
- 封装/路由: 根据网络模式,eBPF 程序决定是直接路由还是进行 VXLAN/Geneve 封装。
- TC Egress 转发: 数据包从宿主机网卡发出前,TC Egress 程序执行最终的封装和发送操作。
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 资源时,控制平面会执行以下步骤:
- API Server 接收: Kubernetes API Server 接收到新的
CiliumNetworkPolicy对象。 - cilium-agent 监听: 每个节点上的
cilium-agent通过 Watch 机制感知到策略变化。 - 策略解析与 Identity 解析:
cilium-agent解析策略规则,将其中引用的 Kubernetes 标签(如app: frontend)转换为 Cilium 内部使用的 Security Identity(一个 24 位的数字 ID)。 - eBPF Maps 更新:
cilium-agent将解析后的策略规则(以 Identity 对 Identity 的形式)写入本地的 策略 Map。 - 数据平面生效: 后续到达该节点的数据包,其 eBPF 程序会查询更新后的策略 Map,并立即执行新的允许/拒绝规则。
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 中,确保集群范围内的一致性。