Cilium Cilium

Cilium 如何使用 eBPF:身份、策略与套接字

当一个 Pod 启动、与另一个 Pod 通信,或某个数据包需要策略判定时,内核中究竟发生了什么 —— 以及它为什么快。

11 min 初级

Cilium 的决定性特征并非某一项具体功能,而是网络、安全和可观测性全都以程序的形式,通过 eBPF 直接运行在 Linux 内核中,而不是通过 iptables 规则或 sidecar 代理附加上去。本指南介绍这在实践中意味着什么:一个 Pod 启动时会发生什么、策略判定是如何做出的,以及为什么 Cilium 的网络路径比它所取代的方案更快。

一段话讲清 eBPF

eBPF 允许你在运行时将小型的、用途明确的程序加载到 Linux 内核中,而无需编写内核模块或修补内核本身。在任何此类程序被允许加载之前,内核中的验证器会对它进行静态分析:确认它会终止(没有无界循环)、保持在安全的内存边界内,并且不会使内核崩溃或挂起。未通过检查的程序会被直接拒绝,这正是让用户空间工具可以安全地把任意逻辑加载进内核空间的原因。每个 eBPF 程序都是现编译、现加载的,而不是作为预编译的内核二进制文件分发。

Pod 启动时发生了什么

Kubernetes 的 kubelet 会要求已配置的 CNI 插件为新 Pod 设置网络。以 Cilium 作为该 CNI 时:

  1. Cilium 为 Pod 分配一个网络命名空间以及常规的 IP 配置,这与任何 CNI 都要做的基础工作相同。
  2. Cilium 为 Pod 分配一个安全身份,它来源于 Pod 的 Kubernetes 标签,而不是它的 IP 地址。共享相同相关标签的所有 Pod(通常包括其 Deployment 的 selector 标签之类)共享同一个身份。这很重要,因为 Pod 的 IP 是短暂的,并且不断被重新分配;与标签绑定的身份在重启和重新调度之间保持稳定,这是 IP 地址永远做不到的。
  3. Cilium 将一个 eBPF 程序附加到 Pod 的网络命名空间。从此刻起,该程序可以看到并处理涉及该 Pod 的每一个网络事件:连接建立、数据包到达、请求发往另一个服务或外部世界。

策略判定针对每个数据包,而不是每个会话

传统防火墙通常实现”允许已建立的连接”:一旦连接被允许,其上的所有后续数据包都不再重新评估通过,只有新连接才会按策略检查。Cilium 基于 eBPF 的执行会针对当前策略评估每一个单独的数据包,而不只是连接的初始建立。

实际后果是:当你更改网络策略时,变更会立即对所有流量生效,包括已经打开的连接。不存在这样一个窗口期:已建立的会话在陈旧规则下继续通行,直到它碰巧关闭再重新打开。

可观测性来自同一个事件流,不需要额外付出

做出策略判定的同一套 eBPF 插桩,也会为它观察到的每次网络交互生成一个事件:连接尝试、被允许和被拒绝的流量、对外部目的地的请求。这也是 Cilium 能把流量归因到实际产生它的进程的原因,不只是”这个 Pod 与那个 Pod 通信了”,而是 Pod 内具体是哪个进程发起了连接,这个细节层次是类似位于 sidecar 边缘的深度包检测这类方法通常无法在事后重建出来的。这个事件流正是 Cilium 自己的可观测性工具 Hubble 的构建基础,在这一技术的落地页的核心概念中有介绍。

套接字级负载均衡:跳过数据包重写

访问 Kubernetes Service 传统上意味着,发往 Service 虚拟 IP 的数据包会被重写(NAT)为实际后端 Pod 的 IP,这一步历史上由 iptables 或 IPVS 规则实现,每个数据包都必须经过它们。Cilium 则在套接字层、连接建立时执行这个转换,使用附加在进程调用 connect() 或发送数据处的 eBPF 钩子。应用的连接从一开始就直接指向被选中的后端,而不是之后每个数据包都在传输途中被逐个重写。这去掉了相当可观的每包开销,对于高吞吐或对延迟敏感的服务间流量尤其明显。

完全取代 kube-proxy

kube-proxy 包含在标准的 Kubernetes 二进制文件中,默认使用 iptables 或 IPVS 规则来实现 Service 路由(ClusterIP、NodePort 等)。Cilium 可以彻底取代 kube-proxy,改用 eBPF 实现同样的 Service 路由逻辑。除了原始性能之外,这还改变了一个值得了解的运维特性:庞大的 iptables 规则集是一个相互依赖的整体结构,修改其中一条规则可能意味着重新加载整个规则集。Cilium 基于 eBPF 的规则更接近独立的、原子的条目,所以改动其中一条不需要触碰其余部分。

为什么这在”它很快”之外也很重要

性能是醒目的卖点,但更深层的意义在于架构:由于 Cilium 在内核层面运行,而不是通过一堆 iptables 规则或每个 Pod 一个 sidecar,网络、安全策略、负载均衡和可观测性都来自同一个底层事件流和同一个内核级执行点,而不是四个各自需要配置、保持同步、并指望它们彼此一致的独立系统。本系列的其余部分都建立在这个基础之上:集群设置、Gateway API、网络策略编写,以及 BGP 路由通告。

热门指南