1. 引言
Cilium 是一款开源软件,旨在为云原生环境(尤其是 Kubernetes)中的容器化工作负载提供、保护和观察网络连接。它采用 Go 语言开发,并深度依赖于 Linux 内核中的一项革命性技术——eBPF(扩展的伯克利数据包过滤器)。作为云原生计算基金会(CNCF)的毕业项目,Cilium 已成为 Kubernetes 生态系统中功能最为先进且广泛应用的容器网络接口(CNI)之一。
Cilium 的核心目标是利用 eBPF 的强大能力,在操作系统内核层面实现高效的网络数据包处理、动态可编程性以及相比传统基于 iptables 的解决方案更低的性能开销,从而提供可大规模扩展且高度安全的网络连接与可见性。
本报告将深入剖析 Cilium 项目,从其核心理念与愿景出发,详细解析其架构设计、关键组件、eBPF 技术的运用、核心网络与安全能力、Hubble 可观测性平台、服务网格实现,并探讨其部署运维、性能优化、实际应用案例以及在生态系统中的定位。通过全面的分析,旨在为技术研究人员、架构师和运维工程师提供对 Cilium 的深刻理解。
2. Cilium 核心理念与愿景
2.1. 创始目标与演进
Cilium 项目的创始目标非常明确:将 eBPF 技术引入 Kubernetes 生态系统,并致力于成为其中性能最优、功能最强的 CNI。其最初的关注点在于提供强大的安全性、卓越的可观测性以及高效的网络连接能力,这些能力从内核层面一直延伸到整个网络基础设施,包括云端、本地及其他混合环境。
随着容器技术的飞速发展和微服务架构的普及,Cilium 的发展也聚焦于解决由此带来的新挑战。其中一个关键的演进方向是应对容器化环境下的可扩展性问题,尤其是在策略管理和地址分配方面,因为传统的基于虚拟机的思考模式已不再适用。此外,项目早期就认识到,在用户空间网络日益盛行的背景下,提升内核网络的可扩展性和灵活性至关重要,目标是实现内核空间网络与用户空间网络同等的可扩展能力。
2.2. 未来展望:下一代网络层
Cilium 的愿景远不止于成为 Kubernetes 的一个 CNI 插件。其宏伟蓝图是将 Cilium 打造成下一代网络层的标准,其覆盖范围将从容器和 Kubernetes 扩展到虚拟机、物理服务器、边缘计算以及多云连接等更广泛的领域。Cilium 期望用户在考虑任何连接需求时——无论是容器、Kubernetes 集群、服务器组还是虚拟机——都能首先想到 Cilium,并信赖其提供的安全性、可扩展性和简洁性,而无需依赖十几种不同的工具来实现这些目标。
这种愿景也体现在 Cilium 与更广泛的云原生生态系统的融合上。例如,思科(Cisco)对 Cilium 创始公司 Isovalent 的收购,旨在利用 eBPF 技术增强其在网络和安全可观测性方面的能力,并促进 Cilium 与 Splunk、AppDynamics 等现有平台的集成,从而提供更全面的基础设施管理和可观测性解决方案。这反映了行业向融合、智能解决方案以支持动态云原生应用的趋势。
2.3. eBPF:Cilium 的基石
eBPF 是 Cilium 实现其强大功能和宏伟愿景的技术基石。eBPF 是一项革命性的 Linux 内核技术,允许在内核运行时动态加载和执行用户定义的代码(沙箱程序),而无需修改内核源代码或加载内核模块。这些 eBPF 程序可以在内核的多个挂钩点(hook points)上运行,例如网络接口、系统调用等,从而实现对系统行为的深度洞察和控制。
Cilium 巧妙地利用 eBPF 在以下几个核心方面获得了显著优势:
- 高性能与低延迟:通过在内核级别直接处理网络数据包,eBPF 避免了传统网络方案中数据包在内核空间和用户空间之间的多次拷贝和上下文切换,从而显著降低了延迟并提升了吞吐量。
- 动态可编程性:eBPF 使得网络行为的定义和修改可以动态进行,无需重启服务或中断现有连接。Cilium 将网络策略、负载均衡规则等直接编译成 eBPF 程序并加载到内核,实现了高度灵活和实时的网络控制。
- 内核级可见性:eBPF 程序能够访问内核数据结构和事件,为 Cilium 提供了对网络流量和系统调用的深度可见性,这是其可观测性平台 Hubble 和安全组件 Tetragon 的基础。
- 减少开销:相较于传统的基于 iptables 的防火墙和网络代理,eBPF 的内核级执行路径更为高效,减少了与传统方案相关的性能开销。
eBPF 的这些特性使得 Cilium 能够以一种全新的方式来解决云原生环境中的网络、安全和可观测性挑战。它不仅仅是一个 CNI,更是一个基于 eBPF 的可编程数据平面,为现代应用提供了坚实的基础。内核的可编程性赋予了 Cilium 巨大的灵活性和强大的功能,使其能够根据不断变化的基础设施需求进行调整和扩展,这正是 Cilium 能够持续引领云原生网络发展方向的关键所在。
3. Cilium 架构与核心组件
Cilium 的架构设计旨在充分发挥 eBPF 的潜力,提供高效、可扩展且功能丰富的网络、安全和可观测性解决方案。其核心在于清晰划分的控制平面和数据平面,以及一系列协同工作的组件。
3.1. 整体架构:控制平面与数据平面
Cilium 遵循了网络系统中常见的控制平面与数据平面分离的架构模式。
数据平面 (Data Plane):数据平面的核心职责是高效处理实际的网络流量。在 Cilium 中,数据平面主要由运行在每个 Kubernetes 节点(宿主机)Linux 内核中的 eBPF 程序构成。这些 eBPF 程序负责处理 L3/L4 层的网络连接、执行网络策略、进行负载均衡等。对于 L7 层的策略执行(例如 HTTP、Kafka 策略),Cilium 的数据平面还会集成一个 Envoy 代理。数据平面的设计目标是尽可能简单、高性能且高效地完成其核心任务:传输字节、实施策略和保障安全。
控制平面 (Control Plane):控制平面的主要职责是管理和配置数据平面组件。Cilium 的控制平面主要由运行在每个 Kubernetes 节点上的
cilium-agent
守护进程实现。每个cilium-agent
都是一个独立的控制平面实例,它连接到 Kubernetes API 服务器,监视集群状态和配置变化(例如 Pod 的创建与删除、网络策略的更新等),并将这些高级配置翻译成具体的 eBPF 程序和规则,下发到其所在节点的数据平面执行。此外,cilium-agent
还会将其节点上创建的端点(Endpoints)或身份(Identities)等信息以 Kubernetes 自定义资源(CRD)的形式写回 Kubernetes API。
这种控制平面与数据平面的分离架构带来了可扩展性和弹性。数据平面利用 eBPF 在内核级别运行,能够高效处理大量网络流量;而控制平面则负责与编排系统交互并管理数据平面的逻辑。然而,在规模较大的集群中,每个 cilium-agent
都需要监视多种 Kubernetes CRD(可能多达 15 种以上),并且频繁地向 Kubernetes API 服务器进行读写操作(例如更新 CiliumEndpoint 和 CiliumIdentity CR),这可能会对 Kubernetes API 服务器造成较大压力。为了缓解这个问题,Cilium 支持使用专用的键值存储(如 etcd)来分担 Kubernetes API 服务器的负载,用于存储工作负载身份、端点和 IP 到身份的映射等信息。这种方式将这些关键数据的存储和同步从 Kubernetes CRD 转移到了更高效的专用数据库中,从而提升了大规模集群下的控制平面性能和可扩展性。
3.2. Cilium Agent (cilium-agent
)
Cilium Agent (cilium-agent
) 是 Cilium 的核心组件之一,它以守护进程的形式运行在集群中的每一个节点上。其主要职责包括:
- 配置接收与转换:Agent 通过 Kubernetes API 或其他 API 接口接收描述网络连接、服务负载均衡、网络策略以及可见性和监控需求的配置信息。
- 事件监听:Agent 监听来自 Kubernetes 等编排系统的事件,例如容器或工作负载的启动和停止,以便及时更新网络配置。
- eBPF 程序管理:Agent 的核心任务是管理 Linux 内核中的 eBPF 程序。它将接收到的高级配置(如网络策略)编译或加载为 eBPF 字节码,并将其附加到内核的适当挂钩点,从而控制进出该节点上容器的所有网络访问。
- 本地状态维护:Agent 维护其所在节点的网络状态和端点信息。
3.3. Cilium Operator
Cilium Operator 负责处理集群中那些逻辑上应该在整个集群级别处理一次的任务,而不是在每个节点上都处理的任务。与 Agent 不同,Operator 并不处于数据转发或网络策略决策的关键路径上,集群在 Operator 短暂不可用时通常仍能正常运行。
然而,根据配置的不同,Operator 的不可用可能会导致:
- IP 地址管理 (IPAM) 延迟:如果 Operator 负责分配新的 IP 地址,其故障会导致新工作负载调度延迟。
- 键值存储心跳更新失败:这可能导致 Agent 认为键值存储不健康并重启。
3.4. Cilium CLI (cilium
和 cilium-dbg
)
Cilium 提供了两个主要的命令行工具:
cilium
CLI:这是一个用于快速安装、管理和故障排除运行 Cilium 的 Kubernetes 集群的命令行工具。用户可以使用它来安装 Cilium、检查 Cilium 安装状态、启用/禁用特性(如 ClusterMesh、Hubble)等。cilium-dbg
(Debug Client):这是一个与 Cilium Agent 一同安装在每个节点上的命令行工具。它通过与同一节点上运行的 Cilium Agent 的 REST API 交互,允许检查本地 Agent 的状态和各种内部信息。此外,它还提供了直接访问 eBPF 映射以验证其状态的工具。需要注意的是,这个内嵌于 Agent 的cilium-dbg
与用于集群管理的cilium
CLI 是不同的工具。
3.5. CNI 插件 (cilium-cni
)
cilium-cni
插件在 Kubernetes 环境中扮演着关键角色。当 Kubernetes 在某个节点上调度或终止一个 Pod 时,它会调用该节点上的 cilium-cni
插件。该插件随后会与该节点的 Cilium API(由 cilium-agent
提供)进行交互,以触发必要的数据平面配置,为 Pod 提供网络连接、负载均衡和网络策略实施。
3.6. 数据存储 (Data Store)
Cilium 需要一个数据存储来在各个 Agent 之间传播状态信息。它支持以下两种主要的数据存储方式:
- Kubernetes CRDs (Custom Resource Definitions):这是默认的存储和传播状态的方式。Kubernetes CRD 允许集群组件通过 Kubernetes 资源来表示配置和状态。Cilium 利用 CRD 来存储如身份、网络策略等信息。
- 键值存储 (Key-Value Store):作为一种优化选项,尤其是在大规模集群(例如超过 500 个节点)中,可以使用键值存储来提高可扩展性。直接使用键值存储在变更通知和存储需求方面通常比 CRD 更高效。目前支持的键值存储是 etcd。
3.7. eBPF 基础:指令集、映射、辅助函数、尾调用
eBPF 作为 Cilium 的核心技术,其本身拥有一套完整的架构体系,理解这些基础构件对于深入理解 Cilium 的工作原理至关重要。
指令集 (Instruction Set):eBPF 拥有一套通用的精简指令集(RISC),最初设计用于以 C 语言的子集编写程序,并通过编译器后端(如 LLVM)编译成 eBPF 指令。这些指令是固定长度的 64 位编码,包含了加载(BPF_LD, BPF_LDX)、存储(BPF_ST, BPF_STX)、算术逻辑单元(BPF_ALU, BPF_ALU64)和跳转(BPF_JMP)等操作指令类别。eBPF 程序拥有 11 个 64 位寄存器(r0-r10)、一个程序计数器和一个 512 字节的栈空间。
映射 (Maps):eBPF 映射是驻留在内核空间的高效键值存储,是 eBPF 程序存储和共享状态的关键机制。Cilium 大量使用 eBPF 映射来存储策略规则、连接跟踪条目、服务负载均衡信息、IP 与身份的映射关系等。内核提供了多种映射类型,如哈希表(hash)、数组(array)、每 CPU 数组(per-CPU array)、最近最少使用(LRU)哈希表、最长前缀匹配(LPM)树、程序数组(prog array,用于尾调用)等。这些映射可以通过文件描述符从用户空间访问,实现了内核态 eBPF 程序与用户态控制平面(如 Cilium Agent)之间的数据交换。
辅助函数 (Helper Functions):辅助函数是内核提供的一组预定义函数,eBPF 程序可以通过调用这些函数来与内核其他子系统交互或执行特定操作,例如操作映射(查找、更新、删除元素)、修改数据包内容、获取当前时间戳、进行尾调用等。可用的辅助函数集合取决于 eBPF 程序的类型。
尾调用 (Tail Calls):尾调用是一种机制,允许一个 eBPF 程序调用另一个 eBPF 程序,而无需返回到原始程序。它通过特殊的程序数组映射(
BPF_MAP_TYPE_PROG_ARRAY
)实现,并使用bpf_tail_call()
辅助函数触发。尾调用开销极小(类似于长跳转),并且允许将复杂的 eBPF 程序分解为更小、更易于管理的模块化单元。Cilium 利用尾调用来构建灵活和可扩展的数据路径逻辑。
3.8. eBPF 验证器与 JIT 编译器
为了确保内核的安全性和稳定性,eBPF 程序在加载到内核之前必须经过严格的验证过程,并且为了获得最佳性能,通常会进行即时编译(JIT)。
验证器 (Verifier):内核中的 eBPF 验证器负责静态分析 eBPF 程序的字节码。它会检查程序是否会访问未授权的内存区域、是否包含可能导致内核崩溃的无限循环(尽管指令集包含后向跳转,验证器会禁止循环以保证程序终止)、是否遵循类型安全等。只有通过验证器检查的 eBPF 程序才被允许加载和执行。
JIT 编译器 (Just-In-Time Compiler):一旦 eBPF 程序通过验证,内核中的 JIT 编译器会将其字节码动态编译成本地机器指令。这使得 eBPF 程序能够以接近原生代码的速度在 CPU 上执行,显著提高了性能。主流的 CPU 架构(如 x86_64, arm64)都拥有内核内置的 eBPF JIT 编译器。
3.9. Cilium 中的 eBPF 程序类型:XDP 与 TC Hook
Cilium 在其数据平面中广泛利用了 Linux 内核网络栈提供的多种 eBPF 挂钩点,通过在这些点上加载 eBPF 程序来实现其网络、安全和负载均衡功能。
XDP (eXpress Data Path):XDP 挂钩点位于网络驱动程序接收数据包的最早阶段,甚至在内核为数据包分配套接字缓冲区(
sk_buff
)之前。这使得 XDP 程序能够以极高的性能处理数据包。Cilium 主要利用 XDP 进行早期的数据包过滤(例如,基于 CIDR 的预过滤,丢弃恶意或非预期流量)和某些场景下的负载均衡加速。TC (Traffic Control) Ingress/Egress Hooks:TC 挂钩点位于网络接口的流量控制层,分别在数据包进入协议栈(ingress)和离开协议栈(egress)时触发。与 XDP 不同,TC 层的 eBPF 程序操作的是
sk_buff
,可以访问更丰富的包元数据。Cilium 在 TC ingress 挂钩点上加载 eBPF 程序,用于实现 L3/L4 网络策略实施、端点识别、流量重定向到本地端点或 Envoy 代理等。对于容器流量,Cilium 通常将 eBPF 程序附加到连接容器的虚拟以太网设备(veth pair)的宿主机端 TC 挂钩点上,以监控和控制进出容器的所有流量。Socket Operations 和 Socket Send/Recv Hooks:这些挂钩点与套接字操作相关联。Socket operations hook 附加到特定的 cgroup,并在 TCP 事件(如连接建立)发生时触发。Cilium 利用它来监控 TCP 连接状态,并在连接建立后附加 socket send/recv BPF 程序。Socket send/recv hook 在 TCP 套接字执行发送操作时运行,允许 eBPF 程序检查消息内容并决定是将其传递给 TCP 层、丢弃还是重定向到另一个套接字。Cilium 使用这些套接字层面的 hook 来加速数据平面重定向,例如在服务网格场景中或进行 socket 层负载均衡。
3.10. Cilium eBPF Datapath 配置与优化
Cilium 数据平面的功能和行为在很大程度上取决于其 eBPF 程序的配置。这些配置值,如特性开关、地址、超时、安全 ID 等,由 Cilium Agent 在加载 BPF 程序时提供。
Cilium 采用了一种巧妙的机制来将配置传递给 eBPF 程序并实现基于配置的优化。通过在 C 头文件中使用 DECLARE_CONFIG()
和 NODE_CONFIG()
宏来声明配置变量,这些声明会在编译时自动生成相应的 Go 代码,允许 Agent 在启动时设置这些值。eBPF 程序则通过 CONFIG()
宏来访问这些配置值。
一个关键的优化点在于,对于 Linux 内核 5.2 及更高版本,Cilium 利用只读 eBPF 映射来存储这些配置数据。当 eBPF 程序中的条件分支依赖于这些只读映射中的配置值时,内核的 eBPF 验证器能够执行死代码消除(dead code elimination)。这意味着,如果根据当前配置,某些代码路径永远不会被执行,验证器会在 JIT 编译之前将这些不可达的分支从程序中移除。这种机制使得 Cilium 可以交付一套通用的 BPF 源代码,并在加载时根据具体启用的特性动态地裁剪和优化内核中实际运行的 BPF 字节码,从而在不牺牲灵活性的前提下,最大程度地提升了数据平面的性能和效率。这也为构建一个“clang-free”的 Agent(即 Agent 本身不依赖于在运行时编译 BPF 代码)奠定了基础,减少了 Agent 的体积并加快了启动速度。
3.11. Cilium eBPF 映射 (Maps) 详解
eBPF 映射是 Cilium 数据平面的核心数据结构,用于存储和检索状态信息,从而实现各种网络功能。理解这些映射的类型、用途和规模限制对于掌握 Cilium 的工作原理、进行故障排除和性能调优至关重要。所有 eBPF 映射在创建时都有容量上限,超出限制的插入操作会失败,这直接影响数据平面的可扩展性。Cilium 会根据系统总内存的一定比例自动推导某些大型映射的默认大小,但高级用户也可以通过命令行参数或 Helm 配置覆盖这些默认值。
以下是一些关键的 Cilium eBPF 映射类型及其功能:
映射名称 (示例) | 范围 (Scope) | 默认限制 (Default Limit) | 用途与核心功能支持 |
策略映射 (Policy Map) | 端点 (Endpoint) | 16k | 存储每个端点允许的身份、端口和协议组合,用于实施 L3/L4 网络策略。键通常包含身份、流量方向、端口/协议,值定义了策略行为(如允许、拒绝、审计)。是 Cilium 安全功能的核心。 |
连接跟踪映射 (CT Map) | 节点或端点 | 1M TCP / 256k UDP | 跟踪活动的 TCP 和 UDP 连接状态,用于实现有状态防火墙和 NAT。键通常是连接的五元组,值包含连接状态、超时等信息。对网络和安全至关重要。Cilium 根据节点总内存计算其大小,最小为 131072 条目。 |
服务/负载均衡映射 (Service LB Map) | 节点 (Node) | 64k | 存储 Kubernetes Service (ClusterIP, NodePort) 的 IP 地址到后端 Pod IP 的映射,是 kube-proxy 替换功能的核心。键是 Service IP 和端口,值是后端端点信息。其大小影响可支持的服务数量。 |
IP 缓存/身份映射 (IPCache) | 节点 (Node) | 512k | 缓存 IP 地址到 Cilium 安全身份的映射。键是 IP 地址,值是安全身份及相关元数据。对于基于身份的策略执行和高效查找至关重要,加速了策略决策过程。 |
隧道映射 (Tunnel Map) | 节点 (Node) | 64k | 在覆盖网络模式(如 VXLAN, Geneve)下,存储远端节点的隧道端点信息(如 VTEP IP)。键是远端节点 IP,值是隧道端点信息。支持跨节点网络连接。 |
NAT 映射 (NAT Map) | 节点 (Node) | 512k | 存储网络地址转换(NAT)条目,例如用于出向流量的源地址伪装(SNAT)。键可能是原始源 IP/端口,值是转换后的 IP/端口。支持 Pod 与外部网络通信。其大小不能超过连接跟踪表总大小的 2/3。 |
LPM Trie 映射 (CIDR 策略) | 节点 (Node) | (未明确, 但依赖其他) | 使用最长前缀匹配(LPM)算法高效存储和查询基于 CIDR 的策略规则。键是网络前缀,值是与该 CIDR 相关的策略信息或身份。用于实现基于 IP 地址段的访问控制。 |
邻接表映射 (Neighbor Table) | 节点 (Node) | 512k | 存储邻居信息,如 ARP 表项(IPv4)或 NDP 表项(IPv6)。用于解析本地网络上 IP 地址对应的 MAC 地址。是基础网络通信所必需的。 |
端点映射 (Endpoints Map) | 节点 (Node) | 64k | 存储本地节点上的端点(Pod)和主机 IP 的信息。用于识别和管理节点内的网络端点。 |
代理映射 (Proxy Map) | 节点 (Node) | 512k | 存储被重定向到用户空间代理(如 Envoy)的 TCP 连接信息。用于 L7 策略执行和服务网格功能。 |
会话亲和性映射 (Session Affinity) | 节点 (Node) | 64k | 存储会话亲和性信息,确保来自同一客户端的后续请求被定向到同一后端 Pod。用于有状态应用的负载均衡。 |
伪装映射 (Masquerade Maps) | 节点 (Node) | 各 16k (IPv4/IPv6) | 存储用于基于 BPF 的 ip-masq-agent 的 IPv4/IPv6 CIDR。用于出向流量的源地址伪装。 |
Egress 策略映射 | 端点 (Endpoint) | 16k | 存储 Egress 策略中跨所有目标 CIDR 的端点信息。用于控制 Pod 的出向流量。 |
这些 eBPF 映射共同构成了 Cilium 高效数据平面的基础,使得 Cilium 能够在内核级别快速做出网络决策,实现精细化的策略控制和灵活的网络功能。对这些映射的正确配置和监控,对于保障 Cilium 集群的稳定性和性能至关重要。
4. 网络能力
Cilium 凭借其基于 eBPF 的数据平面,提供了强大且灵活的网络能力,远超传统 CNI 插件。它不仅实现了 Kubernetes 的标准网络功能,还引入了多项高级特性,以满足现代云原生应用对高性能、高可扩展性和高安全性的需求。
4.1. Kubernetes CNI 实现
作为一款符合 CNI规范的插件,Cilium 负责管理 Kubernetes 集群中 Pod 的网络连接。其核心职责包括:
- IP 地址管理 (IPAM):为 Pod 分配 IP 地址。Cilium 支持多种 IPAM 模式,包括
kubernetes
(使用 Kubernetes API 分配节点级 Pod CIDR)、cluster-pool
(Cilium 管理的全局 IP 地址池)、以及与特定云提供商集成的模式(如 AWS ENI、Azure IPAM)。 - 网络接口配置:为每个 Pod 创建和配置网络接口(通常是 veth pair),并将其连接到宿主机网络。
- Pod 间连接:利用 eBPF 程序在内核级别高效地路由 Pod 之间的流量,无需依赖传统的 iptables 或 IPVS 规则。
Cilium 支持多种网络模式,以适应不同的底层网络环境和需求:
- 覆盖网络 (Overlay Mode):通过 VXLAN 或 Geneve 等封装技术,在所有宿主机之上构建一个虚拟的 L3 网络。这种模式对底层网络基础设施的要求最低,只需要宿主机之间具有 IP 连通性即可。但由于引入了封装头,会略微降低有效 MTU,可能影响最大吞吐率,可以通过启用巨型帧(Jumbo Frames)来缓解。部署时需要确保底层网络防火墙允许相应的封装协议端口(VXLAN 默认 UDP 8472,Geneve 默认 UDP 6081)。
- 原生路由 (Native Routing / Direct Routing):直接使用宿主机的路由表进行 Pod IP 的路由。这种模式下,底层网络必须能够感知并路由 Pod 的 IP 地址。它通常具有更好的性能(无封装开销),但对网络基础设施的集成要求更高,可能需要 BGP 路由协议或云提供商的路由服务支持。
- 云提供商特定模式 (Cloud Provider Specific Modes):Cilium 与主流云提供商(如 AWS、Azure、GCP)的网络服务深度集成,例如 AWS ENI 模式允许将 VPC 子网的 IP 地址直接分配给 Pod。这种模式能够充分利用云平台的网络能力,简化与云服务的集成,但可能受到云平台自身的一些限制,如单个实例可挂载的 ENI 数量或 IP 地址密度。
选择何种网络模式是一个关键的决策,它需要在部署简易性、性能需求、IP 地址规划以及与现有网络基础设施的集成度之间进行权衡。覆盖网络模式因其对底层网络的依赖性小,通常是入门或网络环境受限时的首选。原生路由模式则更适合对性能有较高要求且具备相应网络控制能力的场景。而云提供商特定模式则是在特定云环境中深度集成和优化的选择。
4.2. 高级负载均衡
Cilium 实现了分布式的负载均衡机制,能够高效处理集群内部(东西向)和外部到集群(南北向)的流量,并声称可以完全替代 kube-proxy
组件。
其核心优势在于:
- 基于 eBPF 的高效实现:Cilium 使用高效的 eBPF 哈希表(如
cilium_lb_services_v2
和cilium_lb_backends
映射)在内核级别进行服务 IP 到后端 Pod IP 的转换和流量分发。 kube-proxy
替代:通过绕过传统的 iptables 或 IPVS 规则,Cilium 的负载均衡机制避免了大规模规则集带来的性能开销和更新延迟,从而提升了服务路由的性能、降低了延迟,并增强了大规模集群下的可扩展性。对于源自本地节点的流量,eBPF 可以在套接字层(TCP 连接时)进行服务转换;对于外部流量,则在 TC 或 XDP 钩子点进行处理,有效减少了每个数据包的 NAT 操作开销。- XDP 加速:对于 NodePort、LoadBalancer 和 externalIP 类型的服务,Cilium 支持在兼容的网卡上启用 XDP(eXpress Data Path)加速。XDP 允许在网络驱动层直接处理数据包,可以实现直接服务响应(DSR)和 Maglev 一致性哈希等高级负载均衡策略,从而最大化性能并降低延迟。
- 多种负载均衡算法:Cilium 支持包括轮询(Round-Robin)、一致性哈希(Consistent Hashing)和最少连接(Least Connections)在内的多种负载均衡算法,以适应不同应用场景的需求。
用 eBPF 原生实现的服务处理机制替代 kube-proxy
是 Cilium 在性能和可扩展性方面的一大进步。这不仅简化了 Kubernetes 节点的网络栈,也使得服务负载均衡与 Cilium 整体以 eBPF 为中心的数据平面设计保持一致。然而,这也意味着在排查服务相关问题时,需要理解 eBPF 映射(如服务映射、后端映射)的工作方式,而非传统的 iptables 规则。
4.3. 服务发现与路由
Cilium 提供了强大的网络和服务发现能力,能够实时自动发现并跟踪集群中所有的 Pod、Service 和 Endpoint。这确保了网络策略和路由决策始终基于最新的集群状态,对于动态变化的云原生环境至关重要。Cilium 与 Kubernetes 内置的服务发现机制(通常基于 DNS)紧密集成,确保应用可以透明地发现和访问其他服务。
4.4. ClusterMesh:跨集群网络与服务发现
Cilium ClusterMesh 是一项关键特性,旨在解决多 Kubernetes 集群环境下的网络连接、服务发现和负载均衡挑战。它允许将地理上分散或逻辑上独立的多个 Kubernetes 集群连接起来,形成一个统一的网络平面,使得跨集群的 Pod 间可以直接通信,服务可以被全局发现和访问,就如同它们在同一个集群中一样。
ClusterMesh 架构特性:
- 控制平面:每个参与 ClusterMesh 的集群都会运行一个
clustermesh-apiserver
组件。该组件负责管理集群间的证书颁发与同步,并暴露控制平面接口,以便其他集群能够安全地与之通信和同步状态信息。 - 连接要求:要成功建立 ClusterMesh,集群之间必须满足一些前提条件,包括:节点间和 Pod 间的 IP 连通性(通常通过 VPN、专线或云提供商的对等连接实现)、所有集群使用唯一的、不冲突的 Pod CIDR 地址范围、以及相同的 Cilium 数据路径模式(如均为封装模式或均为原生路由模式)。
- 安全通信:ClusterMesh 通常依赖共享的证书颁发机构(CA)来确保跨集群控制平面通信的安全性。
- 全局服务 (Global Services):通过在 Kubernetes Service 的注解中添加
service.cilium.io/global: "true"
,可以将该服务声明为全局服务。Cilium 会自动在所有连接的集群中同步这些全局服务的信息,并实现跨集群的负载均衡,将流量导向位于不同集群中的后端 Pod。 - 跨集群网络策略:Cilium 允许定义跨集群的网络策略。通过在
CiliumNetworkPolicy
的选择器中指定集群名称(例如io.cilium.k8s.policy.cluster: cluster1
),可以精确控制来自特定集群中特定 Pod 的流量是否可以访问另一个集群中的特定 Pod。
ClusterMesh 对于构建地理分布式、高可用或混合云应用具有重要意义。它极大地简化了多集群应用的运维复杂性,但同时也要求在 IP 地址规划、集群间网络连通性保障以及跨集群安全策略设计方面进行仔细规划。目前,ClusterMesh 支持连接多达 255 个集群,这对于绝大多数大规模部署场景而言是足够的。
5. 安全范式:基于身份的策略执行及其他
Cilium 的安全模型以其创新的基于身份的策略执行为核心,并结合了透明加密、运行时安全增强等多种机制,旨在为云原生工作负载提供全面而精细的安全防护。
5.1. 网络策略实现
Cilium 的网络策略实现是其安全能力的核心,它超越了传统基于 IP 地址和端口的防火墙规则,引入了更灵活、更动态的基于身份的安全模型。
基于身份的安全 (Identity-Based Security):Cilium 的一个根本性设计原则是将安全策略与网络地址(IP 地址)解耦。它为每个 Pod 或工作负载分配一个安全身份(Security Identity),这个身份通常基于 Kubernetes 的标签(Labels)或其他元数据自动派生而来。网络策略随后基于这些身份来定义,而不是基于易变的 IP 地址。这种方法极大地增强了策略的动态适应性和可扩展性,尤其是在 Pod IP 地址频繁变化的 Kubernetes 环境中。
Kubernetes NetworkPolicy 与 CiliumNetworkPolicy (CNP):Cilium 完全兼容并实现了标准的 Kubernetes
NetworkPolicy
API。然而,为了提供更高级和更细粒度的控制能力,Cilium 引入了自定义资源定义(CRD)——CiliumNetworkPolicy
(CNP)。CNP 扩展了 KubernetesNetworkPolicy
的功能,支持诸多高级特性,例如:- L7 应用层策略:针对 HTTP (方法、路径、头部)、Kafka (Topic、生产者/消费者角色)、gRPC (服务、方法) 等应用协议的精细化访问控制。
- 基于 DNS 的策略:允许基于域名 (FQDN) 定义策略,这对于目标 IP 地址动态变化或未知的场景非常有用。
- 面向实体 (Entities) 的策略:可以定义到预定义实体(如
world
代表集群外部所有端点,host
代表宿主机本身)的策略。 - 显式拒绝 (Deny) 规则:除了允许规则外,还可以定义明确的拒绝规则。
- 更丰富的选择器:支持更复杂的标签选择逻辑。
CiliumClusterwideNetworkPolicy (CCNP):CCNP 是另一种 Cilium CRD,它提供了集群范围的网络策略定义能力。CCNP 策略作用于整个集群,可以跨越所有命名空间,并能够覆盖特定命名空间内的策略。这对于实施全局性的基线安全规则、保护多租户集群的隔离性非常有用。例如,Google Kubernetes Engine (GKE) 就支持使用 Cilium CCNP。需要注意的是,目前在 GKE 的 CCNP 实现中,尚不支持 L7 策略和节点选择器。
L3/L4 及 API 感知的 L7 策略执行:Cilium 能够在 OSI模型的 L3(IP 地址、CIDR)和 L4(端口、协议)层面执行策略。更进一步,Cilium 凭借其 L7 策略能力,可以深入应用层协议内部,实现 API 感知的安全控制。例如,可以允许对
/api/v1/users
路径的GET
请求,但禁止POST
请求;或者只允许特定的 Kafka 客户端向特定的 Topic 生产消息。L7 策略的执行通常涉及到 Cilium 数据平面中集成的 Envoy 代理,eBPF 程序负责将相关的应用层流量高效地重定向到 Envoy 进行深度检查和策略匹配。策略执行机制:在数据平面,eBPF 程序被附加到网络接口的 TC 钩子点。当数据包到达时,eBPF 程序会检查其元数据(如源/目标 IP 和端口),在 eBPF 映射(如 IPCache)中查找源和目标的身份,然后查询策略映射(Policy Map)以确定相应的策略规则,并据此做出允许、拒绝或转发到 L7 代理的决定。
基于身份的策略模型是 Cilium 安全体系的基石。它摆脱了传统网络防火墙对 IP 地址的依赖,使得安全策略能够紧密贴合应用和服务的逻辑边界,而不是物理网络拓扑。这不仅提高了策略的灵活性和可维护性,也使得在高度动态的云原生环境中实现真正的微隔离成为可能。当然,这也要求用户在部署应用时制定良好的标签策略,以便 Cilium 能够准确地派生安全身份。同时,身份信息的分发、存储(在 IPCache 和策略映射中)及其查找效率,也是影响 Cilium 性能和可扩展性的关键因素。
5.2. 透明加密:IPsec 与 WireGuard
为了保护数据在网络传输过程中的机密性和完整性,Cilium 提供了对节点间流量进行透明加密的功能,支持 IPsec 和 WireGuard 两种主流的加密协议。
IPsec:
- Cilium 使用 Kubernetes Secrets 来管理和分发 IPsec 预共享密钥 (PSK)。
- 自 Cilium v1.18 起,在启用隧道模式(如 VXLAN)时,IPsec 加密操作发生在隧道封装之后。这意味着包括 Cilium 安全身份在内的原始数据包头信息也会被加密后传输,进一步增强了安全性。
- Cilium 推荐并强制使用基于共享密钥派生的每隧道 IPsec 密钥,以取代之前被认为不够安全的全局 IPsec 密钥。
- IPsec 的一些局限性包括:在某些配置下(如 CNI 链式部署、BPF 主机路由模式)不被支持;解密操作在每个 IPsec 隧道上可能受限于单个 CPU核心的性能。
WireGuard:
- WireGuard 是一种更现代、配置更简洁且通常被认为性能更高的 VPN 技术。
- 在 Cilium 中启用 WireGuard 时,每个节点会自动生成自己的密钥对,并通过
CiliumNode
CRD 的注解(network.cilium.io/wg-pub-key
)分发其公钥给其他节点。 - 节点间的 WireGuard 隧道一旦建立,所有符合条件的流量(默认为 Pod 间流量)都将被透明加密。
- Cilium 还支持 WireGuard 的节点到节点加密模式,该模式下,不仅 Pod 间流量,节点间的所有流量(包括 Pod 到节点、节点到 Pod)也会被加密。为了确保控制平面通信的可靠性,通常会将 Kubernetes 控制平面节点从此类加密中排除。
尽管具体的 eBPF 在加密过程中的详细作用未在提供的片段中阐述,但可以合理推断,eBPF 程序在数据路径中扮演着识别需要加密的流量并将其导向相应加密隧道(IPsec 或 WireGuard)的关键角色。
将加密功能直接集成到数据平面,是 Cilium 的一个重要特点。这为用户提供了一种相对简单的方式来实现基础的链路加密,而无需为每个服务单独配置和管理 mTLS(尽管服务网格层面的 mTLS 提供了更细粒度的身份验证和应用层加密)。这种内核级的透明加密可以作为一种补充性的安全层,特别适用于那些对所有网络流量都有加密需求的场景,或者在尚未部署完整服务网格的环境中。
5.3. Tetragon:基于 eBPF 的安全可观测性与运行时增强
Tetragon 是 Cilium 生态系统中的一个重要子项目,它将 eBPF 的能力从网络层面扩展到了更广泛的主机运行时安全领域,提供了强大的安全可观测性和运行时增强(Runtime Enforcement)功能。
架构与原理:Tetragon 利用 eBPF 传感器(Sensors)动态地将监控逻辑注入到 Linux 内核的多个关键挂钩点,如系统调用、内核函数(kprobes)、用户空间函数(uprobes)和跟踪点(tracepoints)。通过这些传感器,Tetragon 能够实时捕获和分析系统行为,并将收集到的事件用丰富的 Linux 内核元数据和 Kubernetes 元数据(如命名空间、Pod 名称、容器 ID 等)进行增强。
事件检测能力:Tetragon 能够检测到多种对安全分析至关重要的运行时事件,包括但不限于:
- 进程执行事件:默认情况下,Tetragon 会生成
process_exec
(进程启动)和process_exit
(进程退出)事件,从而提供完整的进程生命周期可见性。 - 系统调用活动:通过 kprobes、tracepoints 等机制,可以监控任意系统调用的发生及其参数。
- 文件访问:可以监控对特定文件或目录的读、写、打开等操作。
- 网络活动:提供网络连接、数据包传输等网络层面的可见性,并能与 Cilium 的网络可观测性数据关联。
- 权限提升:能够检测到进程权限变化等敏感操作。
- 进程执行事件:默认情况下,Tetragon 会生成
Kubernetes 感知:Tetragon 的一个核心特性是其 Kubernetes 感知能力。它能够理解 Kubernetes 的对象模型和身份(如 Pod、Namespace、Deployment 等),并将这些上下文信息关联到捕获到的安全事件中。这使得安全策略的定义和事件的分析可以紧密围绕 Kubernetes 的工作负载进行,而不是孤立的进程或 IP 地址。
运行时增强 (Runtime Enforcement):除了提供安全可观测性,Tetragon 还具备在运行时对检测到的恶意或不合规行为做出反应的能力。这是通过
TracingPolicy
CRD 实现的,用户可以在策略中定义selectors
来匹配特定的事件模式,并通过matchActions
来指定响应动作。一个常见的响应动作是发送SIGKILL
信号给违反策略的进程,从而主动阻止潜在的威胁。例如,可以定义策略来阻止对敏感文件(如/etc/shadow
)的读取尝试,一旦检测到此类行为,Tetragon 就会终止相关进程。Tetragon 的文档还提到了Override
等其他可能的动作类型,允许更细致地干预系统行为。
Tetragon 的出现,标志着 Cilium 生态系统将 eBPF 的应用从纯粹的网络领域成功扩展到了主机安全和运行时保护。通过在内核级别进行无侵入的、低开销的监控和增强,Tetragon 为云原生环境提供了一种全新的、更为强大的安全解决方案。它与 Cilium 的网络策略能力相结合,使得用户能够构建一个覆盖网络和主机两个层面的统一安全平台,这对于实现深度防御和零信任安全架构具有重要意义。
5.4. 其他运行时安全特性
除了 Tetragon 提供的广泛运行时安全能力外,Cilium 项目本身也利用 eBPF 在网络策略执行层面实现了一些运行时安全特性。例如,当网络策略被违反时,Cilium 的 eBPF 程序可以直接在内核中丢弃不合规的数据包,这本身就是一种运行时增强。此外,Cilium 也提及了文件完整性监控(File Integrity Monitoring, FIM)作为其利用 eBPF 实现的安全功能之一。然而,对于更全面的、专门针对主机层面的安全可观测性和运行时增强,Tetragon 是 Cilium 生态中的首选组件。
6. Hubble 可观测性
Hubble 是 Cilium 内置的可观测性平台,旨在为云原生环境提供深入的网络流量可见性、服务依赖关系映射以及策略执行情况的洞察。它与 Cilium 紧密集成,并充分利用 eBPF 的能力在内核级别收集数据,从而实现低开销、高性能的监控。
6.1. Hubble 架构:Server、Relay、CLI 与 UI
Hubble 采用分层架构,以支持从单节点调试到集群范围监控的各种需求:
Hubble Server:Hubble Server 作为 Cilium Agent 的一部分,嵌入式运行在集群中的每个节点上。它的主要职责是从该节点上的 Cilium Agent 处获取基于 eBPF 的原始可见性数据(如网络流事件)。为了实现高性能和低开销,这种嵌入式设计使得数据收集路径非常短。Hubble Server 通过 gRPC 服务向外暴露收集到的流数据和 Prometheus 指标。
Hubble Relay (
hubble-relay
):Hubble Relay 是一个独立部署的组件,通常在集群范围内运行一个或多个实例。Relay 能够感知集群中所有正在运行的 Hubble Server,并连接到它们各自的 gRPC API。它会从各个 Hubble Server 收集流数据,聚合成一个集群范围的统一视图,并通过自身的 API 提供服务。这种设计避免了用户需要直接查询每个节点的 Agent,简化了集群级监控的实现。Hubble CLI (
hubble
):Hubble CLI 是一个命令行工具,允许用户与 Hubble 系统进行交互。它可以连接到单个节点的 Hubble Server(用于本地调试和细粒度观察)或连接到 Hubble Relay(用于获取集群范围的聚合数据)。通过 Hubble CLI,用户可以实时观察、过滤和检索网络流事件。Hubble UI (
hubble-ui
):Hubble UI 是一个图形用户界面,它利用 Hubble Relay 提供的聚合数据,以可视化的方式展示服务依赖关系图和网络连接拓扑。用户可以通过 UI 直观地理解服务间的通信模式、发现潜在的网络问题,并观察策略的执行效果。
Hubble 的这种分层架构设计,兼顾了数据收集的效率和数据查询的便捷性。本地 Hubble Server 的高效数据采集保证了对系统性能影响最小化,而 Hubble Relay 的聚合能力则为用户提供了进行集群级分析和故障排除的强大工具。gRPC API 的使用也为 Hubble 与其他可观测性系统(如日志管理、追踪系统)的集成提供了可能性。
6.2. eBPF 驱动的可视性:流日志、服务地图、策略裁决
Hubble 的核心能力源于 Cilium 对 eBPF 技术的深度运用。Cilium Agent 通过加载到内核的 eBPF 程序,能够在数据包处理路径的关键节点捕获详细的网络流信息。这些信息随后被 Hubble Server 收集并处理。
Hubble 提供的可见性包括:
- 详细的流日志 (Flow Logs):记录了每个网络连接的 L3/L4 信息,如源/目标 IP 地址和端口、协议类型(TCP, UDP, ICMP 等)、数据包计数、字节数等。如果配置了 L7 网络策略,Hubble 还能提供应用层协议的可见性,例如 HTTP 请求的方法、路径、状态码,DNS 查询的域名和响应,Kafka 消息的 Topic 等。
- 实时服务依赖地图 (Service Maps):基于捕获到的网络流数据,Hubble 能够动态生成服务之间的依赖关系图,清晰地展示出微服务架构中各个组件是如何相互通信的。这对于理解复杂应用的拓扑结构、识别关键路径和潜在瓶颈非常有价值。
- 策略裁决 (Policy Verdicts):对于每一条被观察到的网络流,Hubble 都会记录 Cilium 网络策略对其的裁决结果,例如是被允许 (FORWARDED)、被拒绝 (DROPPED) 还是处于审计模式 (AUDIT)。这使得用户能够直观地了解网络策略的实际执行情况,并快速定位由于策略配置不当导致的连接问题。
通过这些由 eBPF 驱动的可见性特性,Hubble 能够回答诸如“哪些服务正在相互通信?”、“服务间的通信频率如何?”、“为什么某个连接失败了?是 DNS 解析问题、TCP 连接问题还是 HTTP 层面问题?”、“哪些流量被网络策略阻止了?”等关键问题。
6.3. 指标与监控:集成 Prometheus 和 Grafana
除了提供实时的流数据和拓扑视图外,Cilium 和 Hubble 还暴露了大量的性能指标,这些指标可以被 Prometheus 等监控系统收集,并用于在 Grafana 等仪表盘工具中进行可视化和告警。
这些指标覆盖了 Cilium 和 Hubble 运行的各个方面,包括:
- Cilium Agent 指标:如端点(Endpoint)的创建和再生频率、数据路径错误计数、策略导入错误计数、连接跟踪表垃圾回收(GC)时长、eBPF 映射压力、IPAM 地址分配情况等。
- Cilium Operator 指标:如管理的 CRD 数量、控制器运行状况等。
- Hubble 指标:如处理的流数量、丢弃的事件数量、DNS 查询和响应统计、HTTP 请求和延迟统计、Kafka 消息统计等。
- 网络性能指标:如数据包丢弃计数(按原因和方向)、转发数据包计数和字节数等。
- 安全相关指标:如策略执行计数、身份分配数量等。
默认情况下,Cilium 和 Hubble 的指标端点可能并未开启,需要通过配置(例如 Helm values)来启用它们,通常会分别在 Cilium Agent、Operator 和 Hubble Relay 上暴露不同的端口(如 9962, 9963, 9965)供 Prometheus 抓取。Cilium 社区也提供了一些预置的 Grafana 仪表盘模板,帮助用户快速开始监控。
这些丰富的指标数据为运维团队提供了量化评估 Cilium 集群健康状况、网络性能、安全策略有效性以及进行容量规划和主动故障排除的坚实基础。虽然指标数量众多,但通过理解关键指标的含义(例如 cilium_datapath_errors_total
反映数据路径健康状况,hubble_drop_total
指示策略或连接问题),并结合预置的仪表盘,可以有效地利用这些数据。
6.4. Hubble 实战:流量监控与故障排除
Hubble 提供的 CLI 和 UI 工具是进行实时流量监控和网络故障排除的利器。
Hubble CLI (
hubble observe
):允许用户直接从命令行观察和过滤网络流。可以通过多种参数来精确指定要观察的流量范围,例如:- 按 Pod 名称、命名空间或身份进行过滤:
hubble observe --pod default/myapp --namespace myns --identity 123
- 按协议类型过滤:
hubble observe --protocol http
- 按策略裁决结果过滤:
hubble observe --verdict DROPPED
- 按时间范围过滤:
hubble observe --since 5m
(观察过去5分钟的流量) - 组合过滤条件以进行更精确的定位。 例如,命令
kubectl exec -n kube-system ds/cilium -- hubble observe --pod default/tiefighter
可以用来观察特定 Pod (default/tiefighter
) 的所有网络流。输出结果会显示每个流的详细信息,包括时间戳、源和目标、协议、端口以及策略裁决等。
- 按 Pod 名称、命名空间或身份进行过滤:
Hubble UI:提供了一个可视化的界面,可以动态展示服务依赖图、网络拓扑以及实时流量信息。用户可以通过点击图中的节点或连接来查看更详细的流数据和策略信息。UI 对于理解复杂应用的服务间交互模式、快速发现异常连接或策略问题非常有帮助。
在故障排除场景中,Hubble 可以用于:
- 识别被策略拒绝的流量:通过过滤
DROPPED
的流,可以快速找到哪些连接因为网络策略而被阻止,并查看具体的策略信息。 - 诊断 DNS 解析问题:通过观察 DNS 相关的流(通常是到
kube-dns
或coredns
的 UDP/53 端口流量),可以判断 DNS 解析是否成功,是否存在延迟或丢包。 - 分析 L7 应用行为:对于启用了 L7 策略的流量(如 HTTP),Hubble 可以显示请求的方法、路径、响应状态码等,帮助诊断应用层的问题。
- 验证网络策略变更:在修改网络策略后,可以使用 Hubble 实时观察策略变更是否按预期生效。
以下是一个关键 Cilium 和 Hubble 指标的表格,可用于监控:
指标名称 (Metric Name) | 组件 (Component) | 描述 (Description) | 监控方面 (Aspect Monitored) |
cilium_endpoint_regenerations_total |
Agent | 端点重新生成的总次数 | 性能, 稳定性 |
cilium_datapath_errors_total |
Agent | 数据路径编程失败的总次数 | 数据路径健康 |
cilium_policy_import_errors_total |
Agent | 策略导入问题的总次数 | 安全, 策略 |
cilium_drop_count_total |
Agent | 按原因和方向统计的总丢包数 | 网络, 安全, 策略执行 |
cilium_forward_count_total |
Agent | 按方向统计的总转发包数 | 网络, 流量 |
bpf_map_pressure |
Agent | eBPF 映射所需大小与配置大小的比率 | 资源利用率, 性能 |
ipam_ips |
Agent | 已分配 IP 地址的数量 | 网络, 资源利用率 |
hubble_flows_processed_total |
Hubble | 按类型、子类型和裁决处理的总流数 | 可观测性, 网络流量 |
hubble_drop_total |
Hubble | 按原因和协议统计的丢包总数 | 安全, 网络, 策略执行 |
hubble_http_requests_total (或 httpV2 ) |
Hubble | HTTP 请求的总数 (v2 版本包含响应码和方法) | 应用层网络, 性能 |
hubble_dns_queries_total |
Hubble | 观察到的 DNS 查询总数 | 网络, DNS 解析 |
cilium_operator_controllers_failing |
Operator | Operator 中失败的控制器数量 | 控制平面健康 |
cilium_clustermesh_remote_clusters_failed |
Agent/Operator | 连接到远端集群失败的次数 | 多集群网络 |
通过结合使用这些工具和指标,运维团队可以有效地监控 Cilium 集群的网络状态,快速诊断并解决问题。
7. Cilium 服务网格
Cilium 正在将其基于 eBPF 的能力扩展到服务网格领域,旨在提供一种更高效、更轻量级的服务网格实现方案,尤其强调其“无 Sidecar”(Sidecar-less)的架构。传统服务网格(如早期 Istio)通常依赖于在每个应用 Pod 中注入一个 Sidecar 代理(如 Envoy)来拦截和处理所有进出流量,这会带来一定的资源开销和延迟。
7.1. Sidecar-less 架构:利用 eBPF 与 Envoy
Cilium 服务网格的核心思想是利用 eBPF 在内核层面进行高效的 L3/L4 网络处理、实现基于身份的安全以及智能地将 L7 流量重定向到 Envoy 代理进行处理。与传统 Sidecar 模型不同,Envoy 代理可以不作为每个 Pod 的一部分运行,而是以每个节点一个实例(per-node proxy)的方式部署,或者以其他更集中的方式运行(例如,Cilium 1.16 版本引入了将 L7 Envoy 代理作为专用 DaemonSet 运行的选项)。
这种架构的优势在于:
- 降低资源开销:减少了每个 Pod 中运行 Sidecar 代理所需的 CPU 和内存资源。
- 减少延迟:通过 eBPF 在内核级别进行部分处理和流量重定向,可以避免数据包在用户空间和内核空间之间的多次拷贝,从而降低网络延迟。
- 简化运维:管理和升级每个节点上的少量 Envoy 实例通常比管理成百上千个 Sidecar 代理更为简单。
eBPF 在此架构中扮演关键角色:它不仅负责高效地将需要 L7 处理的流量导向 Envoy,还能直接在内核中处理部分服务网格功能,如 L4 负载均衡和基于身份的 L4 安全策略。只有当需要进行复杂的 L7 协议解析、流量路由(如基于 HTTP Header 的路由)、TLS 终止或复杂的重试/超时逻辑时,流量才会被导向 Envoy。这种“尽可能在 eBPF 中处理,必要时回退到 Envoy”的策略,旨在最大化性能和效率。
然而,这种无 Sidecar 或节点级代理的模式也带来了一些不同的考量。例如,单个节点代理的故障可能会影响该节点上所有依赖其进行 L7 处理的 Pod,其“爆炸半径”相对较大。此外,所有在该节点上共享该代理的 Pod 的 TLS 密钥材料可能都由该代理进程持有,这在安全性方面需要仔细评估。
7.2. L7 流量管理
Cilium 服务网格利用集成的 Envoy 代理提供丰富的 L7 流量管理功能,这些功能通常通过 Cilium 的自定义资源(CRD)如 CiliumEnvoyConfig
或 CiliumClusterwideEnvoyConfig
进行配置。
主要 L7 流量管理能力包括:
- 流量切分 (Traffic Splitting):允许将流量按比例分配到服务的不同版本或实例。例如,可以将 90% 的请求路由到服务的 v1 版本,10% 路由到 v2 版本,以实现金丝雀发布或 A/B 测试。
- 头部/路径修改 (Header/Path Modification):支持在请求或响应过程中修改 HTTP 头部或 URL 路径。例如,可以根据特定条件重写 URL 路径,或者添加/删除自定义的 HTTP 头部。
- 熔断 (Circuit Breaking):通过配置如最大连接数、最大挂起请求数、最大请求数等参数,可以在后端服务出现故障或响应缓慢时,主动“熔断”到该服务的连接,防止雪崩效应,并允许服务有时间恢复。
- 速率限制 (Rate Limiting):虽然 Cilium Agent 本身具有 API 速率限制功能以保护自身免受过多请求的影响,但这与服务网格中的应用流量速率限制是不同的概念。对于 L7 应用流量的速率限制,Cilium 服务网格会依赖 Envoy 的原生速率限制能力。这通常涉及到在 Envoy 配置中定义 HTTP 速率限制过滤器,并可能需要与一个全局速率限制服务 (global rate limit service) 集成,以实现全局的、跨实例的速率控制。具体的配置方式会通过
CiliumEnvoyConfig
或CiliumClusterwideEnvoyConfig
CRD 将相应的 Envoy 过滤器配置注入到数据平面。
这些 L7 流量管理功能的核心在于通过 Cilium CRD 向 Envoy 代理注入配置。eBPF 负责高效地将相关流量导向 Envoy,而 Envoy 则根据这些配置执行具体的 L7 操作。这意味着用户在需要这些高级 L7 功能时,可能需要对 Envoy 的配置概念有一定程度的理解,即使这些概念被 Cilium CRD 进行了抽象。这也为排查 L7 相关问题时,检查 Envoy 的配置和日志提供了线索。
7.3. 双向认证 (mTLS)
双向 TLS (mTLS) 是服务网格中实现服务间安全通信的关键机制,它能确保通信双方的身份都得到验证,并且通信内容被加密。Cilium 服务网格也提供了对 mTLS 的支持,目前该功能处于 Beta 阶段。
Cilium 的 mTLS 实现具有以下特点:
- SPIFFE 集成:为了实现强大的、可移植的工作负载身份,Cilium 与 SPIFFE (Secure Production Identity Framework for Everyone) 标准集成。Cilium Operator 负责与 SPIRE 服务器(SPIFFE 的一种实现)交互,为集群中的工作负载(如 Pod)注册身份并获取相应的 SVID (SPIFFE Verifiable Identity Document)。
- 策略驱动:mTLS 的启用和执行与 Cilium 的网络策略紧密结合。通过在
CiliumNetworkPolicy
的 ingress 或 egress 规则中添加authentication: mode: "required"
块,可以要求匹配该规则的流量必须进行 mTLS 认证。 - 演进中的特性:mTLS 是 Cilium 服务网格中一个仍在积极发展和完善的领域。其 Beta 状态以及过去社区对其早期实现的一些讨论表明,用户在采用时应关注其成熟度和具体的功能表现。
mTLS 的实现依赖于可靠的工作负载身份(由 SPIFFE 提供)和策略驱动的执行机制。在数据层面,eBPF 程序可能负责识别需要进行 mTLS 的流量,并将其导向 Envoy 代理,由 Envoy 代理完成实际的 TLS 握手、证书验证和加解密操作。对于希望在 Cilium 服务网格中实现零信任安全的用户来说,mTLS 是一个核心组件,但鉴于其发展阶段,建议密切关注官方文档和社区更新。
7.4. Gateway API 支持
除了传统的 Kubernetes Ingress 资源,Cilium 也在积极扩展对新兴的 Kubernetes Gateway API 标准的支持。Gateway API 旨在提供比 Ingress 更富有表现力、更灵活、角色更清晰的 API,用于管理进入集群的流量。
Cilium 对 Gateway API 的支持包括:
- 作为控制平面:将 Gateway API 资源(如
Gateway
,HTTPRoute
等)作为 L7 流量管理的配置来源。 CiliumGatewayClassConfig
CRD:允许用户通过此 CRD 对GatewayClass
进行参数化配置,从而定制 Cilium 实现的 Gateway 的行为。- 部署要求:通常要求启用 NodePort 或
kube-proxy
替代功能,并启用 L7 代理(Envoy)。 - 暴露方式:可以通过 LoadBalancer 类型的 Service 或直接在宿主机网络上暴露 Gateway 监听器。
Gateway API 的引入为用户提供了更标准、更强大的方式来配置南北向流量管理,Cilium 对其的支持也反映了项目紧跟社区标准和发展趋势的努力。
7.5. 与 Istio 集成
Cilium 可以与现有的 Istio 服务网格控制平面进行集成。在这种模式下,Cilium 通常负责 CNI 层的功能(提供 Pod 网络和执行基础网络策略),而 Istio 则负责服务网格的控制平面逻辑(如服务发现、配置分发给 Envoy 代理)。
目前,这种集成通常要求 Istio 运行在其传统的基于 Sidecar 的数据平面模式下。Cilium 的文档提供了与 Istio ambient 模式和 Sidecar 模式集成的示例和指南。这种集成为那些已经投入 Istio 但希望利用 Cilium 强大的 eBPF 数据平面和网络策略能力的用户提供了一条路径。
8. 部署、运维与性能
成功部署和高效运维 Cilium,并充分发挥其性能优势,需要对安装方法、系统需求、配置最佳实践、性能调优手段以及潜在的运维挑战有深入的理解。
8.1. 安装方法:Cilium CLI、Helm
Cilium 提供了多种安装方式,以适应不同的用户偏好和部署场景:
Cilium CLI (
cilium install
):这是官方推荐给初次接触 Cilium 或希望快速部署的用户的方式。cilium install
命令能够自动检测 Kubernetes 集群的配置(如 GKE, EKS, AKS 等),并选择最合适的默认参数进行安装。它通常会安装最新稳定版的 Cilium。如果需要自定义配置,Cilium CLI 也支持通过--set
(类似于 Helm 的--set
)或--helm-values
(指定一个 Helm values YAML 文件)参数来传递自定义的 Helm Chart 值。Helm Charts:对于需要高度自定义安装参数或希望将 Cilium 集成到 GitOps 工作流的生产环境部署,使用官方的 Cilium Helm Chart 是更灵活的选择。通过 Helm,用户可以精确控制 Cilium 的各种配置选项,包括网络模式、IPAM 模式、
kube-proxy
替换、Hubble 和服务网格功能的启用等。使用 Helm 时,用户需要根据自己的环境和需求,手动选择最佳的数据路径和 IPAM 模式,而不像 Cilium CLI 那样会自动检测。
官方文档为各种主流的 Kubernetes 发行版和云提供商的托管 Kubernetes 服务都提供了详细的安装指南,无论是使用 Cilium CLI 还是 Helm。
8.2. 系统需求与内核依赖
Cilium 的运行对其宿主机环境,特别是 Linux 内核版本和配置,有明确的要求。
- 支持的体系架构:Cilium 主要支持 AMD64 和 AArch64 (ARM64) 体系架构。
- Linux 内核版本:
- 基本要求:通常要求 Linux 内核版本 >= 5.4。对于某些特定的企业发行版,如 RHEL 8.6,其 4.18 内核也可能包含足够的 eBPF backport 支持。
- 高级特性依赖:许多 Cilium 的高级特性和性能优化依赖于更新的内核版本中引入的 eBPF 功能。例如:
- BPF 主机路由 (eBPF Host-Routing):>= 5.10
- WireGuard 透明加密:>= 5.6
- IPv6 BIG TCP 支持:>= 5.19
- IPv4 BIG TCP 支持:>= 6.3
netkit
设备模式:>= 6.8
- 内核版本是部署 Cilium 并期望获得其全部功能和最佳性能的关键成功因素。在较旧的内核上运行 Cilium 可能会导致某些高级功能不可用或性能不佳。因此,在选择操作系统或规划内核升级策略时,务必参考 Cilium 官方文档中关于内核版本要求的最新说明。
- clang+LLVM 版本:如果需要在宿主机上本地编译 eBPF 程序(这对于标准的容器化 Cilium Agent 部署来说并不常见,因为 Agent 通常自带预编译的 eBPF 程序),则需要 clang+LLVM 版本 >= 18.1。
- 必需的内核配置:除了版本号,内核还需要启用一系列与 eBPF 和网络相关的配置选项,如
CONFIG_BPF=y
,CONFIG_BPF_SYSCALL=y
,CONFIG_NET_CLS_BPF=y
,CONFIG_BPF_JIT=y
等。 - eBPF 文件系统:eBPF 文件系统(通常挂载在
/sys/fs/bpf
)必须被挂载,以便 Cilium Agent 能够持久化 eBPF 映射和程序。 - 权限要求:Cilium Agent 需要
CAP_SYS_ADMIN
权限以及访问宿主机网络命名空间的能力,才能在内核中加载 eBPF 程序和管理网络设备。在 Kubernetes 中,这通常通过配置 Pod 的securityContext
和hostNetwork: true
来实现。
8.3. Kubernetes 部署最佳实践
根据官方文档和社区经验,以下是一些在 Kubernetes 中部署 Cilium 的最佳实践:
- 工具选择:对于初次部署或简单场景,可以使用
cilium-cli
进行快速安装。对于生产环境或需要深度定制的场景,推荐使用 Helm Chart 进行部署,并结合版本控制系统(如 Git)管理 Helm values 文件,以实现 GitOps。 - 网络模式选择:仔细评估并选择最适合自身环境的网络模式(覆盖网络、原生路由或云提供商特定模式)。考虑因素包括底层网络能力、性能需求、IP 地址规划和运维复杂度。
kube-proxy
替换:为了获得最佳性能、更低的延迟和更高级的网络功能(如 XDP 加速、高效的服务负载均衡),强烈建议启用 Cilium 的kube-proxy
替换功能。这通常通过设置 Helm 参数kubeProxyReplacement=true
(或类似选项)来实现。- 默认拒绝策略:在网络安全方面,遵循“默认拒绝”原则。即,首先部署一个默认拒绝所有流量的策略,然后根据应用需求,逐步、显式地允许必要的通信路径。这有助于实现最小权限原则。
- 启用 Hubble 可观测性:从部署之初就启用 Hubble,以便能够监控网络流量、排查连接问题和验证策略有效性。
- CNI 链式部署 (Chaining Mode):如果需要在已存在其他 CNI 插件的环境中运行 Cilium(例如,某些托管 Kubernetes 服务可能默认安装了自己的 CNI),或者希望将 Cilium 与 Istio 等服务网格集成,可能需要配置 Cilium 的 CNI 链式部署模式(例如,
cni.chainingMode=generic-veth
)。确保仔细阅读相关文档,以避免 CNI 配置冲突。 - SELinux 注意事项:如果在宿主机上启用了 SELinux(例如在 Red Hat OpenShift 环境中),需要确保 Cilium Agent 和任何相关的 Envoy 代理(如果 L7 代理以独立 DaemonSet 运行)具有兼容的 SELinux 上下文类型,以允许它们通过 UNIX 域套接字进行通信。
8.4. 性能调优与 eBPF 优化
Cilium 提供了丰富的配置选项和机制,用于优化其数据平面的性能。官方文档中通常包含专门的性能调优指南。
关键的性能调优建议包括:
- 启用推荐的性能配置组合:官方通常会推荐一组经过验证的配置组合,以达到最佳性能,例如启用
netkit
设备模式、eBPF 主机路由、BIG TCP、优化的 eBPF 映射后端内存管理(如每 CPU 分布式 LRU)和 eBPF 时钟探测等。 netkit
设备模式:对于支持的内核版本(>= 6.8),启用netkit
可以显著减少网络命名空间切换的开销,提升 Pod 间通信的吞吐量和降低延迟。- eBPF 主机路由 (eBPF Host-Routing):对于内核版本 >= 5.10,启用此功能可以完全绕过宿主机网络栈中的 iptables 和上层协议栈,实现更快的数据包转发路径。
- BIG TCP (IPv4/IPv6):在支持的内核版本(IPv6 >= 5.19, IPv4 >= 6.3)和兼容的网卡上启用 BIG TCP,允许网络栈处理更大的 GSO (Generic Segmentation Offload) 和 GRO (Generic Receive Offload) 数据包,从而减少协议栈遍历次数,降低 CPU 负载,提升高带宽(如 100Gbit/s)网络下的性能。通常要求禁用隧道和加密。
- eBPF 映射优化:
- 每 CPU 分布式 LRU (
bpf.distributedLRU.enabled=true
):为核心的 eBPF 映射(如连接跟踪表)启用每 CPU 的 LRU 缓存,以避免在多核高并发场景下因访问全局 LRU 锁而产生的竞争和性能瓶颈。 - 动态调整映射大小比例 (
bpf.mapDynamicSizeRatio
):根据系统总内存动态调整关键 eBPF 映射的大小,以更好地适应不同规模的节点和负载。 - eBPF 时钟探测 (
bpfClockProbe=true
):允许 Cilium探测并使用更高效的时钟源(如jiffies
而非ktime
)来管理连接跟踪表中的条目超时,降低获取时间戳的开销。
- 每 CPU 分布式 LRU (
- 绕过 iptables 连接跟踪:如果环境中不再依赖宿主机的 iptables 连接跟踪(例如,已完全采用 Cilium 的 eBPF 连接跟踪),可以配置 Cilium 绕过它,以减少不必要的处理开销。
- XDP 加速:对于 NodePort 和 LoadBalancer 类型的服务,如果网卡驱动支持原生 XDP,可以启用 XDP 加速,在网络驱动层面直接处理和转发服务流量,显著降低延迟。
- 宿主机内核调优:
- 内核抢占模式 (
CONFIG_PREEMPT_NONE=y
):对于服务器工作负载,推荐使用非抢占式内核,这通常能带来更好的网络性能。 - CPU 调速器 (CPU Governor):将 CPU 调速器设置为
performance
模式,以防止 CPU 频率动态调整影响网络延迟和吞吐量。 - 网卡中断绑定:停止
irqbalance
服务,并将特定网卡的中断请求(IRQ)绑定到固定的 CPU核心上,以提高中断处理效率和减少性能抖动。
- 内核抢占模式 (
- MTU 配置:确保在支持巨型帧(Jumbo Frames)的网络环境中,宿主机和网络设备都已正确配置,Cilium 会自动检测并利用更大的 MTU。
实现 Cilium 的最佳性能是一个多方面的工作,它涉及到对 Cilium 自身配置、Linux 内核参数乃至底层硬件的综合调优。在要求严苛的生产环境中,建议在代表性的测试环境中进行基准测试,以验证调优效果并找到最适合自身工作负载的配置。
8.5. 可扩展性考量与限制
Cilium 被设计用于大规模 Kubernetes 集群,并已在拥有数万节点和数十万 Pod 的环境中得到验证。然而,在极端规模下,仍然存在一些可扩展性方面的考量和潜在限制:
- eBPF 映射大小限制:所有的 eBPF 映射都有预设的容量上限(尽管很多可以配置)。例如,每个端点的策略映射默认有 16k 条目的限制,服务负载均衡映射默认有 64k 条目的限制。如果这些映射达到容量上限,可能会导致新的策略无法实施、新的服务无法创建或连接跟踪失败。合理规划和调整这些映射的大小对于大规模部署至关重要。
- 安全身份数量:Cilium 的基于身份的安全模型依赖于为工作负载分配安全身份。历史上,数据包头中用于携带身份信息的字段大小可能会对集群中可唯一标识的身份数量造成理论上的限制(例如,早期提到过 65k 的限制)。虽然 Cilium 通过各种机制(如身份缓存、优化的身份分配算法)来管理身份,但在拥有海量、高度异构工作负载的超大规模集群中,身份空间的管理和分配效率仍是一个需要关注的方面。
- 控制平面可扩展性:
- Kubernetes API 服务器负载:Cilium Agent 和 Operator 需要与 Kubernetes API 服务器进行频繁交互,以监视资源变化(如 Pod、Service、NetworkPolicy、Cilium CRD 等)并更新状态。在节点数量和资源变更频率非常高的大规模集群中,这可能会对 API 服务器造成显著压力。使用专用的 etcd 存储 Cilium 的状态数据(而非完全依赖 CRD)是缓解此问题的一种方式。
- IP 到身份的映射分发:在需要全局一致的 IP 地址到安全身份映射的场景下(例如,用于策略执行),如何高效地将这些映射信息分发并同步到所有节点,是一个可扩展性挑战。
- ClusterMesh 集群数量:Cilium ClusterMesh 目前支持最多连接 255 个集群。
- 标签可变性带来的挑战:Kubernetes 中 Pod 或 Namespace 的标签是可变的。如果安全身份与 IP 地址分配紧密耦合,并且依赖于这些标签,那么标签的变更可能会导致需要重新分配 IP 地址或更新身份映射,这在某些大规模 IPAM 模型下可能引发复杂性和性能问题。
Cilium 社区和开发者一直在积极应对这些可扩展性挑战,通过优化算法、改进数据结构、引入新的工作模式等方式,持续提升 Cilium 在超大规模环境下的表现。用户在计划将 Cilium部署到非常大规模的集群时,应密切关注最新的版本特性和社区的最佳实践,并在必要时寻求专业支持。
8.6. 常见运维挑战与故障排除
在运维 Cilium 过程中,可能会遇到各种挑战。理解常见的故障模式和掌握有效的故障排除技术至关重要。
常见运维挑战包括:
- 连接性问题:Pod 间、Pod 与 Service 间或 Pod 与外部网络间的通信失败。
- 网络策略未按预期工作:流量被意外阻止或允许,不符合已定义的网络策略规则。
- 组件健康问题:Cilium Agent 或 Cilium Operator Pod 崩溃、重启或处于非健康状态。
- eBPF 映射问题:映射已满、包含过时或错误的条目,导致功能异常。
- DNS 解析失败:Pod 无法解析内部或外部域名。
- 性能瓶颈:网络延迟过高、吞吐量不达标,可能与 eBPF 程序效率、连接跟踪或资源限制有关。
- 升级过程中的问题:版本不兼容、CRD 更新失败、配置迁移错误等。
故障排除技术:
检查组件状态:
- 使用
kubectl get pods -n kube-system -l k8s-app=cilium
查看 Cilium Agent Pod 的状态。 - 使用
kubectl get pods -n kube-system -l name=cilium-operator
查看 Cilium Operator Pod 的状态。 - 在每个节点上执行
cilium status --verbose
(通过kubectl exec
进入 Agent Pod)获取详细的健康状况报告,包括与 KVStore(如 etcd 或 CRD)、Kubernetes API 服务器的连接状态,以及控制器和代理(Envoy)的状态。
- 使用
分析日志:
- 查看 Cilium Agent 的日志:
kubectl logs -n kube-system -l k8s-app=cilium -c cilium-agent
。 - 查看 Cilium Operator 的日志:
kubectl logs -n kube-system -l name=cilium-operator
。 - 关注日志中的
level=warning
或level=error
级别的消息,以及与特定问题相关的关键字(如 "Failed to", "Endpoint starting regeneration", "Policy denied")。 - 根据需要调整日志级别以获取更详细的调试信息,例如
cilium config set debug true
。
- 查看 Cilium Agent 的日志:
使用 Hubble 进行流量观察:
- 通过 Hubble CLI (
hubble observe
) 或 Hubble UI 实时观察网络流、服务依赖关系和策略裁决结果。 - 过滤特定 Pod、命名空间、协议或策略裁决(如
DROPPED
)的流量,以定位问题。
- 通过 Hubble CLI (
使用
cilium monitor
:- 在 Agent Pod 内执行
cilium monitor
命令可以捕获更底层的网络事件,包括数据包丢弃事件及其原因代码(如DROP_POLICY
,DROP_CT_INVALID
)。 - 使用
--type drop
选项专门查看丢弃的数据包。
- 在 Agent Pod 内执行
检查 eBPF 映射:
- 使用
cilium bpf ct list global
查看连接跟踪表条目。 - 使用
cilium bpf nat list
查看 NAT 表条目。 - 使用
cilium bpf policy get <endpoint_id>
查看特定端点的策略映射。 - 检查映射是否已满、是否存在过时条目或非预期条目。
- 使用
DNS 问题排查:
- 验证 CoreDNS/kube-dns 是否正常工作。
- 检查 Cilium 的 DNS 代理配置(如果启用)。
- 如果使用了基于 FQDN 的网络策略,检查相关的 DNS 策略和
cilium fqdn cache list
的输出。 - 使用
cilium monitor --type l7 | grep DNS
监控 DNS 流量。
资源利用情况:
- 检查 Cilium Agent 和 Operator Pod 的 CPU 和内存使用情况,是否存在 OOMKilled 事件或 CPU 节流。
Cilium Bugtool:
- 在遇到难以解决的问题时,使用
cilium bugtool
命令收集集群的诊断信息(包括日志、配置、eBPF 状态等),以便向社区或支持团队报告问题。
- 在遇到难以解决的问题时,使用
通过系统地运用这些工具和技术,结合对 Cilium 架构和工作原理的理解,运维人员可以有效地诊断和解决 Cilium 在运行过程中出现的各种问题。
8.7. 升级策略与最佳实践
升级 Cilium 是一个需要谨慎规划和执行的过程,以确保集群的稳定性和业务的连续性。官方文档和社区通常会提供详细的升级指南和版本特定的注意事项。
升级最佳实践:
- 阅读官方升级指南:在开始任何升级操作之前,务必仔细阅读目标版本的官方升级指南和发行说明,了解所有前提条件、必需步骤、潜在的重大变更和已知问题。
- 逐个次版本升级:官方通常只测试和支持从一个次要版本(Minor Release, e.g., 1.x 到 1.y)到下一个连续的次要版本的升级路径。避免跨多个次要版本进行跳跃式升级。
- 升级到最新的补丁版本:在进行次要版本升级之前,建议先将当前运行的 Cilium 升级到该次要版本的最新补丁版本(Patch Release)。
- 执行预检 (Pre-flight Check):在正式升级之前,务必运行 Cilium 提供的预检脚本或命令。预检通常会检查集群环境是否满足新版本的依赖要求(如内核版本、CRD 版本等),并预先拉取新版本的 Cilium 镜像到所有节点,以减少 Agent 重启时的停机时间和避免因镜像拉取失败导致的升级中断。
- 使用 Helm 进行升级:推荐使用 Helm 来管理 Cilium 的升级过程。可以通过
helm upgrade
命令进行升级,并确保在升级时传递与初始部署时等效的配置参数(通过--set
标志或 Helm values 文件)。 - 谨慎使用
--reuse-values
:在进行次要版本间的 Helm 升级时,不建议使用--reuse-values
标志,因为它可能导致 Helm 模板渲染不正确。更好的做法是保存旧的 values 文件,对照新版本的 Chart 检查是否有重命名或废弃的参数,然后使用更新后的 values 文件进行升级。 - 关注
upgradeCompatibility
选项:某些 Cilium 版本可能提供upgradeCompatibility
这样的 Helm 选项,用于在升级过程中保持与旧版本数据平面的兼容性,以最大限度地减少流量中断。 - 监控升级过程:在升级过程中,密切监控 Cilium Agent 和 Operator Pod 的状态,以及集群的整体网络连通性和应用健康状况。
- CRD 更新:Helm 升级通常会自动处理 Cilium CRD 的更新。但对于某些重大版本升级,可能需要手动执行 CRD 更新步骤,务必遵循官方指南。
- 版本特定的注意事项:每个 Cilium 版本都可能有其特定的升级说明、已移除或废弃的配置选项、新增或变更的指标等。例如,Cilium 1.17 版本的升级说明中就列出了大量此类变更。务必仔细阅读这些说明。
- 流量中断预期:需要注意的是,当 Cilium Agent Pod 重启时(这是滚动升级的一部分),通过用户空间代理(如 Envoy,用于 L7 策略或服务网格)处理的流量将会中断,客户端需要重新连接。对于不涉及 L7 代理的纯 L3/L4 流量,影响通常较小或没有影响。
- 备份与回滚计划:在升级之前,制定详细的回滚计划。了解如何使用
kubectl rollout undo
或helm rollback
将 Cilium 回滚到之前的版本,以应对升级失败或出现严重问题的情况。 - 利用专业工具:对于复杂的环境或希望简化升级流程的团队,可以考虑使用像 Chkk 这样的第三方工具。这类工具通常提供自动化的预检、策划的发行说明、升级模板(支持原地升级和蓝绿部署策略)以及回滚指导,旨在降低升级风险并节省时间。
遵循这些最佳实践,并结合对目标版本具体变化的充分了解,可以帮助用户更安全、更平稳地完成 Cilium 的升级。
9. 应用案例与生态采纳
Cilium 凭借其先进的 eBPF 技术和丰富的功能集,在云原生领域获得了广泛的应用和业界的积极采纳。它不仅被用于构建高性能的 Kubernetes 网络平台,还在零信任安全、多集群管理、服务网格等多个关键场景中展现出其价值。
9.1. Kubernetes 中的关键应用场景
Cilium 在 Kubernetes 环境中的应用场景非常广泛,以下是一些典型的例子:
- 高性能 Kubernetes 网络:作为 CNI 插件,Cilium 利用 eBPF 提供比传统 iptables 或 IPVS 更高效的 Pod 网络和负载均衡,尤其适用于对网络吞吐量和延迟有较高要求的应用。
- 零信任安全与微隔离:通过基于身份的网络策略(
CiliumNetworkPolicy
)和 L3-L7 的精细化访问控制,Cilium 能够帮助用户构建零信任安全模型,实现严格的微隔离。 - API 感知安全:对 HTTP、gRPC、Kafka 等应用协议的深度感知能力,使得 Cilium 可以基于 API 调用、消息主题等应用层语义来实施安全策略。
kube-proxy
替代:Cilium 的 eBPF 数据平面可以完全替代 Kubernetes 的kube-proxy
组件,从而消除kube-proxy
在大规模集群中可能带来的性能瓶颈和复杂性。- 网络可观测性:集成的 Hubble 平台提供了对网络流量、服务依赖和策略执行的深度可见性,极大地简化了故障排除和性能监控。
- 多集群网络 (ClusterMesh):通过 ClusterMesh 功能,Cilium 可以连接多个 Kubernetes 集群,实现跨集群的服务发现、负载均衡和统一策略管理,支持地理分布式应用和混合云部署。
- 服务网格:Cilium 正在构建其服务网格能力,旨在提供一种更轻量、更高效的无 Sidecar 服务网格方案。
- 透明加密:支持 IPsec 和 WireGuard 对节点间流量进行透明加密,增强数据传输安全。
- 运行时安全增强 (Tetragon):通过子项目 Tetragon,将 eBPF 的能力扩展到主机运行时安全监控和增强领域。
- 减少工具蔓延:由于 Cilium 提供了网络、安全、可观测性乃至部分服务网格功能,它可以帮助企业整合技术栈,减少需要独立部署和维护的工具数量,从而降低运维复杂性。
- 避免云厂商锁定:作为一个开源的、跨平台的 CNI 解决方案,Cilium 有助于用户在不同的云提供商和本地环境中构建一致的网络和安全模型,从而避免被特定云厂商的技术栈深度绑定。
Cilium 的这些应用场景表明,它不仅仅是一个简单的网络插件,更是一个功能全面的平台级组件,旨在解决云原生应用在网络连接、安全防护和运行可见性等方面的核心挑战。通过将这些能力深度集成并基于 eBPF 进行高效实现,Cilium 为构建现代化、可扩展和安全的云原生基础设施提供了坚实的基础。
9.2. 企业采纳:案例研究 (DB Schenker)
全球物流巨头 DB Schenker 的案例是 Cilium 在大型企业中成功应用的一个典型代表。在采用 Cilium 之前,DB Schenker 面临着现有 IT 基础设施在网络可观测性、性能和安全性方面的挑战。他们原有的 CNI(Calico)在性能提升和高级可观测性方面能力有限,并且他们希望简化运维复杂度,特别是围绕服务网格的运维。
DB Schenker 选择 Cilium 的主要原因包括:
- eBPF 带来的性能优势:他们认识到 eBPF 能够简化连接跟踪并提供更快的 TCP 连接,从而显著提升网络性能并降低延迟。
- 全面的功能集:Cilium 提供的 Hubble 可观测性、WireGuard 加密以及模块化的架构设计,都非常符合他们的需求。
- 清晰的文档和迁移路径:Cilium 良好的文档和对增量迁移(如通过 CNI 链式模式)的支持,使得迁移过程更为平顺。
DB Schenker 的迁移过程是分阶段进行的。他们首先利用 Cilium 的链式模式,在保留现有 VPC CNI 的同时逐步引入 Cilium。随后,一个重要的里程碑是移除了 kube-proxy
,这消除了一个主要的延迟和开销来源。他们还用 Cilium 提供的 WireGuard 加密替代了原有的服务网格方案,从而简化了架构并增强了安全性。
采用 Cilium 后,DB Schenker 获得了显著的收益:
- 性能提升:服务连接得到优化,网络稳定性增强,延迟降低。通过移除
kube-proxy
和利用 eBPF,TCP 连接速度加快,资源利用效率也得到提高,进而降低了成本。Pod 调度更快,节点网络就绪效率更高。 - 安全性增强:通过 Cilium 精细化的网络策略实现了命名空间隔离,并利用 WireGuard 进行了集成加密,强化了其零信任安全模型。
- 可观测性改善:Hubble 提供了实时的 L7 网络流量可见性,使得故障排除更为快速高效。
- 运维简化:用 Cilium 替代服务网格消除了不必要的复杂性,显著简化了运维。故障事件发生率大幅下降,使得团队能够更专注于战略性任务。
展望未来,DB Schenker 计划进一步利用 Cilium 的 L7 可见性能力,并评估 Gateway API 等新特性,以持续优化其 IT 平台。
除了 DB Schenker,许多其他大型企业和科技公司,如 Google、Capital One、Adobe、Datadog、Cloudflare 等,也都在其生产环境中使用 Cilium,这充分证明了 Cilium 在大规模、复杂场景下的成熟度和可靠性。
10. 对比分析
在选择云原生网络解决方案时,了解不同选项之间的差异至关重要。本节将 Cilium 与其他主流的 CNI 插件和服务网格进行对比。
10.1. Cilium 与 Calico
Cilium 和 Calico 是 Kubernetes 生态系统中最受欢迎的两个高级 CNI 解决方案,它们都利用 eBPF 技术,但在核心设计、功能侧重和生态位上有所不同。
以下是 Cilium 与 Calico 的主要对比点:
特性/方面 | Cilium | Calico |
核心技术 | 完全基于 eBPF 的数据平面。 | 支持多种数据平面:eBPF、Linux IP Tables、Windows HNS、VPP。 |
网络安全 | 基于身份的安全模型,API 感知的 L7 策略,CiliumNetworkPolicy 提供高级功能。L7 可见性是关键优势。 |
同时支持 L3/L4 和应用层策略,实现 Kubernetes 标准策略,并扩展了全局网络策略、主机端点保护等。企业版提供 DNS 策略、应用层策略等。 |
负载均衡 | 高效的 eBPF 负载均衡,可完全替代 kube-proxy 。 |
其 eBPF 数据平面也提供高效的负载均衡,支持东西向和南北向流量。 |
可观测性 | 内置 Hubble 平台,提供流日志、服务地图、策略裁决等。Hubble 的数据导出能力曾被指出可能存在局限性。 | 与 Prometheus/Grafana 集成,可与 Istio/Jaeger 集成实现 L7 可观测性。商业版提供图形化界面。 |
可扩展性 | 可扩展,但可能受 eBPF 映射大小和身份数量的限制(例如,策略映射 16k 实体/端点,ClusterMesh 最多 255 集群)。 | 高度可扩展,其基于 BGP 的路由模型适合大型 L3 网络。已被大规模部署验证。 |
性能 | eBPF 带来高性能。具体性能需视场景而定。 | eBPF 数据平面性能优异,尤其在 UDP 场景。多数据平面选项提供了灵活性。 |
加密 | 支持 WireGuard 和 IPsec 进行透明加密。 | 支持 WireGuard 加密,以及通过与 Istio 集成实现 mTLS。 |
策略管理 | 通过 kubectl 、REST API 和 cilium CLI 进行。缺乏高级生命周期管理和策略推荐功能。 |
提供 Calico API、calicoctl CLI。企业版和云版本提供图形化策略管理、指标和推荐等高级功能。 |
DNS 策略 | 使用 DNS 代理拦截和过滤 DNS 请求,实现基于 DNS 名称的策略。可能引入单点故障或性能瓶颈。 | 直接嗅探 DNS 请求,避免了 DNS 代理的潜在问题,更为分散。 |
平台支持 | 主要聚焦于 Kubernetes 和容器编排平台。 | 支持更广泛的平台,包括 Kubernetes、OpenShift、Docker EE 等。 |
适用场景 | 强调深度 eBPF 集成、高级身份/API 感知安全、内置可观测性 (Hubble)、高性能服务网格的场景。 | 需要数据平面灵活性、高级 IPAM、简单 BGP 路由模型、更广泛平台支持的场景。 |
Cilium 和 Calico 的核心差异往往可以归结为 Cilium 对 eBPF 的深度专一投入与 Calico 支持多种数据平面的灵活性之间的权衡。Cilium 的设计使其能够在兼容的 Linux 内核上最大程度地发挥 eBPF 在性能、安全和可观测性方面的潜力,其创新与 eBPF 技术和内核的发展紧密相连。而 Calico 的多数据平面策略则为用户提供了更广泛的兼容性和部署选项,能够适应包括 Windows 节点或对 iptables/VPP 有特定偏好的环境,或者那些 eBPF 尚不成熟或不可用的场景。对于追求极致 eBPF 原生能力、运行在现代 Linux 内核上的纯 Kubernetes 环境,Cilium 具有强大的吸引力。而对于需要更广泛平台兼容性或不希望完全依赖 eBPF 的异构环境,Calico 提供了更多选择。
10.2. Cilium 与其他 CNI (例如 Flannel, Weave)
与 Flannel、Weave Net 等相对简单的 CNI 插件相比,Cilium 在功能丰富度和技术先进性上有着显著的优势,这主要归功于其 eBPF 基础。
- Flannel:是一个简单、轻量级的 L3 Overlay 网络方案,易于安装和管理,支持多种后端(如 VXLAN)。然而,Flannel 的功能相对基础,主要解决 Pod 间网络连通性问题,缺乏高级的网络策略执行能力和深入的可观测性。
- Weave Net:提供了 L2 Overlay Mesh 网络,也相对容易安装和配置。它支持一些基本的网络策略,但与 Cilium 基于身份的 L3-L7 精细化策略相比,功能较为有限。
总的来说,Cilium 凭借 eBPF 提供了远超 Flannel 和 Weave Net 的高级网络功能(如 kube-proxy
替代、高级负载均衡)、安全特性(L3-L7 策略、API 感知安全、透明加密)和可观测性能力(Hubble)。对于需要这些高级功能的企业级 Kubernetes 部署,Cilium 是一个更强大的选择。而 Flannel 和 Weave Net 则更适合对功能要求不高、追求简单易用的小型或开发测试集群。
10.3. Cilium 服务网格 vs. Istio/Linkerd
Cilium 正在将其能力扩展到服务网格领域,其核心理念是提供一种基于 eBPF 和可选 Envoy 的、更轻量级的“无 Sidecar”或“Sidecar-less”方案。这与传统的服务网格如 Istio 和 Linkerd 在架构和实现上有所不同。
以下是 Cilium 服务网格与 Istio、Linkerd 的主要架构和特性差异:
特性/方面 | Cilium 服务网格 | Istio | Linkerd |
架构 | 无 Sidecar/节点代理:eBPF 处理 L4,可选每个节点一个 Envoy 代理(或嵌入式)处理 L7。旨在减少资源开销和延迟。 | 传统模式:每个 Pod 一个 Envoy Sidecar 代理。Ambient Mesh 模式(较新):节点级 ztunnel (L4) + 按需的 Waypoint 代理 (L7,每个服务账户)。 | 轻量级 Sidecar:每个 Pod 一个用 Rust 编写的轻量级 Linkerd-proxy Sidecar。 |
安全 (mTLS) | Beta 阶段,与 SPIFFE 集成,通过 CiliumNetworkPolicy 执行。其 mTLS 实现仍在演进中。 |
成熟的 mTLS 功能,支持多种身份验证和授权策略。 | 以安全为核心设计,提供简单易用的 mTLS,通常默认开启或易于配置。 |
性能 | eBPF 和无 Sidecar 架构旨在实现低延迟和低资源消耗。但有第三方基准测试指出 Linkerd 更快。 | Sidecar 模式有一定开销。Ambient Mesh 模式旨在提升性能和降低资源占用。 | Linkerd-proxy 以其轻量和高效著称,性能表现优异。2024 年第三方基准测试显示其优于 Cilium Mesh。 |
复杂度 | 在 CNI 功能之上叠加服务网格能力。复杂度取决于启用的特性。无 Sidecar 模型旨在简化运维。 | 功能非常丰富,但也因此带来了较高的学习曲线和运维复杂度。Ambient Mesh 旨在简化部分运维。 | 强调极简主义和运维简单性,学习曲线相对平缓。 |
L7 特性处理 | 主要依赖 Envoy(通过 CRD 配置)进行 L7 处理。eBPF 可直接处理部分 L4 服务网格功能。 | 完全依赖 Envoy 进行 L7 处理。 | Linkerd-proxy 负责 L7 处理。 |
CNI 集成 | Cil |