本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

Kubernetes 1.29:新(Alpha)特性,服務的負載均衡器 IP 模式

這篇博文介紹了 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 中的容器傳送一個目的地為負載均衡器 IP 地址的出站資料包時,透過繞過負載均衡器,高效地將 Pod 流量直接重定向到後端服務。

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

問題

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

  1. 源 IP 一些雲提供商在向節點傳輸資料包時使用負載均衡器的 IP 作為源 IP。在 kube-proxy 的 ipvs 模式下,存在一個問題,即來自負載均衡器的健康檢查永遠不會返回。這是因為回覆資料包將被轉發到本地介面 kube-ipvs0(負載均衡器的 IP 繫結到此介面),隨後被忽略。

  2. 負載均衡器層面的功能丟失 某些雲提供商在負載均衡器層面提供功能(如 TLS 終止、代理協議等)。繞過負載均衡器會導致資料包到達服務時這些功能丟失(導致協議錯誤)。

即使停用了新的 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 和初始實現程式碼。我中途接手並完成了這項工作。同樣,非常感謝在設計、實現和審查此功能方面提供幫助的其他貢獻者(按字母順序排列):