透過永久 IP 位址控管通訊

本頁說明如何在 Google Kubernetes Engine (GKE) Pod 上實作永久 IP 位址。您可以透過自訂持續性 IP 位址對應,控管 GKE Pod 網路。如要進一步瞭解永久 IP 位址、用途和優點,請參閱「關於 GKE Pod 的永久 IP 位址」。

需求條件

  • GKE 1.31 以上版本。
  • 您可以選擇保留 Google 提供的 IP 位址,或是自備 IP 位址 (BYOIP)。
  • 設定在 Pod 中執行的應用程式,以便識別及使用指派的持續性 IP 位址。
  • 如要為 GKE Pod 設定永久 IP 位址,必須啟用 GKE Dataplane V2 和 Gateway API 的叢集。

限制

  • 您必須設定應用程式,才能使用指派的永久 IP 位址。GKE 不會自動將 IP 位址設定新增至 Pod 的網路介面。
  • 每個持續性 IP 位址一次只能與一個 Pod 建立關聯。 如果有多個可用的 Pod,GKE 通常會將流量傳送至最新的相符 Pod。不過,只有在最新的 Pod 處於健康狀態時,GKE 才會執行這項操作,也就是說,Pod 預設具有 Ready 條件狀態 True。如要設定或變更這項行為,請在 GKEIPRoute 上使用 reactionMode 設定。
  • GKE 僅支援 IPv4 位址做為永久 IP 位址。
  • GKE 僅支援第 3 層或裝置類型多重網路
    • 非 DPDK 用途不支援使用永久 IP 位址的高可用性 (HA)。
  • 單一 GKEIPRoute 最多可指定 16 個 IP 位址。如要設定更多地址,可以建立多個 GKEIPRoute 物件。

事前準備

開始之前,請確認你已完成下列工作:

  • 啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 如要使用 Google Cloud CLI 執行這項工作,請安裝初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update 指令,取得最新版本。較舊的 gcloud CLI 版本可能不支援執行本文件中的指令。

為 GKE Pod 實作永久 IP 位址

GKE 中的永久 IP 位址可為 Pod 提供穩定的網路身分,即使 Pod 本身更新或移動,也不會受到影響。

本節將摘要說明為 GKE Pod 實作永久 IP 位址的工作流程:

  1. 建立叢集:建立具有 Gateway API 和 GKE Dataplane V2 的叢集。
  2. 預留 IP 位址:決定您需要外部 (可公開存取) 或內部 (僅限 Google Cloud) IP 位址,並預留該位址。選擇與 GKE 叢集相同的區域。
  3. 建立 Gateway:設定 Kubernetes Gateway 物件,該物件會保留您預留的永久 IP 位址,並允許您建立規則 (GKEIPRoutes),指定叢集中的哪些 Pod 可以使用這些永久 IP 位址。
  4. 建立或識別永久 IP 位址的工作負載:如果您在額外網路使用永久 IP 位址,請啟用多個網路介面,並定義永久 IP 位址所在的網路,準備讓 Pod 使用永久 IP 位址。
  5. 為所選工作負載建立 GKEIPRoute 物件:設定 GKEIPRoute,將永久 IP 位址指派給特定 Pod。您可以使用標籤指定正確的 Pod,並視需要設定路由對 Pod 變更的反應方式。
  6. 設定應用程式感知功能:在 Pod 中設定應用程式,主動使用持續性 IP 位址。
  7. 監控:追蹤閘道和 GKEIPRoute 物件的狀態,確保一切運作正常。

如要為 GKE Pod 實作永久 IP 位址,請執行下列步驟:

步驟 1:建立已啟用 Gateway API 和 GKE Dataplane V2 的 GKE 叢集

如要啟用進階網路轉送和 IP 位址管理功能,以便在 GKE Pod 上實作永久 IP 位址,請按照下列步驟建立 GKE Dataplane V2 叢集:

gcloud container clusters create CLUSTER_NAME \
    --cluster-version=CLUSTER_VERSION \
    --enable-dataplane-v2 \
    --enable-ip-alias \
    --gateway-api=standard

更改下列內容:

  • CLUSTER_NAME:叢集名稱。
  • CLUSTER_VERSION:叢集版本。

步驟 2:設定持續性 IP 位址

