Cilium 系列-7-Cilium 的 NodePort 實現從 SNAT 改為 DSR

2023-07-29 15:01:00

系列文章

前言

將 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 的 NodePort 實現從 SNAT 改為 DSR 以提升網路效能。

測試環境

  • Cilium 1.13.4
  • K3s v1.26.6+k3s1
  • OS
    • 3 臺 Ubuntu 23.04 VM, Kernel 6.2, x86

Direct Server Return (DSR)

預設情況下,Cilium 的 eBPF NodePort 實現以 SNAT 模式執行。也就是說,當節點外部流量到達時,如果節點確定負載平衡器、NodePort 或具有外部 IP 的服務的後端位於遠端節點,那麼節點就會通過執行 SNAT 將請求重定向到代表自己的遠端後端。這不需要額外更改 MTU。代價是,來自後端的回覆需要額外跳回節點,在那裡執行反向 SNAT 轉換,然後再將封包直接返回給外部使用者端。

範例如下,Cilium 的 eBPF NodePort 實現以 SNAT 模式執行:

$ kubectl -n kube-system exec ds/cilium -- cilium status --verbose
...
KubeProxyReplacement Details:
  Status:                 Strict
  Socket LB:              Enabled
  Socket LB Tracing:      Enabled
  Socket LB Coverage:     Full
  Devices:                eth0 192.168.2.3 (Direct Routing)
  Mode:                   SNAT

SNAT 模式下,NodePort 後端 pod 在其他節點入向流量:

出向流量:

該設定可通過 loadBalancer.mode Helm 選項更改為 dsr,以便讓 Cilium 的 eBPF NodePort 實現在 DSR 模式下執行。在這種模式下,後端直接回復外部使用者端,而不需要額外的跳轉,也就是說,後端通過使用服務 IP/port 作為源來回復。DSR 目前要求 Cilium 以本地路由模式部署,也就是說,它不能在任何一種隧道模式下工作。

DSR 模式流量如下:

DSR 模式的另一個優點是保留了使用者端的源 IP,因此可以在後端節點對其進行策略匹配。而在 SNAT 模式下則無法做到這一點。鑑於一個特定的後端可被多個服務使用,後端需要知道它們需要回復的服務 IP/埠。

請注意,由於 Cilium 特定的 IP 選項可能會被底層網路結構丟棄,因此 DSR 模式在某些公共雲提供商環境中可能無法使用。如果後端位於與處理給定 NodePort 請求的節點相距較遠的節點上,在出現服務連線問題時,首先要檢查 NodePort 請求是否實際到達了包含後端的節點。如果不是,則建議切換回預設 SNAT 模式作為一種解決方法。

此外,在某些實施源/目標 IP 地址檢查的公共雲提供商環境中(如 AWS),必須禁用檢查才能使用 DSR 模式。

啟用 DSR 實施步驟

在啟用僅 DSR 模式的無 kube proxy 環境中,上述 Helm 範例設定如下:

helm upgrade cilium cilium/cilium --version 1.13.4 \
    --namespace kube-system \
    --reuse-values \
    --set loadBalancer.mode=dsr