Kubernetes 1.29:服務的負載平衡器 IP 模式 (新功能,Alpha 版)

本部落格介紹 Kubernetes 1.29 中的一項新的 Alpha 功能。它提供一種可設定的方法,以定義 Service 實作 (在本部落格中以 kube-proxy 為例) 如何處理叢集中從 Pod 到 Service 的流量。

背景

在較舊的 Kubernetes 版本中,kube-proxy 會攔截目的地為與 type: LoadBalancer Service 相關聯的 IP 位址的流量。無論您為 kube-proxy 使用哪種模式,都會發生這種情況。攔截實作了預期的行為 (流量最終到達 Service 後面的預期端點)。實現此目的的機制取決於 kube-proxy 的模式;在 Linux 上,iptables 模式中的 kube-proxy 會將封包直接重新導向到端點;在 ipvs 模式中,kube-proxy 會將負載平衡器的 IP 位址設定為節點上的某個介面。實作該攔截的動機有兩個原因

  1. 流量路徑最佳化: 有效率地重新導向 Pod 流量 - 當 Pod 中的容器傳送目的地為負載平衡器的 IP 位址的輸出封包時 - 直接繞過負載平衡器到達後端服務。

  2. 處理負載平衡器封包: 有些負載平衡器傳送的目的地 IP 設定為負載平衡器 IP 位址的封包。因此,這些封包需要直接路由到正確的後端 (可能不在該節點本機),以避免迴圈。

問題

然而,上述行為存在幾個問題

  1. 來源 IP 有些雲端供應商在傳輸封包到節點時,會使用負載平衡器的 IP 作為來源 IP。在 kube-proxy 的 ipvs 模式中,存在負載平衡器的健康檢查永遠不會傳回的問題。發生這種情況的原因是回覆封包會轉發到本機介面 kube-ipvs0 (負載平衡器的 IP 繫結到該介面),然後被忽略。

  2. 負載平衡器層級的功能遺失 某些雲端供應商在負載平衡器層級提供功能 (例如 TLS 終止、Proxy Protocol 等)。繞過負載平衡器會導致封包到達服務時遺失這些功能 (導致協定錯誤)。

即使停用新的 Alpha 行為 (預設值),也有一種解決方法,涉及為 Service 設定 .status.loadBalancer.ingress.hostname,以繞過 kube-proxy 繫結。但這只是一個權宜之計。

解決方案

總之,為雲端供應商提供停用目前行為的選項將非常有益。

為了解決這個問題,Kubernetes v1.29 為 Service 引入了一個新的 (Alpha) .status.loadBalancer.ingress.ipMode 欄位。此欄位指定負載平衡器 IP 的行為方式,且只能在也指定 .status.loadBalancer.ingress.ip 欄位時指定。

.status.loadBalancer.ingress.ipMode 可能有兩個值:"VIP""Proxy"。預設值為 "VIP",表示傳遞到節點且目的地設定為負載平衡器的 IP 和連接埠的流量將由 kube-proxy 重新導向到後端服務。這保留了 kube-proxy 的現有行為。"Proxy" 值旨在防止 kube-proxy 在 ipvs 和 iptables 模式中將負載平衡器的 IP 位址繫結到節點。因此,流量會直接傳送到負載平衡器,然後轉發到目的地節點。轉發封包的目的地設定取決於雲端供應商的負載平衡器如何傳遞流量

  • 如果流量傳遞到節點,然後 DNAT 到 Pod,則目的地將設定為節點的 IP 和節點連接埠;
  • 如果流量直接傳遞到 Pod,則目的地將設定為 Pod 的 IP 和連接埠。

用法

以下是啟用此功能的必要步驟

  • 下載最新的 Kubernetes 專案 (版本 v1.29.0 或更新版本)。
  • 在 kube-proxy、kube-apiserver 和 cloud-controller-manager 上使用命令列旗標 --feature-gates=LoadBalancerIPMode=true 啟用功能閘道。
  • 對於 type: LoadBalancer 的 Service,將 ipMode 設定為適當的值。此步驟很可能由您選擇的 cloud-controller-manager 在 EnsureLoadBalancer 過程中處理。

更多資訊

參與其中

Slack 上聯絡我們:#sig-network,或透過郵寄清單

致謝

非常感謝 @Sh4d1 的原始 KEP 和初始實作程式碼。我中途接手並完成了工作。同樣地,非常感謝其他協助設計、實作和審查此功能 (依字母順序排列) 的貢獻者