cilium 网络概念
Encapsulation(隧道封装)
当未提供配置时,Cilium会自动以这种模式运行,因为这种模式对底层网络基础设施的要求最少。
在这种模式下,所有集群节点使用基于UDP的封装协议VXLAN或Geneve形成隧道网格。所有Cilium节点之间的流量都被封装。
对网络的要求
封装依赖于正常的节点之间的连通性。这意味着如果Cilium节点已经可以相互通信,那么所有路由要求已经得到满足。
底层网络和防火墙必须允许封装的数据包
封装方式 |
Port Range / Protocol |
---|---|
VXLAN (Default) |
8472/UDP |
Geneve |
6081/UDP |
Encapsulation 模型的优点
简单性
连接集群节点的网络不需要了解PodCIDRs。集群节点可以生成多个路由或链路层域。只要集群节点可以使用IP/UDP相互访问,底层网络的拓扑结构就无关紧要。
地址空间
由于不依赖于任何底层网络限制,可用的地址空间可能更大,并且如果配置PodCIDR大小,则允许在每个节点上运行任意数量的Pod。
自动配置
与诸如Kubernetes之类的编排系统一起运行时,集群中所有节点的列表,包括它们各自的分配前缀节点,会自动提供给每个代理程序。加入集群的新节点将自动纳入网格。
身份上下文
封装协议允许在网络数据包中携带元数据。Cilium利用这种能力传输元数据,如源安全标识。身份传递是一个优化设计,旨在避免在远程节点上进行一次身份查找。
Encapsulation 模型的缺点
由于添加封装头部,有效负载可用的MTU比原生路由低(每个网络数据包的VXLAN为50字节)。这导致特定网络连接的最大吞吐量降低。通过启用巨型帧(每1500字节额外50字节开销 vs 每9000字节额外50字节开销),可以很大程度上减轻这一问题。
Native-Routing(原生路由 or 本地路由)
本地路由数据路径通过设置 routing-mode: native 启用,并启用本机数据包转发模式。本机数据包转发模式利用Cilium所在网络的路由能力,而不是执行封装。
在本地路由模式下,Cilium将把所有未寻址给另一个本地端点的数据包委托给Linux内核的路由子系统。这意味着该数据包将被路由,就像一个本地进程发出了数据包一样。因此,连接集群节点的网络必须能够路由 PodCIDRs。
当配置本机路由时,Cilium会自动在Linux内核中启用IP转发。
对网络的要求
为了运行本地路由模式,运行Cilium的宿主之间的网络必须能够使用分配给Pod或其他工作负载的地址转发IP流量。
节点上的Linux内核必须知道如何转发所有运行Cilium的节点的Pod或其他工作负载的数据包。这可以通过两种方式实现:
1. 节点本身不知道如何路由所有Pod的IP,但网络上存在一个路由器,该路由器知道如何到达所有其他Pod。在这种情况下,配置Linux节点包含一条默认路由,指向这样的路由器。此模型用于云提供商网络集成。
2. 每个单独的节点被告知所有其他节点的所有Pod IP,并将路由插入Linux内核路由表以表示这一点。如果所有节点共享单一的L2网络,那么通过启用选项auto-direct-node-routes: true可以解决这个问题。否则,必须运行额外的系统组件(例如BGP守护进程)来分发路由。
配置
routing-mode: native: 启用本地路由模式。
ipv4-native-routing-cidr: x.x.x.x/y: 设置可以执行本地路由的CIDR。
Masquerading(地址伪装)
将来自集群外部流量转发至集群上的Pod时依赖的功能,传统方式是使用iptables nat机制(称为iptables mode)。
eBPF提供了更加高效的masquerading机制(eBPF mode),但仅在4.19及以上版本的Linux内核上支持。
此行为可以通过选项 enable-ipv4-masquerade: false(对于IPv4流量)和 enable-ipv6-masquerade: false(对于IPv6流量)来禁用,从而离开主机的流量不再进行伪装。
基于 eBPF-based 实现
基于eBPF的实现是最高效的实现方式。它需要Linux内核版本4.19,并可以通过 bpf.masquerade=true Helm选项进行启用。
当前的实现依赖于BPF NodePort功能。这种依赖关系将在将来移除。
伪装只能在运行eBPF伪装程序的设备上进行。这意味着如果输出设备运行该程序,那么从Pod发送到外部地址的数据包将被伪装(转换为输出设备的IPv4地址)。如果未指定,程序将自动附加到由BPF NodePort设备检测机制选择的设备上。要手动更改此设置,请使用devices Helm选项。使用cilium status 命令确定程序正在哪些设备上运行。
基于eBPF的伪装可以伪装以下L4协议的报文:
传输控制协议
UDP协议
ICMP
默认情况下,所有从Pod发送到ipv4-native-routing-cidr范围之外的IP地址的数据包都会进行伪装,除了发送到其他集群节点的数据包(就像对于IPv6的情况,使用ipv6-native-routing-cidr)。
为了实现更加精细的控制,Cilium在eBPF中实现了ip-masq-agent,可以通过 ipMasqAgent.enabled=true Helm选项启用。
基于eBPF的ip-masq-agent支持在配置文件中设置nonMasqueradeCIDRs、masqLinkLocal和masqLinkLocalIPv6选项。从Pod发送到属于nonMasqueradeCIDRs中任何CIDR的目标的数据包不会被伪装。如果配置文件为空,代理将提供以下非伪装CIDRs:
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
100.64.0.0/10
192.0.0.0/24
192.0.2.0/24
192.88.99.0/24
198.18.0.0/15
198.51.100.0/24
203.0.113.0/24
240.0.0.0/4
此外,如果masqLinkLocal未设置或设置为false,则将169.254.0.0/16附加到非伪装CIDRs列表中。对于IPv6,如果masqLinkLocalIPv6未设置或设置为false,则会附加fe80::/10。
基于iptables
这是适用于所有内核版本的遗留实现。
这意味着,可以通过指定特定的网络接口(例如eth0),来限制仅在这些接口上进行源地址伪装(MASQUERADE)。这种做法通常在想要限定出站流量伪装发生在特定网络路径上时非常有用。例如,在有多个出口接口的复杂网络环境中,或者在仅希望对外部(Internet)出站流量进行伪装,而保持内部网络流量原始源地址不变的场景下。
对于路由层根据目标CIDR选择不同源地址的高级情况,可以使用选项 enable-masquerade-to-route-source: "true",以便对源地址进行伪装,而不是对主接口地址进行伪装。然后,后者仅被视为通用的备用选项,用于默认路由。对于这些高级情况,用户需要确保在相关的伪装接口上没有重叠的目标CIDR作为路由。
这意味着允许在路由级别上根据目标CIDR选择不同的源地址。通过设置 enable-masquerade-to-route-source: "true",数据包将根据目标CIDR对源地址进行伪装。这种灵活性可在需要更复杂路由选择行为的场景下使用,但要注意确保没有在相关伪装接口上设置重叠目标CIDR,以避免路由冲突。
IP 地址管理 (IPAM)
IP 地址管理 (IPAM) 负责 Cilium 管理的网络端点(容器等)使用的 IP 地址的分配和管理。支持多种IPAM模式,满足不同用户的需求。
不要更改现有集群的 IPAM 模式。在现有环境中更改 IPAM 模式可能会导致现有工作负载的连接持续中断。更改 IPAM 模式的最安全方式是使用新的 IPAM 配置安装新的 Kubernetes 集群。
Feature |
Kubernetes 主机范围 |
集群范围(默认) |
Multi-Pool |
CRD 支持 |
AWS ENI |
Azure IPAM |
GKE |
---|---|---|---|---|---|---|---|
Tunnel routing |
✅ |
✅ |
❌ |
❌ |
❌ |
❌ |
❌ |
Direct routing |
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
✅ |
CIDR Configuration |
Kubernetes |
Cilium |
Cilium |
External |
External (AWS) |
External (Azure) |
External (GCP) |
Multiple CIDRs per cluster |
❌ |
✅ |
✅ |
N/A |
N/A |
N/A |
N/A |
Multiple CIDRs per node |
❌ |
❌ |
✅ |
N/A |
N/A |
N/A |
N/A |
Dynamic CIDR/IP allocation |
❌ |
❌ |
✅ |
✅ |
✅ |
✅ |
❌ |
集群范围(默认)
集群范围的IPAM模式为每个节点分配节点范围的PodCIDR,并使用每个节点上的主机范围分配器分配IP地址。因此,它类似于Kubernetes的Host Scope模式。不同之处在于,Cilium操作员将通过v2.CiliumNode资源管理每个节点的PodCIDR,而不是Kubernetes通过Kubernetes v1.Node资源分配每个节点的PodCIDR。这种模式的优势在于它不依赖于Kubernetes配置为分配每个节点的PodCIDR。
架构
扩展 cluster pool
在clusterPoolIPv4PodCIDRList列表中不要更改任何现有元素,因为更改会导致意外行为。如果池耗尽了,应该向列表添加新元素。最小掩码长度为/30,建议最小掩码长度至少为/29。之所以添加新元素而不更改现有元素的原因是分配器为每个CIDR块保留了2个IP地址,用于网络地址和广播地址。不能更改clusterPoolIPv4MaskSize。
Kubernetes 主机范围
Kubernetes 主机范围 IPAM 模式通过 ipam: kubernetes 启用,并将地址分配委托给集群中的每个单独节点。 IP 是由 Kubernetes 在与每个节点关联的 PodCIDR 范围之外分配的。
架构
annotation 设置
Annotation |
Description |
---|---|
|
IPv4 PodCIDR range |
|
IPv6 PodCIDR range |
|
IPv4 address of the cilium host interface |
|
IPv6 address of the cilium host interface |
|
IPv4 address of the cilium-health endpoint |
|
IPv6 address of the cilium-health endpoint |
配置
通过 ConfigMap 选项来配置 Kubernetes 主机范围:
ipam: kubernetes:启用 Kubernetes IPAM 模式。如果enable-ipv4为true,启用此选项将自动启用k8s-require-ipv4-pod-cidr;如果enable-ipv6为true,则启用k8s-require-ipv6-pod-cidr。
k8s-require-ipv4-pod-cidr: true:指示 Cilium 代理等待,直到通过 Kubernetes 节点资源提供 IPv4 PodCIDR。
k8s-require-ipv6-pod-cidr: true:指示 Cilium 代理等待,直到通过 Kubernetes 节点资源提供 IPv6 PodCIDR。
通过 helm 选项来配置 Kubernetes 主机范围:
ipam: kubernetes: --set ipam.mode=kubernetes.
k8s-require-ipv4-pod-cidr: true: --set k8s.requireIPv4PodCIDR=true,仅适用于 --set ipam.mode=kubernetes
k8s-require-ipv6-pod-cidr: true: --set k8s.requireIPv6PodCIDR=true,仅适用于 --set ipam.mode=kubernetes
参考文档
https://docs.cilium.io/en/stable/network/concepts/