本文說明如何解決 Kubernetes 服務流量分配不均的問題。
找出流量分配不均的徵兆
流量分配不均 (通常稱為熱點) 是指一小部分 Pod 或節點處理的總工作負載量不成比例,而其他 Pod 或節點仍未充分利用。
常見症狀包括:
- 效能瓶頸:使用者可能會在過度使用的網路連線上,遇到間歇性逾時、HTTP 5xx 錯誤或封包遺失等問題。
- 資源耗盡:特定 Pod 或節點的 CPU 或記憶體使用率明顯高於機群中的其他項目。
- 流量失衡模式:
- 每個 Pod 的負載不平衡:即使所有 Pod 都回報健康狀態良好且已準備就緒,流量仍只會傳送至一小部分可用的 Pod。
- 每個節點的不平衡:一或多個節點收到的封包或要求明顯多於其他節點,通常發生在使用
externalTrafficPolicy: Local時,Pod 放置位置不均。 - 用戶端工作階段黏性:來自單一高用量用戶端的所有要求,一律會轉送至相同的後端 Pod。
使用 Cloud Monitoring 診斷問題
如要確認這些徵兆,請使用下列指標顯示流量模式:
- 第 7 層 (Ingress/閘道):繪製
loadbalancing.googleapis.com/backend/request_count並依backend_target分組依據,比較不同後端的請求量。
瞭解流量分配不均的常見原因
本節說明 Kubernetes 服務流量分配不均的常見原因。這種不平衡可能會導致效能瓶頸、特定 Pod 的資源耗盡,以及應用程式可用性降低,因為某些 Pod 接收的流量遠高於其他 Pod,而某些 Pod 接收的流量則非常少或沒有。
工作階段相依性導致分配不均
啟用工作階段相依性的負載平衡器會持續將來自相同用戶端的要求,轉送至同一個後端 Pod,因此會發生下列問題。如果特定用戶端產生大量流量,該 Pod 就會過度負載,導致資源使用率不均,也就是該 Pod 接收的負載遠高於其他 Pod,而其他 Pod 仍未充分利用資源。
您可以使用 sessionAffinity 欄位,在 Kubernetes Service 物件中設定工作階段相依性。
如果 sessionAffinity 設為 ClientIP,Service 會確保來自相同用戶端 IP 位址的所有連線,一律轉送至相同後端 Pod。這項設定可提供真正的用戶端 IP 工作階段相依性。
如果 sessionAffinity 設為 None (預設行為),第 4 層負載平衡器通常會使用各種網路參數的雜湊值分配連線,例如 4 值組 (用戶端 IP 位址、目的地 IP 位址、目的地通訊埠、通訊協定) 或 5 值組 (包括來源通訊埠)。雖然這個雜湊作業可將具有相同元組值的連線一律路由至相同後端,藉此提供某種程度的連線「黏著性」,但如果其他元組元素有所變更,就無法保證來自特定用戶端 IP 位址的所有連線一律會連線至相同 Pod。
詳情請參閱「工作階段相依性」。
如果是 GKE Gateway,則 GCPTrafficDistributionPolicy CRD 會設定工作階段相依性。詳情請參閱「使用政策設定 Gateway 資源」。
如果是區域外部直通式網路負載平衡器,您可以使用工作階段相依性,維持與特定後端的連線黏性。不過請注意,如果某些用戶端產生的流量多於其他用戶端,工作階段相依性本身可能會導致分配不均。
詳情請參閱「工作階段相依性」和「後端服務型外部直通式網路負載平衡器簡介」。
以下範例顯示含有 sessionAffinity: ClientIP 的 Service 資訊清單:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: LoadBalancer
sessionAffinity: ClientIP # This can cause uneven distribution
ports:
- port: 80
targetPort: 8080
selector:
app: my-app
連線集區導致分配不均
當負載平衡器重複使用特定 Pod 的現有連線時,即使其他 Pod 有可用容量,也會發生連線集區化。如果某些連線的存留時間較長,或處理的要求明顯多於其他連線,這種行為可能會導致不平衡。這會將流量集中在特定 Pod 上,類似於工作階段相依性,造成資源使用率不均,也就是這些 Pod 負載過重,而其他 Pod 仍未充分利用。
負載平衡器會實作連線集區,減少建立新連線的負擔,進而提升效能。不過,如果管理不當,連線集區可能會導致流量分配不均,尤其是維持長期連線的應用程式。
如要減輕連線共用造成的分配不均問題,請在應用程式或用戶端層級導入策略:
設定用戶端使用多個連線:不要依賴單一長期連線,而是設定用戶端開啟及管理負載平衡器的多個連線集區。這樣一來,負載平衡器就能將新的連線嘗試分配至可用的後端 Pod,進而改善整體流量分配。
定期關閉並重新開啟連線:對於自然維持長期連線的應用程式,請設定應用程式或其用戶端,定期關閉並重新開啟連線。雖然這樣會稍微增加重新建立連線的負擔,但負載平衡器有新的機會,可將後續的連線嘗試分配給其他使用率較低的後端 Pod。如果服務的連線終止和重新建立不會造成過度中斷,這種做法就特別有效。
實作積極的連線排除功能:請確認 Pod 已設定為正常關機和連線排除。當 Pod 正常終止時 (例如在部署或縮減期間),負載平衡器應停止將新連線傳送至該 Pod,並允許現有連線完成或排空。這樣一來,流量就能更順暢地轉移至其他 Pod,避免集中在終止的 Pod。
主動管理連線行為,有助於負載平衡器更平均地分配流量,即使是長期連線也適用。
5 元組雜湊導致分配不均
如果您未明確設定工作階段相依性,許多第 4 層負載平衡器都會採用這項預設行為。如果許多連線來自同一個用戶端,或使用相同的連接埠組合,就會導致分配不均。
如要解決雜湊造成的失衡問題,請考慮下列事項:
使用第 7 層負載平衡:GKE Ingress 和 Gateway 會在要求層運作,因此能將單一用戶端的要求分配至多個後端 Pod。
調整用戶端行為:設定用戶端以使用多個連線或較大的來源連接埠集區。
節點間的 Pod 分布不均,導致分布不均
如果 Pod 未平均分配到各個節點,且負載平衡器未使用容器原生負載平衡,就會發生這個問題。Pod 較多的節點會收到更多流量,導致部分節點過載,其他節點則未充分運用。
使用 externalTrafficPolicy: Local 時,這個問題尤其重要。
外部流量政策設定導致分配不均
Service 的 externalTrafficPolicy 設定會影響流量的轉送方式。
- 叢集:負載平衡器可將流量分配給叢集中的任何節點。使用
Cluster設定,在所有可用節點和 Pod 中平均分配工作負載。 - Local:只將流量轉送至收到流量的相同節點上執行的 Pod。如果沒有在節點間平均分配 Pod,可能會導致分配不均。
節點親和性導致分布不均
使用節點相依性將 Pod 限制在部分節點上,可能會導致這些節點過度負載,尤其是當工作負載在這些節點間的分配不均時。
確認 Pod 並未固定在特定節點。