Cilium 系列 -6- 从地址伪装从 IPtables 切换为 eBPF
本文最后更新于:2024年7月24日 晚上
系列文章
前言
将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能. 但是通过对 Cilium 不同模式的切换 / 功能的启用, 可以进一步提升 Cilium 的网络性能. 具体调优项包括不限于:
- 启用本地路由(Native Routing)
- 完全替换 KubeProxy
- IP 地址伪装 (Masquerading) 切换为基于 eBPF 的模式
- Kubernetes NodePort 实现在 DSR(Direct Server Return) 模式下运行
- 绕过 iptables 连接跟踪(Bypass iptables Connection Tracking)
- 主机路由 (Host Routing) 切换为基于 BPF 的模式 (需要 Linux Kernel >= 5.10)
- 启用 IPv6 BIG TCP (需要 Linux Kernel >= 5.19)
禁用 Hubble(但是不建议, 可观察性比一点点的性能提升更重要)- 修改 MTU 为巨型帧(jumbo frames) (需要网络条件允许)
- 启用带宽管理器(Bandwidth Manager) (需要 Kernel >= 5.1)
- 启用 Pod 的 BBR 拥塞控制 (需要 Kernel >= 5.18)
- 启用 XDP 加速 (需要 支持本地 XDP 驱动程序)
- (高级用户可选)调整 eBPF Map Size
- Linux Kernel 优化和升级
CONFIG_PREEMPT_NONE=y
- 其他:
- tuned network-* profiles, 如:
tuned-adm profile network-latency
或network-throughput
- CPU 调为性能模式
- 停止
irqbalance
,将网卡中断引脚指向特定 CPU
- tuned network-* profiles, 如:
在网络 / 网卡设备 /OS 等条件满足的情况下, 我们尽可能多地启用这些调优选项, 相关优化项会在后续文章逐一更新. 敬请期待.
今天我们来启用 Cilium eBPF IP 地址伪装 (Masquerading) 模式以提升网络效率.
测试环境
- Cilium 1.13.4
- K3s v1.26.6+k3s1
- OS
- 3 台 Ubuntu 23.04 VM, Kernel 6.2, x86
IP 地址伪装(Masquerading)
Pod 使用的 IPv4 地址通常是从 RFC1918 专用地址块中分配的,因此不可公开路由。Cilium 会自动将离开群集的所有流量的源 IP 地址伪装成 node 的 IPv4 地址,因为 node 的 IP 地址已经可以在网络上路由。如下图:
对于 IPv6 地址,只有在使用 iptables 执行模式时才会进行伪装。
如果要禁用该选项:
- 对于离开主机的 IPv4 流量,可使用选项
enable-ipv4-masquerade:false
, - 对于 IPv6 流量,可使用选项
enable-ipv6-masquerade:false
。
配置
设置可路由 CIDR
默认行为是排除本地节点 IP 分配 CIDR 范围内的任何目的地。如果 pod IP 可通过更广泛的网络进行路由,则可使用选项:ipv4-native-routing-cidr: 10.0.0.0/8
(或 IPv6 地址的 ipv6-native-routing-cidr: fd00::/100
)指定该网络,在这种情况下,该 CIDR 范围内的所有目的地都 不会 被伪装。
设置伪装接口
请参阅下文配置伪装接口。
基于 eBPF 的 IP 地址伪装模式
如果没有明确指定, 默认使用基于 IPTables 的 IP 地址伪装模式. 这是传统的实现方式,可以在所有内核版本上运行。默认配置检查如下:
1 |
|
而基于 eBPF 的实现是 最有效 的实现。它需要 Linux 内核 4.19,并可通过 bpf.masquerade=true
helm 选项启用。
当前的实现依赖于 BPF NodePort 功能。未来将移除该依赖关系(GitHub 问题 13732)。
具体命令为:
1 |
|
伪装只能在运行 eBPF 伪装程序的网卡设备上进行。这意味着,如果输出网卡设备运行了该程序,从 pod 发送到外部地址的数据包将被伪装(伪装到输出网卡设备的 IPv4 地址)。如果未指定,程序将自动连接到 BPF NodePort 网卡设备检测机制 选择的网卡设备上。要手动更改,请使用devices
helm 选项。使用 cilium status
来确定程序运行在哪些网卡设备上:
1 |
|
如上输出, IPv6: Disabled
, 这是因为基于 eBPF 的伪装目前不支持 IPv6 流量。
从上面的输出来看,程序正在 eth0
网卡设备上运行。
基于 eBPF 的伪装可伪装以下 IPv4 L4 协议的数据包:
- TCP
- UDP
- ICMP(仅 Echo request 和 Echo reply)
默认情况下,除了发往其他集群节点的数据包外,所有从 pod 发往 ipv4-native-routing-cidr
范围之外 IP 地址的数据包都会被伪装。排除的 CIDR 显示在上述 cilium status
(10.0.0.0/22
)输出中。
为实现更精细的控制,Cilium 在 eBPF 中实现了 ip-masq-agent,可通过 ipMasqAgent.enabled=true
helm 选项启用。
基于 eBPF 的 ip-masq-agent 支持在配置文件中设置 nonMasqueradeCIDRs
和 masqLinkLocal
选项。从 pod 发送到属于 nonMasqueradeCIDRs
中任何 CIDR 的目的地的数据包都不会被伪装。如果配置文件为空,agent 将提供以下非伪装 CIDR:
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
📝Note
关于使用
ip-masq-agent
的配置, 本次暂不进行演示, 感兴趣的小伙伴可以自行尝试.
此外,如果 masqLinkLocal
未设置或设置为 false,则 169.254.0.0/16
会被附加到非屏蔽 CIDR 列表中。
Agent 使用 Fsnotify 跟踪配置文件的更新
下面的示例展示了如何通过 ConfigMap 配置 agent 并进行验证:
1 |
|
1 |
|
或者,在通过 Helm 安装 Cilium 时,可以通过 --set ipMasqAgent.config.nonMasqueradeCIDRs='{10.0.0.0/8,172.16.0.0/12,192.168.0.0/16}'
和 --set ipMasqAgent.config.masqLinkLocal=false
来配置上述 ip-masq-agent
。
总结
本文我们将地址伪装从 IPTables 切换为基于 eBPF 的模式. 相比 IPTables 模式, 基于 eBPF 的实现是 最有效 的实现。
至此, 性能调优已完成:
- ✔️ 启用本地路由(Native Routing)
- ✔️ 完全替换 KubeProxy
- ✔️ IP 地址伪装 (Masquerading) 切换为基于 eBPF 的模式
- Kubernetes NodePort 实现在 DSR(Direct Server Return) 模式下运行
- 绕过 iptables 连接跟踪(Bypass iptables Connection Tracking)
- 主机路由 (Host Routing) 切换为基于 BPF 的模式 (需要 Linux Kernel >= 5.10)
- 启用 IPv6 BIG TCP (需要 Linux Kernel >= 5.19)
- 修改 MTU 为巨型帧(jumbo frames) (需要网络条件允许)
- 启用带宽管理器(Bandwidth Manager) (需要 Kernel >= 5.1)
- 启用 Pod 的 BBR 拥塞控制 (需要 Kernel >= 5.18)
- 启用 XDP 加速 (需要 支持本地 XDP 驱动程序)