如要為 Pod 建立可靠的網路身分,並設定永久 IP 位址,請先取得永久 IP 位址。您可以選擇保留 Google 提供的 IP 位址,或使用自己的 IP 位址 (BYOIP)。

步驟 2a:預留 Google 提供的 IP 位址

如要保留外部 IP 位址,請執行下列指令:

gcloud compute addresses create ADDRESS_NAME \
   --region=REGION

更改下列內容:

  • ADDRESS_NAME:您要與這個地址建立關聯的名稱。
  • REGION:要保留這個位址的區域。這個地區應與要連結 IP 位址的 Pod 位於同個地區。

    注意:保留 IP 位址時必須指定區域,因為轉送規則 (負責處理持續性 IP 位址的流量路徑) 屬於區域性。IP 位址和 GKE 叢集必須位於相同區域,才能正確轉送流量。

如要保留內部 IP 位址,請執行下列指令:

gcloud compute addresses create ADDRESS_NAME \
    --region REGION
    --subnet SUBNETWORK \
    --addresses IP_ADDRESS

更改下列內容:

  • ADDRESS_NAME:要保留的一或多個位址名稱。如有數個地址,請以空格分隔,並以清單形式指定所有地址。例如:example-address-1 example-address-2 example-address-3
  • REGION:這項要求的區域。
  • SUBNETWORK:這個內部 IPv4 位址所屬的子網路。

為確保流量在私有網路中正確路由,內部 IP 位址必須屬於叢集的預設子網路或額外網路子網路。

如要進一步瞭解外部和內部 IP 位址,或查看如何使用主控台預留位址,請參閱「預留靜態外部 IP 位址」和「預留靜態內部 IP 位址」。

步驟 2b:自備 IP 位址 (BYOIP)

您可以自備 IP 位址 (BYOIP),不必使用 Google 提供的 IP 位址。如果您需要應用程式的特定 IP 位址,或是要將現有系統移至 Google Cloud,BYOIP 就非常實用。如要使用 BYOIP,Google 會驗證您是否擁有 IP 位址範圍,並在 IP 位址匯入 Google Cloud後,將這些位址指派為 GKE Pod 的持續性 IP 位址。詳情請參閱「使用自備 IP 位址」。

步驟 3:建立 Gateway 物件

閘道物件會保留 IP 位址,並定義哪些 Pod 有資格使用這些位址。如要控管如何將永久 IP 位址指派給 GKE Pod,請使用 Gateway 物件。

  1. 建立適當類別的 Kubernetes Gateway 物件:
    • gke-persistent-regional-external-managed,適用於外部 (公開) IP 位址。
    • gke-persistent-regional-internal-managed 內部 (僅限Google Cloud) IP 位址。
    • gke-persistent-fast-regional-external-managed,適用於具備快速容錯移轉功能的外部 IP 位址。
    • gke-persistent-fast-regional-internal-managed,適用於內部 (僅限 Google Cloud) IP 位址,並提供快速容錯移轉功能。
  2. 在閘道的地址部分,列出這個閘道管理的持續性 IP 位址 (Google 提供或 BYOIP)。
  3. 使用 Listeners 區段,判斷哪些 Pod (和相關聯的 GKEIPRoute 物件) 可能會使用閘道的 IP 位址。Listeners 做為篩選器,依據 GKEIPRoute 物件所在的命名空間進行篩選。GKEIPRoute

    您可以選擇下列 Kubernetes 命名空間選取選項:

    • 所有命名空間:叢集中的任何 GKEIPRoute
    • 選取器GKEIPRouteGKEIPRoute 的命名空間符合特定標籤。
    • 相同命名空間:只有與 Gateway 位於相同 GKEIPRoute 命名空間的 GKEIPRoutes

以下範例提供叢集範圍的外部永久 IP 位址存取權,允許任何 Pod 使用這些位址。

將下列範例資訊清單儲存為 allowed-pod-ips.yaml

kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
  namespace: default
  name: allowed-pod-ips
spec:
  gatewayClassName: gke-persistent-regional-external-managed

  listeners:
    - name: default
      port: 443
      protocol: none
      allowedRoutes:
        namespaces:
          from: All

  addresses:
    - value: "34.123.10.1/32"
      type: "gke.networking.io/cidr"
    - value: "34.123.10.2/32"
      type: "gke.networking.io/cidr"

