本篇文章已超過一年。較舊的文章可能包含過時的內容。請確認頁面上的資訊自發布以來是否已變得不正確。

Kubernetes 1.27:避免為 NodePort 服務指派埠時發生衝突

在 Kubernetes 中,服務 (Service) 可用於為一組 Pod 上運行的應用程式提供統一的流量端點。用戶端可以使用服務提供的虛擬 IP 位址 (或 VIP) 進行存取,而 Kubernetes 為存取不同後端 Pod 的流量提供負載平衡,但 ClusterIP 類型的服務僅限於提供叢集內節點的存取,而來自叢集外部的流量則無法路由。解決此問題的一種方法是使用 type: NodePort 服務,它會設定到叢集中所有節點特定埠的映射,從而將流量從外部重新導向到叢集內部。

Kubernetes 如何為服務分配節點埠?

當建立 type: NodePort 服務時,其對應的埠會以兩種方式之一分配

  • 動態:如果服務類型為 NodePort,且您未在該服務的 spec 中明確設定 nodePort 值,則 Kubernetes 控制平面將在建立時自動為其分配一個未使用的埠。

  • 靜態:除了上述的動態自動分配之外,您也可以明確指定一個位於 nodeport 埠範圍配置內的埠。

您手動分配的 nodePort 值在整個叢集中必須是唯一的。嘗試建立 type: NodePort 服務,但明確指定已分配的節點埠將會導致錯誤。

為什麼您需要保留 NodePort 服務的埠?

有時,您可能希望 NodePort 服務在眾所周知的埠上運行,以便叢集內部或外部的其他組件和使用者可以使用它們。

在某些複雜的叢集部署中,同一個網路上混合了 Kubernetes 節點和其他伺服器,可能有必要使用一些預定義的埠進行通訊。特別是,某些基本組件不能依賴支援 type: LoadBalancer 服務的 VIP,因為該叢集的虛擬 IP 位址映射實作也依賴這些基礎組件。

現在假設您需要在 Kubernetes 上向 Kubernetes 叢集外部運行的用戶端公開 Minio 物件儲存服務,並且約定的埠是 30009,我們需要建立如下的服務

apiVersion: v1
kind: Service
metadata:
  name: minio
spec:
  ports:
  - name: api
    nodePort: 30009
    port: 9000
    protocol: TCP
    targetPort: 9000
  selector:
    app: minio
  type: NodePort

然而,如前所述,如果 minio 服務所需的埠 (30009) 未保留,並且在 minio 服務之前或與之同時建立並動態分配了另一個 type: NodePort (或可能是 type: LoadBalancer) 服務,則 TCP 埠 30009 可能會分配給該另一個服務;如果是這樣,由於節點埠衝突,minio 服務的建立將會失敗。

您如何避免 NodePort 服務埠衝突?

Kubernetes 1.24 為 type: ClusterIP 服務引入了變更,將叢集 IP 位址的 CIDR 範圍劃分為兩個區塊,這些區塊使用不同的分配策略來降低衝突風險。在 Kubernetes 1.27 中,作為 Alpha 功能,您可以為 type: NodePort 服務採用類似的策略。您可以啟用新的 功能閘道 ServiceNodePortStaticSubrange。啟用此功能可讓您為 type: NodePort 服務使用不同的埠分配策略,並降低衝突風險。

NodePort 的埠範圍將根據公式 min(max(16, nodeport-size / 32), 128) 進行劃分。公式的結果將是一個介於 16 和 128 之間的數字,步長大小會隨著 nodeport 範圍的增大而增加。公式的結果決定了靜態埠範圍的大小。當埠範圍小於 16 時,靜態埠範圍的大小將設定為 0,這表示所有埠都將動態分配。

動態埠分配預設將使用較高的頻帶,一旦耗盡,它將使用較低的範圍。這將允許使用者在較低的頻帶上使用靜態分配,且衝突風險較低。

範例

預設範圍:30000-32767

範圍屬性
service-node-port-range30000-32767
頻帶偏移min(max(16, 2768/32), 128)
>= min(max(16, 86), 128)
>= min(86, 128)
= 86
靜態頻帶起始30000
靜態頻帶結束30085
動態頻帶起始30086
動態頻帶結束32767
pie showData title 30000-32767 "靜態" : 86 "動態" : 2682

非常小的範圍:30000-30015

範圍屬性
service-node-port-range30000-30015
頻帶偏移0
靜態頻帶起始-
靜態頻帶結束-
動態頻帶起始30000
動態頻帶結束30015
pie showData title 30000-30015 "靜態" : 0 "動態" : 16

小範圍(下限):30000-30127

範圍屬性
service-node-port-range30000-30127
頻帶偏移min(max(16, 128/32), 128)
>= min(max(16, 4), 128)
>= min(16, 128)
= 16
靜態頻帶起始30000
靜態頻帶結束30015
動態頻帶起始30016
動態頻帶結束30127
pie showData title 30000-30127 "靜態" : 16 "動態" : 112

大範圍(上限):30000-34095

範圍屬性
service-node-port-range30000-34095
頻帶偏移min(max(16, 4096/32), 128)
>= min(max(16, 128), 128)
>= min(128, 128)
= 128
靜態頻帶起始30000
靜態頻帶結束30127
動態頻帶起始30128
動態頻帶結束34095
pie showData title 30000-34095 "靜態" : 128 "動態" : 3968

非常大的範圍:30000-38191

範圍屬性
service-node-port-range30000-38191
頻帶偏移min(max(16, 8192/32), 128)
>= min(max(16, 256), 128)
>= min(256, 128)
= 128
靜態頻帶起始30000
靜態頻帶結束30127
動態頻帶起始30128
動態頻帶結束38191
pie showData title 30000-38191 "靜態" : 128 "動態" : 8064