Cilium系列-6-從地址偽裝從IPtables切換為eBPF

2023-07-27 12:13:52

系列文章

前言

將 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-latencynetwork-throughput
    • CPU 調為效能模式
    • 停止 irqbalance,將網路卡中斷引腳指向特定 CPU

在網路/網路卡裝置/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 地址偽裝模式. 這是傳統的實現方式,可以在所有核心版本上執行。預設設定檢查如下:

$ kubectl -n kube-system exec ds/cilium -- cilium status | grep Masquerading
Masquerading:            IPTables [IPv4: Enabled, IPv6: Disabled]

而基於 eBPF 的實現是最有效的實現。它需要 Linux 核心 4.19,並可通過 bpf.masquerade=true helm 選項啟用。

當前的實現依賴於 BPF NodePort 功能。未來將移除該依賴關係(GitHub 問題 13732)。

具體命令為:

helm upgrade cilium cilium/cilium \
   --namespace kube-system \
   --reuse-values \
   --set bpf.masquerade=true

偽裝只能在執行 eBPF 偽裝程式的網路卡裝置上進行。這意味著,如果輸出網路卡裝置執行了該程式,從 pod 傳送到外部地址的封包將被偽裝(偽裝到輸出網路卡裝置的 IPv4 地址)。如果未指定,程式將自動連線到 BPF NodePort 網路卡裝置檢測機制選擇的網路卡裝置上。要手動更改,請使用devices helm 選項。使用 cilium status 來確定程式執行在哪些網路卡裝置上:

$ kubectl -n kube-system exec ds/cilium -- cilium status | grep Masquerading
Masquerading:            BPF   [eth0]   10.0.0.0/22 [IPv4: Enabled, IPv6: Disabled]

如上輸出, IPv6: Disabled, 這是因為基於 eBPF 的偽裝目前不支援 IPv6 流量。

從上面的輸出來看,程式正在 eth0 網路卡裝置上執行。

基於 eBPF 的偽裝可偽裝以下 IPv4 L4 協定的封包:

  • TCP
  • UDP
  • ICMP(僅 Echo request 和 Echo reply)

預設情況下,除了發往其他叢集節點的封包外,所有從 pod 發往 ipv4-native-routing-cidr 範圍之外 IP 地址的封包都會被偽裝。排除的 CIDR 顯示在上述 cilium status10.0.0.0/22)輸出中。

為實現更精細的控制,Cilium 在 eBPF 中實現了 ip-masq-agent,可通過 ipMasqAgent.enabled=true helm 選項啟用。

基於 eBPF 的 ip-masq-agent 支援在組態檔中設定 nonMasqueradeCIDRsmasqLinkLocal 選項。從 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