其中:

  • addresses:列出權限由特定閘道管理的所有 IP 位址。
  • listeners:用於識別 GKEIPRoute 物件可參照這個閘道的命名空間。

將資訊清單套用至叢集:

kubectl apply -f allowed-pod-ips.yaml

步驟 4:(選用) 建立或識別具有額外網路的工作負載,以取得永久 IP 位址

如果您打算將永久 IP 位址用於需要連線至多個網路的 Pod,可以設定多網路 Pod,並建立網路物件,指出永久 IP 位址所屬的網路。

步驟 5:為所選工作負載建立 GKEIPRoute 物件

如要將永久 IP 位址指派給所選 Pod,請建立 GKEIPRoute 物件。

將下列範例資訊清單儲存為 my-ip-route.yaml

kind: GKEIPRoute
apiVersion: networking.gke.io/v1
metadata:
  namespace: default
  name: my-ip-route
spec:
  parentRefs:
  - name: allowed-pod-ips
    namespace: default
  addresses:
  - value: "34.123.10.1/32"
    type: "gke.networking.io/cidr"
  network: default
  reactionMode: ReadyCondition
  podSelector:
    matchLabels:
      component: proxy
  nodeSelector: # Can only be specified when using fast failover Gateway Classes.
    matchLabels:
      component: proxy

其中:

  • parentRefs:指向使用永久 IP 位址的 Gateway。這個欄位無法變更。
  • 位址:列出所有路由至以 podSelector 識別的 Pod 的持續性 IP 位址。這個欄位可變更。如果是 IPv4,則僅支援 /32 位址。
  • podSelector:指定用於識別 Pod 的標籤,持續性 IP 位址會路由至該 Pod。這個欄位可變動,且適用於放置 GKEIPRoute 的相同命名空間。如果選取多個 Pod,系統會額外考量兩個因素:Pod 建立時間 (GKE 會選取最新的 Pod) 和 reactionMode 欄位的設定。
  • reactionMode:指定在建立或刪除特定 Pod (由 podSelector 選取) 時,這項功能的行為。這個欄位為選填,預設值為 ReadyConditionReadyCondition 欄位無法變更。您可以設定 reactionMode,控管在建立、刪除或更新 Pod 時,這項功能的運作方式。
  • 網路:指向 Pod 上的網路介面,持續性 IP 位址會路由至該介面。這個欄位為選填欄位,預設值為 default。請注意,如果使用預設網路,network 必須設為 default。如果您使用其他網路,請將網路設為先前建立的網路物件名稱。這個欄位無法變更。
  • nodeSelector:指定要預先設定的節點標籤,以利快速容錯移轉。使用快速容錯移轉閘道類別時,必須設定這個欄位,最多可選取 64 個節點。您必須確保具有持續性 IP 位址的 Pod 排程在這些節點上,通常是使用 Pod 的 nodeSelector

將資訊清單套用至叢集:

kubectl apply -f my-ip-route.yaml

將永久 IP 位址指派給 StatefulSet Pod

如要將永久 IP 位址指派給 StatefulSet 中的特定多重網路 Pod,請使用 Pod 的可預測主機名稱和 Kubernetes 的自動標籤,如下列範例所示:

將下列範例資訊清單儲存為 my-pod-ips.yaml

kind: GKEIPRoute
apiVersion: networking.gke.io/v1
metadata:
  namespace: proxy-ss-ns
  name: my-pod-ips
spec:
  parentRefs:
  - name: allowed-pod-ips
    namespace: default
  addresses:
  - value: "34.123.10.1/32"
    type: "gke.networking.io/cidr"
  - value: "34.123.10.2/32"
    type: "gke.networking.io/cidr"
  network: blue-network
  reactionMode: ReadyCondition
  podSelector:
    matchLabels:
      statefulset.kubernetes.io/pod-name: proxy-ss-1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  namespace: proxy-ss-ns
  name: proxy-ss
spec:
  selector:
    matchLabels:
      component: proxy
  serviceName: "proxy"
  replicas: 3
  template:
    metadata:
      annotations:
        networking.gke.io/default-interface: 'eth0'
        networking.gke.io/interfaces: '[{"interfaceName":"eth0","network":"default"}, {"interfaceName":"eth1","network":"blue-network"}]'
      labels:
        component: proxy
    spec:
      containers:
      - name: hello-app
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0

