控管與持續性 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. 建立閘道:設定 Kubernetes 閘道物件,其中包含預留的永久 IP 位址,並可建立規則 (GKEIPRoutes),指定叢集中的哪些 Pod 可使用這些永久 IP 位址。
  4. 建立或識別永久 IP 位址的工作負載:如果您在額外網路上使用永久 IP 位址,請啟用多個網路介面並定義永久 IP 位址所在的網路,準備讓 Pod 使用永久 IP 位址。
  5. 為所選工作負載建立 GKEIPRoute 物件:設定 GKEIPRoute,將永久 IP 位址指派給特定 Pod。您可以使用標籤指定正確的 Pod,並視需要設定路由對 Pod 變更的反應方式。
  6. 設定 Application Awareness:在 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。
    • 選取器:GKEIPRoute,位於符合特定標籤的 GKEIPRoute 命名空間中。
    • 相同命名空間:只有與 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
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  name: proxy-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: proxy
  template:
    metadata:
      # annotations:  <- Include these lines if the pods are 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

其中:

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

將資訊清單套用至叢集:

kubectl apply -f my-ip-route.yaml

為 StatefulSet Pod 指派永久 IP 位址

如要將永久 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:  <- Include these lines if the pods are 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

將資訊清單套用至叢集 (請確認您有名為「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:  <- Include these lines if the pods are 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 內的位址。如要達成這個目標,Pod 必須具備權限。

你可以使用下列任一選項設定 Pod 規格:

  • 修改 net.ipv4.ip_nonlocal_bind sysctl

    您可以修改系統設定,允許應用程式使用未直接指派給介面的 IP 位址,方法是在 Pod securityContext 中設定 net.ipv4.ip_nonlocal_bind sysctl。如果應用程式可以繫結至不在介面上的 IP 位址,這個選項就很有用。

    在 Deployment 或 StatefulSet YAML 規格的 spec.template.spec 下方,加入下列內容:

    securityContext:
      sysctls:
      - name: net.ipv4.ip_nonlocal_bind
        value: "1"
    
  • 將指派的 IP 位址新增至 Pod 介面

    您可以使用 init 容器,手動將 GKEIPRoute 物件聲明的 IP 位址新增至其中一個 Pod 介面。這會讓 Pod 看到 IP 位址,彷彿是直接指派的位址。這需要 NET_ADMIN 功能。

    在 Deployment 或 StatefulSet YAML 規格的 spec.template.spec 下方,新增下列內容:

    initContainers:
    - name: configure-ips
      image: gcr.io/google.com/cloudsdktool/cloud-sdk:slim
      command: ['sh', '-c', 'ip address add ASSIGNED_IP/32 dev eth0']
      securityContext:
        capabilities:
          add:
          - NET_ADMIN
    

    將 ASSIGNED_IP 替換為指派給 GKEIPRoute 物件的其中一個 IP 位址。

  • 原始通訊端:如要進一步控管,應用程式可以直接與網路堆疊互動 (進階)。

  • 使用者空間 IP 位址堆疊:在特殊情況下,Pod 內可能會執行獨立應用程式來管理 IP 位址 (非常進階)。

步驟 7:為指派的 IP 位址啟用 ARP (僅限預設網路)

如要產生有效的位址解析協定 (ARP) 要求和回應,並使用預設網路上 GKEIPRoute 物件指派的 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 分鐘。在這段期間,您必須更新叢集設定。如要執行這項操作,請在 GKEIPRoute 的 spec.podSelector 欄位中,將舊 Pod 的標籤替換為新 Pod 的標籤。

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

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

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

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

排解 Pod 永久 IP 位址的通訊問題

本節說明如何解決 Pod 永久 IP 位址的相關問題。

NoPodsFound 找不到相符的 Pod 時

症狀

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

可能原因

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

解決方法

  1. 檢查標籤:再次確認 GKEIPRoutepodSelector 中的標籤是否與您套用至預期 Pod 的標籤相符。
  2. 確認 Pod 是否存在:確認具有正確標籤的 Pod 確實存在於 Gateway Listeners 指定的 GKEIPRoute 命名空間中。如果 reactionMode == Exists 為 0,請檢查 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. 進一步調查 (如有必要):如果「Mutated」狀態持續一段時間,可能表示設定有誤。檢查其他狀態條件: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 建立關聯,快速容錯移轉機制就不會觸發。

後續步驟