將資訊清單套用至叢集 (請確認您有名為「blue-network」的網路):

kubectl apply -f my-pod-ips.yaml

將永久 IP 位址指派給 Deployment Pod

如要將永久 IP 位址指派給 Deployment 中最新的 Pod,請套用具有下列設定的 GKEIPRoute

將下列範例資訊清單儲存為 my-pod-ips.yaml

kind: GKEIPRoute
apiVersion: networking.gke.io/v1
metadata:
  namespace: proxy-deploy-ns
  name: my-pod-ips
spec:
  parentRefs:
  - name: allowed-pod-ips
    namespace: default
  addresses:
  - value: "34.123.10.1/32"
    type: "gke.networking.io/cidr"
  - value: "34.123.10.2/32"
    type: "gke.networking.io/cidr"
  network: blue-network # point to the right network if you intend to use persistent-ip on additional networks
  reactionMode: ReadyCondition
  podSelector:
    matchLabels:
      component: proxy
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: proxy-deploy-ns
  name: proxy-deploy
spec:
  selector:
    matchLabels:
      component: proxy
  replicas: 4 # Latest Pod is used
  template:
    metadata:
      # annotations:  <- Remove these lines if the pods are not multi-nic pods
      #   networking.gke.io/default-interface: 'eth0'
      #   networking.gke.io/interfaces: '[{"interfaceName":"eth0","network":"default"}, {"interfaceName":"eth1","network":"blue-network"}]'
      labels:
        component: proxy
    spec:
      containers:
      - name: hello-app
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0

將資訊清單套用至叢集:

kubectl apply -f my-ip-route.yaml

如果您使用其他網路,請確認您有名為「blue-network」的網路。

步驟 6:在 Pod 內使用持續性 IP 位址

使用 GKEIPRoute 將永久性 IP 位址指派給 GKE Pod 時,系統不會自動讓應用程式使用這些 IP 位址。持續性 IP 位址是在網路路由層級處理,但 Pod 的預設設定不會知道這件事。您必須設定應用程式的設定,才能辨識及使用 Pod 內的位址。如要達成這個目標,Pod 必須具備權限。

如要設定應用程式,請考慮下列選項:

  • net.ipv4.ip_nonlocal_bind:修改系統設定,允許應用程式使用未直接指派給介面的 IP 位址。
  • ip address add:在應用程式邏輯中使用這個指令,手動將永久 IP 位址新增至介面。
  • 原始通訊端:如要進一步控管,應用程式可以直接與網路堆疊互動 (進階)。
  • 使用者空間 IP 位址堆疊:在特殊情況下,Pod 內可能會執行個別應用程式來管理 IP 位址 (非常進階)。

步驟 7:為持續性 IP 位址啟用 ARP (僅限預設網路)

如要產生有效的位址解析通訊協定 (ARP) 要求和回應,並使用預設網路上的持續性 IP 位址建立與 Pod 的新連線,您必須設定 arp_announce 變數。

如要設定 arp_announce 變數,請在 Pod 上執行下列指令:

echo "2" > /proc/sys/net/ipv4/conf/eth0/arp_announce

其中 arp_announce 變數會控管 ARP 宣告的處理方式。設為「2」可確保系統會針對持續性 IP 位址發布 ARP 宣告,讓網路上的其他裝置瞭解新的關聯。

步驟 8:使用快速容錯移轉

如果使用具備快速容錯移轉功能的永久 IP 位址,可以從 Pod 發出 Gratuitous ARP (GARP),暫時將流量導向該 Pod。Google Cloud 會尊重該 GARP 約 20 分鐘。在這段期間,您必須更新叢集設定。如要這麼做,請在 GKEIPRoutespec.podSelector 欄位中,將舊 Pod 的標籤替換為新 Pod 的標籤。

在 Pod 變更期間自訂永久 IP 位址行為

本節說明建立或刪除目標 Pod 時,GKE Pod 的持續性 IP 位址會如何運作。GKE 控制器會監控 Pod 和 GKEIPRoute 設定。偵測到更新時,系統會根據您選擇的 reactionMode,自動將持續性 IP 位址重新指派給合適的 Pod。

瞭解永久 IP 位址功能如何自動處理 Pod 變更,以及可用的設定選項:

  • GKEIPRoute 設定的 reactionMode 欄位中,決定要使用 ReadyConditionExists。請根據應用程式的需求,考量 IP 位址的指派速度與嚴格的就緒要求。
  • 如果您使用 ReadyCondition 確保就緒狀態,請確認 Pod 已正確導入 Kubernetes 就緒探測器。否則,持續性 IP 位址可能無法正常運作。
  • 建議您監控 Pod 的狀態和 GKEIPRoute 物件的 Conditions 欄位,確保系統運作正常。true狀態表示系統運作正常。Ready

排解與 Pod 持續性 IP 位址的通訊問題

本節說明如何解決 Pod 持續性 IP 位址的相關問題。

NoPodsFound 找不到相符的 Pod 時

症狀

GKEIPRoute 物件會指定 podSelector (一組標籤),用來識別與永久 IP 位址相關聯的 Pod。NoPodsFound 狀態表示目標 GKEIPRoute's 命名空間中沒有任何具有相符標籤的 Pod。

可能原因

  • 標籤不正確:您打算搭配使用永久 IP 位址的 Pod 可能有錯誤的標籤,或完全沒有標籤。
  • 沒有 Pod:如果 reactionMode == Exists,請檢查 pod.Spec.nodeName 欄位,確認 Pod 是否已指派給節點。GKEIPRoute's 命名空間中可能沒有任何符合選取器的 Pod 正在執行。
  • Pod 未就緒:如果 reactionMode == ReadyCondition,請檢查 Pod 狀態是否為 READY。即使有相符的 Pod,如果該 Pod 不處於 Ready 狀態,就無法處理流量,因此不會被選取。

解決方法

  1. 檢查標籤:請再次確認 GKEIPRoute's podSelector 中的標籤是否與您套用至目標 Pod 的標籤相符。
  2. 確認 Pod 是否存在:確認具有正確標籤的 Pod 確實存在於 Gateway Listeners 指定的 GKEIPRoute 命名空間中。如果 reactionMode == Exists,請檢查 pod.Spec.nodeName 欄位,確認 Pod 是否已指派給節點
  3. 確認 Pod 完備性:如果 reactionMode == ReadyCondition,請檢查 Pod 狀態是否為 READY。使用下列指令,確認 Pod 處於 Ready 狀態:

    kubectl get pods -n <namespace>
    

    系統不會選取處於其他狀態的 Pod (例如「待處理」、「錯誤」)。

  4. 設定 Pod,以便在指派的持續性 IP 位址上回應。

Mutated 找到相符的 Pod,且正在進行持續性 IP 位址程式設計

症狀

GKEIPRoute 狀態顯示「已變動」,表示系統正在為相符的 Pod 設定持續性 IP 位址。

可能原因:

設定期間,系統會為持續性 IP 位址設定 GKE 資料路徑和 Google Cloud 資源,因此您會看到「已變更」狀態。

解決方法:

  1. 等待並重試:在大多數情況下,設定程序會在短時間內自動完成。等待一段時間後,請檢查狀態。成功後會變更為 Ready
  2. 進一步調查 (如有必要):如果「已變更」狀態持續一段時間,可能表示設定有誤。檢查GKEIPRoute的其他狀態條件:
    • 已接受:指出 GKEIPRoute 設定是否有效。
    • DPV2Ready:指出節點上的資料路徑是否已正確程式設計。
    • GCPReady:指出 Google Cloud 資源是否已按照預期設定。

請在這些情況下尋找錯誤訊息,協助排解問題。

已傳送 GARP,但 Pod 未接收流量

症狀

您已從新的 Pod 傳送 GARP,但流量流程維持不變。GKEIPRoute 狀態仍為「就緒」,且未顯示錯誤。

可能原因

Pod 所在的節點不符合 GKEIPRoute 中的 nodeSelector。GARP 使用的 IP 位址與 GKEIPRoute 無關。

解決方法

  • 驗證 Pod 的節點:確認 Pod 在符合 GKEIPRoute 設定中 nodeSelector 的節點上執行。如果 Pod 不在相符的節點上,節點可能不會針對 GKEIPRoute 進行程式設計。
  • 驗證 GARP 的 IP 位址:確認 GARP 中的 IP 位址是 GKEIPRoute「位址」欄位中指定的 IP 位址之一。如果 IP 位址未與 GKEIPRoute 建立關聯,快速容錯移轉機制就不會觸發。

後續步驟