部署閘道


本頁說明如何部署 Kubernetes Gateway 資源,以平衡單一 Google Kubernetes Engine (GKE) 叢集的 Ingress 流量負載。

如要部署閘道,在多個叢集 (或機群) 之間平衡 Ingress 流量負載,請參閱「部署多叢集閘道」。

如需更具體的閘道設定,例如跨命名空間的轉送和 HTTP 流量分割,請參閱 Gateway API 使用者指南

事前準備

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

  • 啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 如要使用 Google Cloud CLI 執行這項工作,請安裝初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update,取得最新版本。
  • 確認您有現有的 Autopilot 或 Standard 叢集。如要建立新叢集,請參閱「建立 Autopilot 叢集」。

GKE Gateway 控制器需求

  • 如果是標準叢集,則須使用 GKE 1.24 以上版本。
  • 如果是 Autopilot,則須為 GKE 1.26 以上版本。
  • Google Cloud CLI 407.0.0 以上版本。
  • 閘道 API 僅支援虛擬私有雲原生叢集。
  • 如果您使用內部 GatewayClass,則必須啟用僅限 Proxy 的子網路
  • 叢集必須啟用 HttpLoadBalancing 外掛程式。
  • 如果您使用 Istio,請務必將 Istio 升級至下列其中一個版本:
    • 1.15.2 以上版本
    • 1.14.5 以上版本
    • 1.13.9 以上版本。
  • 如果您使用共用虛擬私有雲,則需要在主機專案中,將 Compute Network User 角色指派給服務專案的 GKE 服務帳戶。

規定與限制

使用 GKE Gateway 時,請瞭解下列限制:

  • GKE GatewayClass 支援的功能取決於使用的負載平衡器。如要進一步瞭解各 GatewayClass 支援的不同功能,請參閱「GatewayClass 功能」。

    最佳做法

    為確保最佳效能,閘道數量上限為 100 個。 超過這個上限可能會影響效能或導致延遲時間增加。

  • 您無法使用 FrontendConfigBackendConfig 設定 Gateway。您必須使用政策

  • GKE Gateway 的行為與 Ingress 不同,因為 Gateway 不會推斷健康狀態檢查參數。如果服務對 GET / 的要求未傳回 200,或您已調整其他 Pod 完備性檢查,則需要為服務設定 HealthCheckPolicy

  • 您無法在主機名稱中直接指定通訊埠編號 (例如 web.example.com:80),以進行流量轉送。

  • 您可以在 Google Cloud 控制台中查看 GKE 為閘道建立的負載平衡器資源,但這些資源不會參照所連結的閘道或 GKE 叢集。

  • 您無法使用閘道自動產生 Google 代管的 SSL 憑證,但可以手動建立並參照 Google 代管的 SSL 憑證。詳情請參閱「保護閘道安全」。

  • 系統僅支援 HTTPRoute 類型的 Route。系統不支援 TCPRoutes、UDPRoutes 和 TLSRoutes。如要查看 GKE Gateway 控制器支援的欄位清單,請參閱 GatewayClass 功能

  • 自訂要求和回應標頭 (搭配 Gateway 或路徑重新導向),以及使用 Gateway 重新編寫網址,僅適用於 GKE 1.27 以上版本。

  • 對於具有閘道和路徑重新導向的自訂要求和回應標頭,以及具有閘道的網址重寫,系統不支援 GatewayClass gke-l7-gxlb

  • 設定 HTTPRoute 自訂要求和回應標頭時,系統不支援下列Google Cloud 變數

    • cdn_cache_id (GKE Gateway 不支援 Cloud CDN)
    • cdn_cache_status (GKE Gateway 不支援 Cloud CDN)
    • origin_request_header (GKE Gateway 不支援 CORS 政策)
  • GKE Gateway 不支援 Cloud CDN 負載平衡功能。

  • 不支援雙向傳輸層安全標準 (mTLS) 自訂標頭 (不支援搭配 GKE Gateway 使用 mTLS)

  • Google Cloud 傳統版應用程式負載平衡器的限制適用於 GKE Gateway。此外,您無法在後端服務中設定自訂 Host 回應標頭。

  • 路徑重新導向和網址重寫互斥,您無法在相同規則中同時使用這兩種篩選器。

  • Cloud Load Balancing 不支援將流量重新導向至其他通訊埠。如要查看 GKE Gateway 控制器支援的欄位清單,請參閱 GatewayClass 功能

  • GKE Gateway 不支援萬用字元、規則運算式和動態網址

  • 如果您指定具有區域外部閘道類別的閘道,控制器會佈建內部 IP 位址,而非外部位址。如要瞭解如何搭配區域性外部應用程式負載平衡器使用具名位址,請參閱部署區域性外部閘道

  • 閘道會使用獨立 NEG 佈建網路端點群組。為確保 Gateway 控制器能正確調解負載平衡器設定,您無法修改屬於 Gateway 的 Service 的 cloud.google.com/neg 註解。

  • GKE Gateway 不支援參照 GKE Ingress 參照的 Service。

  • 如果 Gateway 已設定為佈建 IP 位址,則不支援變更 Gateway.spec.gatewayClass。為確保 Gateway 控制器能正確調解負載平衡器,請刪除現有 Gateway,然後使用更新後的 gatewayClass 值重新部署資訊清單。

  • 系統不支援 networking.gke.io/app-protocols 註解。請改用 appProtocol 欄位 ,達到相同結果。

  • 如果您搭配使用 GKE Gateway 與 external-dns,且 Gateway 的健康狀態不佳,系統預設會從 DNS 區域中刪除與 Gateway 相關聯的所有 DNS 記錄。

    最佳做法

    執行 external-dns 時,請設定 policy=upsert-only 旗標。 這項設定有助於防止現有 DNS 記錄遭到刪除。

  • 如果從 GKE Gateway 透過路徑參照的 Service 移除通訊埠,您也必須更新 Service 上的獨立 NEG 註解,從 Service 上的獨立 NEG 控制器移除該通訊埠。否則,NEG 控制器最終會停止同步處理這項服務的 Pod 端點。詳情請參閱「NEG Controller stops managing endpoints when port removed from Service」。

在叢集中啟用 Gateway API

如要在 GKE 中使用 Gateway 資源,叢集必須啟用 Gateway API。

如要更新現有 GKE 叢集以啟用 Gateway API,請先確認符合最低需求,再繼續更新。

如要在現有 GKE 叢集 (Autopilot 或 Standard) 上啟用 Gateway API,請使用下列指令。叢集最多可能需要 45 分鐘才能完成協調及安裝 CRD。

gcloud container clusters update CLUSTER_NAME \
    --location=CLUSTER_LOCATION\
    --gateway-api=standard

更改下列內容:

--gateway-api=standard 標記會指示 GKE 隨叢集安裝 v1beta1 CRD。

驗證叢集

建立或升級叢集後,GKE Gateway 控制器會自動安裝 GatewayClass。控制器可能需要幾分鐘才能辨識 CRD 並安裝 GatewayClass。

  1. 確認 Gateway API 已在 GKE 控制層中啟用:

    gcloud container clusters describe CLUSTER_NAME \
      --location=CLUSTER_LOCATION \
      --format json
    

    輸出結果大致如下。如果這個輸出內容為空白,請重新執行叢集更新指令

    "networkConfig": {
      ...
      "gatewayApiConfig": {
        "channel": "CHANNEL_STANDARD"
      },
      ...
    },
    
  2. 確認 GatewayClasses 已安裝在叢集中:

    kubectl get gatewayclass
    

    輸出結果會與下列內容相似:

    NAME                             CONTROLLER                  ACCEPTED   AGE
    gke-l7-global-external-managed   networking.gke.io/gateway   True       16h
    gke-l7-regional-external-managed networking.gke.io/gateway   True       16h
    gke-l7-gxlb                      networking.gke.io/gateway   True       16h
    gke-l7-rilb                      networking.gke.io/gateway   True       16h
    

如要瞭解各 GatewayClass 的功能,請參閱「GatewayClass 功能」。

系統只會自動安裝單一叢集 GatewayClass。如要安裝及使用多叢集 GatewayClass,進行內部和外部多叢集負載平衡,請參閱「啟用多叢集閘道」。

部署內部閘道

內部閘道會公開應用程式,但這些應用程式只能從 VPC 或連線至 VPC 的網路存取。

部署區域內部閘道

以下範例說明如何部署區域內部閘道,在特定地理區域內啟用服務間的高效率安全通訊。

設定僅限 Proxy 的子網路

建立使用內部應用程式負載平衡器的 Gateway 之前,您必須設定僅限 Proxy 的子網路。在使用內部應用程式負載平衡器的虛擬私有雲中,每個區域都必須有僅限 Proxy 的子網路。這個子網路會為負載平衡器 Proxy 提供內部 IP 位址。

  1. 建立僅限 Proxy 的子網路:

    gcloud compute networks subnets create SUBNET_NAME \
        --purpose=REGIONAL_MANAGED_PROXY \
        --role=ACTIVE \
        --region=COMPUTE_REGION \
        --network=VPC_NETWORK_NAME \
        --range=CIDR_RANGE
    

    更改下列內容:

    • SUBNET_NAME:僅限 Proxy 子網路的名稱。
    • COMPUTE_REGION:僅限 Proxy 子網路的區域。
    • VPC_NETWORK_NAME:您要在其中建立僅限 Proxy 子網路的 VPC 網路名稱。請確認這是 GKE 叢集所在的 VPC 網路,也是您部署 Gateway 的位置。這項設定非常重要,可確保負載平衡器與後端服務之間的通訊順暢無礙。
    • CIDR_RANGE:子網路的主要 IP 位址範圍。 您必須使用長度不超過 /26 的子網路遮罩,使該地區的 Proxy 至少有 64 個 IP 位址可用。建議使用的子網路遮罩為 /23
  2. 驗證僅限 Proxy 的子網路:

    gcloud compute networks subnets describe SUBNET_NAME \
        --region=COMPUTE_REGION
    

    輸出結果會與下列內容相似:

    ...
    gatewayAddress: 10.1.1.1
    ipCidrRange: 10.1.1.0/24
    kind: compute#subnetwork
    name: proxy-subnet
    network: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/global/networks/default
    privateIpGoogleAccess: false
    privateIpv6GoogleAccess: DISABLE_GOOGLE_ACCESS
    purpose: REGIONAL_MANAGED_PROXY
    region: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION
    role: ACTIVE
    selfLink: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION/subnetworks/proxy-subnet
    state: READY
    

建立閘道

Gateway 資源代表 Kubernetes 中轉送流量的資料層。視衍生自的 GatewayClass 而定,Gateway 可以代表多種不同的負載平衡和路由。如要進一步瞭解 Gateway 資源,請參閱閘道資源說明或 API 規格

在本例中,GKE 叢集管理員想建立 Gateway,供不同團隊用來在內部公開應用程式。管理員會部署 Gateway,應用程式團隊則會獨立部署自己的路徑,並將其附加至這個 Gateway。

  1. 將下列 Gateway 資訊清單儲存至名為 gateway.yaml 的檔案:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-http
    spec:
      gatewayClassName: gke-l7-rilb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
    

    這個資訊清單包含下列欄位:

    • gatewayClassName: gke-l7-rilb:指定這個 Gateway 衍生自的 GatewayClass。gke-l7-rilb 對應於內部應用程式負載平衡器。
    • port: 80:指定 Gateway 只公開通訊埠 80,用於監聽 HTTP 流量。

    這個閘道已設為僅處理通訊埠 80 的 HTTP 流量。根據預設,這項服務不支援 HTTPS (通訊埠 443),如果嘗試透過 HTTPS 連線,要求可能會失敗。

  2. 在叢集中部署閘道:

    kubectl apply -f gateway.yaml
    
  3. 確認閘道已正確部署。部署所有資源可能需要幾分鐘的時間。

    kubectl describe gateways.gateway.networking.k8s.io internal-http
    

    輸出結果會與下列內容相似:

    Name:         internal-http
    Namespace:    default
    Spec:
      Gateway Class Name:  gke-l7-rilb
      Listeners:
        Allowed Routes:
          Kinds:
            Group:  gateway.networking.k8s.io
            Kind:   HTTPRoute
          Namespaces:
            From:  Same
        Name:      http
        Port:      80
        Protocol:  HTTP
     Status:
       Addresses:
         Type:   IPAddress
         Value:  192.168.1.14
       Conditions:
         Last Transition Time:  2025-03-19T19:53:46Z
         Message:               The OSS Gateway API has deprecated this condition, do not depend on it.
         Observed Generation:   1
         Reason:                Scheduled
         Status:                True
         Type:                  Scheduled
         Last Transition Time:  2025-03-19T19:53:46Z
         Message:
         Observed Generation:   1
         Reason:                Accepted
         Status:                True
         Type:                  Accepted
         Last Transition Time:  2025-03-19T19:53:46Z
         Message:
         Observed Generation:   1
         Reason:                Programmed
         Status:                True
         Type:                  Programmed
         Last Transition Time:  2025-03-19T19:53:46Z
         Message:               The OSS Gateway API has altered the "Ready" condition semantics and reserved it for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.
         Observed Generation:   1
         Reason:                Ready
         Status:                True
         Type:                  Ready
         Last Transition Time:  2025-03-19T19:53:46Z
         Message:
         Observed Generation:   1
         Reason:                Healthy
         Status:                True
         Type:                  networking.gke.io/GatewayHealthy
    Events:
      Type    Reason  Age                From                       Message
      ----    ------  ----               ----                       -------
      Normal  ADD     92s                networking.gke.io/gateway  test/internal-http
      Normal  UPDATE  45s (x3 over 91s)  networking.gke.io/gateway  test/internal-http
      Normal  SYNC    45s                networking.gke.io/gateway  SYNC on test/internal-http was a success
    

    此時,叢集中已部署 Gateway,並已佈建負載平衡器和 IP 位址。不過,Gateway 沒有任何 Route,因此不知道如何將流量傳送至後端。如果沒有路由,所有流量都會導向預設後端,並傳回 HTTP 404。 接著,您會部署應用程式和路徑,這些路徑會告知閘道如何連線至應用程式後端。

部署試用版應用程式

應用程式團隊可以獨立部署應用程式和路徑,不必等待閘道部署完成。在某些情況下,應用程式團隊可能也想擁有 Gateway,並自行部署為專用於其應用程式的資源。如要瞭解閘道和路徑的不同擁有權模式,請參閱路徑繫結。不過在本範例中,商店團隊會部署應用程式和隨附的 HTTPRoute,透過上一節建立的 internal-http Gateway 公開應用程式。

HTTPRoute 資源有許多可設定的欄位,用於比對流量。如需 HTTPRoute 欄位的說明,請參閱 API 規格

  1. 將商店應用程式 (store-v1、store-v2 和 store-german 部署作業) 部署至叢集:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
    

    這會建立三個 Deployment 物件和三個 Service 物件,分別命名為 store-v1、store-v2 和 store-german。

  2. 確認應用程式部署成功:

    kubectl get pod
    

    應用程式執行後,輸出內容會與下列內容相似:

    NAME                        READY   STATUS    RESTARTS   AGE
    store-german-66dcb75977-5gr2n   1/1     Running   0          38s
    store-v1-65b47557df-jkjbm       1/1     Running   0          14m
    store-v2-6856f59f7f-sq889       1/1     Running   0          14m
    
  3. 確認服務已部署:

    kubectl get service
    

    輸出內容會顯示每個商店 Deployment 的 Service:

    NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    store-german   ClusterIP   10.48.3.183   <none>        8080/TCP   4s
    store-v1       ClusterIP   10.48.2.224   <none>        8080/TCP   5s
    store-v2       ClusterIP   10.48.4.48    <none>        8080/TCP   5s
    

部署 HTTPRoute

路由資源會定義通訊協定專屬規則,用於將流量從閘道對應至 Kubernetes 後端。HTTPRoute 資源會比對及篩選 HTTP 和 HTTPS 流量,且所有 gke-l7 GatewayClass 皆支援這項資源。

在本節中,您將部署 HTTPRoute,並透過路由規則設定 Gateway,以便連線至商店應用程式。

  1. 將下列 HTTPRoute 資訊清單儲存到名為 store-route.yaml 的檔案:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-v1
          port: 8080
      - matches:
        - headers:
          - name: env
            value: canary
        backendRefs:
        - name: store-v2
          port: 8080
      - matches:
        - path:
            value: /de
        backendRefs:
        - name: store-german
          port: 8080
    
  2. 在叢集中部署 HTTProute:

    kubectl apply -f store-route.yaml
    

    store HTTPRoute 會使用 parentRefs 屬性繫結至 internal-http Gateway。這些轉送規則會設定在基礎負載平衡器上,如下圖所示:

    商店 HTTPRoute 設定的轉送規則

    這些轉送規則會以以下方式處理 HTTP 流量:

    • 傳送至 store.example.com/de 的流量會轉送至服務 store-german
    • 如果傳送至 store.example.com 的流量包含 HTTP 標頭 "env: canary",就會導向服務 store-v2
    • 其餘傳送至 store.example.com 的流量會導向服務 store-v1
  3. 確認 HTTPRoute 是否已部署:

    kubectl describe httproute store
    

    輸出結果會與下列內容相似:

    Name:         store
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         HTTPRoute
    <...>
    Spec:
      Hostnames:
        store.example.com
      Parent Refs:
        Group:  gateway.networking.k8s.io
        Kind:   Gateway
        Name:   internal-http
      Rules:
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v1
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v2
          Port:    8080
          Weight:  1
        Matches:
          Headers:
            Name:   env
            Type:   Exact
            Value:  canary
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-german
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /de
    Status:
      Parents:
        Conditions:
          Last Transition Time:  2022-11-01T04:18:52Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2022-11-01T04:18:52Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   internal-http
    Events:
      Type    Reason  Age                From                   Message
      ----    ------  ----               ----                   -------
      Normal  ADD     24m                sc-gateway-controller  default/store
      Normal  SYNC    16m (x4 over 23m)  sc-gateway-controller  Bind of HTTPRoute "default/store" to ParentRef {Group:       gateway.networking.k8s.io",
      <...>
    
  4. 確認 HTTPRoute 是否繫結至 Gateway:

    kubectl describe gateway
    

    輸出結果會與下列內容相似:

    Name:         internal-http
    Namespace:    default
    Labels:       <none>
    <...>
    Status:
      Addresses:
        Type:   IPAddress
        Value:  10.128.15.203
      Conditions:
        Last Transition Time:  2022-11-01T03:47:01Z
        Message:
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2022-11-01T03:47:01Z
        Message:
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2022-11-01T03:47:01Z
          Message:
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    http
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
          <...>
    

將流量傳送至應用程式

Gateway、Route 和應用程式現已部署至叢集,您可以將流量傳遞至應用程式。閘道已設定為僅在通訊埠 80 上提供 HTTP 流量。除非已另外設定 TLS,否則使用 HTTPS 提出的要求可能會失敗。

  1. 從閘道擷取 IP 位址,以便將流量傳送至應用程式:

    kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}"
    

    輸出內容為 IP 位址。

  2. 從可連線至叢集的虛擬機器 (VM) 執行個體,透過 Shell 將流量傳送至這個 IP 位址。您可以建立 VM 來達成這個目的。這是必要步驟,因為閘道具有內部 IP 位址,且只能從虛擬私有雲網路內部存取。由於 internal-http 是區域負載平衡器,用戶端殼層必須與 GKE 叢集位於相同區域。

    向 store.example.com 發出要求:

    curl http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
    

    GATEWAY_IP_ADDRESS 替換為上一步的 IP 位址。

    示範應用程式的輸出內容會顯示應用程式執行所在位置的相關資訊:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v1-84b47c7f58-pmgmk",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:31:17",
      "zone": "ZONE_NAME"
    }
    
  3. 前往 store.example.com/de 商店服務的德文版本,測試路徑比對:

    curl http://store.example.com/de --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
    

    輸出內容會確認要求是由 store-german Pod 處理:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "Gutentag!", 
      "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal",
      "pod_name": "store-german-5cb6474c55-lq5pl", 
      "pod_name_emoji": "🧞‍♀",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:35:37",
      "zone": "ZONE_NAME"
    }
    
  4. 最後,使用 env: canary HTTP 標頭將流量傳送至商店服務的 Canary 版本:

    curl -H "env: canary" http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
    

    輸出內容會確認要求是由 store-v2 Pod 處理:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v2", 
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v2-5788476cbd-s9thb", 
      "pod_name_emoji": "🦰",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:38:26",
      "zone": "ZONE_NAME"
    }
    

部署外部閘道

外部閘道會公開可從網際網路或虛擬私有雲外部網路存取的應用程式。部署作業與內部閘道部署作業類似,但您必須保護應用程式安全,因為公開網際網路可存取閘道。

您可以建立全球外部閘道或區域外部閘道,這兩種方式都能建立外部閘道。

全域外部閘道會使用全域 IP 位址 (或任一傳播 IP 位址),做為在所有 Google Cloud Compute 區域中宣傳的閘道前端。將流量傳送至這個任播 IP 位址的用戶端,會轉送至 IP 播送位置最近的 Google 位置。全域外部閘道僅適用於進階網路服務級別

區域外部閘道會使用區域 IP 做為閘道前端,且只會在部署區域外部閘道的本機 Google Cloud Compute 地區中宣傳。用戶端將流量傳送至這個區域 IP 位址時,流量會先由當地 ISP 透過網際網路傳送,再抵達 IP 位址的 Google 區域。區域外部閘道僅適用於標準網路服務級別

部署全域外部閘道

以下範例說明如何使用 Certificate Manager 和 HTTPRoute,公開商店應用程式,並將多個憑證附加至全域外部 Gateway,然後分組至憑證對應。

建立憑證對應關係

如果每個閘道需要 15 個以上的憑證,或需要使用萬用字元憑證,Google 建議使用 Certificate Manager 管理憑證。

您也可以使用 Kubernetes Secret 或 Google 代管的 SSL 憑證,保護外部 Gateway。詳情請參閱「閘道安全性」。

在本節中,您將使用 Certificate Manager 建立憑證,確保叢集上執行的應用程式安全無虞。

  1. 啟用 Certificate Manager API:

    gcloud services enable certificatemanager.googleapis.com
    
  2. 建立憑證對應關係:

    gcloud beta certificate-manager maps create store-example-com-map
    
  3. 將 Google 代管的憑證和金鑰載入憑證:

    gcloud beta certificate-manager certificates create store-example-com-cert \
        --certificate-file="CERTIFICATE_FILE" \
        --private-key-file="PRIVATE_KEY_FILE"
    

    更改下列內容:

    • CERTIFICATE_FILE:憑證檔案名稱。檔案的副檔名必須為 .pem。例如:cert.pem
    • PRIVATE_KEY_FILE:私密金鑰檔案名稱。

    詳情請參閱「建立私密金鑰和憑證」。

  4. 建立 CertificateMapEntry,將憑證指派給憑證對應:

    gcloud beta certificate-manager maps entries create store-example-com-map-entry \
        --map=store-example-com-map \
        --hostname=store.example.com \
        --certificates=store-example-com-cert
    

如要瞭解如何使用其他憑證來源 (例如 Kubernetes Secret 或 SSL 憑證) 保護 Gateway,請參閱「保護 Gateway」。

建立閘道

Gateway 資源代表 Kubernetes 中轉送流量的資料層。Gateway 可代表多種負載平衡和路由,具體取決於使用的 GatewayClass。

如要進一步瞭解 Gateway 資源,請參閱 Gateway 資源說明或 API 規格

在本節中,您將建立閘道。應用程式團隊可以部署獨立的路徑,並安全地將其附加至閘道,藉此透過閘道將應用程式公開至網際網路。

  1. 將下列資訊清單儲存到名為 gateway.yaml 的檔案:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: external-http
      annotations:
        networking.gke.io/certmap: store-example-com-map
    spec:
      gatewayClassName: gke-l7-global-external-managed
      listeners:
      - name: https
        protocol: HTTPS
        port: 443
    
    

    這個資訊清單說明具有下列欄位的 Gateway:

    • gatewayClassName: gke-l7-global-external-managed:指定這個閘道的 GatewayClass。這個閘道類別使用全域外部應用程式負載平衡器。
    • protocol: HTTPSport: 443:指定閘道公開通訊埠 443,以處理 HTTPS 流量。這些欄位會啟用 TLS。
    • networking.gke.io/certmap: store-example-com-map:指定 Certificate Manager 中憑證對應的名稱。

    由於 TLS 是透過 Certificate Manager 設定,因此沒有 TLS 區段。設定時使用 networking.gke.io/certmap 註解。

  2. 將資訊清單套用至叢集:

    kubectl apply -f gateway.yaml
    

    GKE 可能需要幾分鐘的時間才能部署資源。

  3. 確認閘道已成功部署:

    kubectl describe gateway
    

    輸出結果會與下列內容相似:

    Name:         external-http
    Namespace:    default
    Labels:       <none>
    ...
    Spec:
      Gateway Class Name:  gke-l7-global-external-managed
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      https
        Port:      443
        Protocol:  HTTPS
        Tls:
          Certificate Refs:
            Group:
            Kind:   Secret
            Name:   store-example-com
          Mode:     Terminate
     ...
    

    這項輸出內容顯示叢集中部署的 Gateway 具有負載平衡器和公開 IP 位址。閘道沒有任何路徑,因此無法將流量傳送至後端。如果沒有路徑,所有流量都會導向預設後端,並傳回 HTTP 404 回應。在下一節中,您將部署「路由」,指示閘道將流量傳送至後端。

部署試用版應用程式

應用程式團隊可以獨立部署應用程式和路徑,不必等待閘道部署完成。在某些情況下,應用程式團隊可能也想擁有 Gateway,並自行部署為應用程式專用的資源。如要瞭解閘道和路徑的不同擁有權模式,請參閱路徑繫結。在本範例中,商店團隊會部署應用程式和隨附的 HTTPRoute,透過上一節建立的 external-http Gateway 公開應用程式。

如要進一步瞭解 HTTPRoute 欄位,請參閱 API 規格

  1. 將範例應用程式部署至叢集:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
    

    這個範例應用程式會建立三個 Deployment 和三個 Service,分別命名為 store-v1store-v2store-german

  2. 確認應用程式已成功部署:

    kubectl get pod
    

    輸出結果會與下列內容相似:

    NAME                            READY   STATUS    RESTARTS   AGE
    store-german-66dcb75977-5gr2n   1/1     Running   0          38s
    store-v1-65b47557df-jkjbm       1/1     Running   0          14m
    store-v2-6856f59f7f-sq889       1/1     Running   0          14m
    
  3. 確認服務是否已成功部署:

    kubectl get service
    

    輸出結果會與下列內容相似:

    NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    store-german   ClusterIP   10.48.3.183   <none>        8080/TCP   4s
    store-v1       ClusterIP   10.48.2.224   <none>        8080/TCP   5s
    store-v2       ClusterIP   10.48.4.48    <none>        8080/TCP   5s
    

建立 HTTPRoute

路由資源會定義通訊協定專屬規則,用於將流量從閘道對應至 Kubernetes 後端。HTTPRoute 資源會比對及篩選 HTTP 和 HTTPS 流量,所有 gke-l7-* GatewayClass 都支援這項資源。

在本節中,您將部署 HTTPRoute,並使用連線至範例應用程式所需的路由規則設定 Gateway。

  1. 將下列資訊清單儲存到名為 store-route-external.yaml 的檔案:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-external
    spec:
      parentRefs:
      - kind: Gateway
        name: external-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-v1
          port: 8080
      - matches:
        - headers:
          - name: env
            value: canary
        backendRefs:
        - name: store-v2
          port: 8080
      - matches:
        - path:
            value: /de
        backendRefs:
        - name: store-german
          port: 8080
    

    這個資訊清單說明參照 external-http 閘道的 HTTPRoute。

  2. 將資訊清單套用至叢集:

    kubectl apply -f store-route-external.yaml
    

    store HTTPRoute 會使用 parentRefs 屬性繫結至 external-http Gateway。下圖顯示在基礎負載平衡器上設定的路由規則:

    商店 HTTPRoute 設定的轉送規則

    轉送規則會依下列方式處理 HTTP 流量:

    • 流量會透過 store.example.com/de 路由傳送至服務 store-german
    • HTTP 標頭為 "env: canary"store.example.com 流量會路由至服務 store-v2
    • 其餘流量會轉送至服務 store-v1store.example.com
  3. 確認 HTTPRoute 是否已部署:

    kubectl describe httproute store-external
    

    輸出結果會與下列內容相似:

    Name:         store-external
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         HTTPRoute
    <...>
    Spec:
      Hostnames:
        store.example.com
      Parent Refs:
        Group:  gateway.networking.k8s.io
        Kind:   Gateway
        Name:   external-http
      Rules:
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v1
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v2
          Port:    8080
          Weight:  1
        Matches:
          Headers:
            Name:   env
            Type:   Exact
            Value:  canary
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-german
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /de
    Status:
      Parents:
        Conditions:
          Last Transition Time:  2022-11-01T05:42:31Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2022-11-01T05:43:18Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   external-http
    Events:
      Type     Reason  Age    From                   Message
      ----     ------  ----   ----                   -------
      Normal   ADD     2m48s  sc-gateway-controller  default/store-external
      Normal  SYNC  61s (x3 over 2m27s)  sc-gateway-controller  Bind of HTTPRoute "default/store-external" to ParentRef Group:       "gateway.networking.k8s.io",
      ...
    
  4. 確認 HTTPRoute 是否繫結至 Gateway:

    kubectl describe gateway external-http
    

    輸出結果會與下列內容相似:

    Name:         external-http
    Namespace:    default
    Labels:       <none>
    <...>
    Status:
      Addresses:
        Type:   IPAddress
        Value:  34.149.207.45
      Conditions:
        Last Transition Time:  2022-11-01T05:37:21Z
        Message:
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2022-11-01T05:43:18Z
        Message:
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2022-11-01T05:43:18Z
          Message:
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    https
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
          <...>
    

將流量傳送至應用程式

閘道、路徑和應用程式現已部署至叢集,您可以將流量傳遞至應用程式。

  1. 取得閘道的 IP 位址:

    kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}"
    

    輸出內容為 IP 位址。

  2. 建立 VM:

    gcloud cloud-shell ssh
    
  3. 從 VM 將流量傳送至閘道 IP 位址。由於您不擁有 example.com 主機名稱,因此必須手動設定主機標頭。

    curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
    

    GATEWAY_IP_ADDRESS 替換為上一步中閘道的 IP 位址。

    cacert.pem:您產生的憑證檔案。您必須將這個檔案儲存在用來連線至閘道的電腦上。

    輸出內容會顯示試用版應用程式的相關資訊,包括應用程式的執行位置:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v1-84b47c7f58-pmgmk",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:31:17",
      "zone": "us-central1-a"
    }
    
  4. 前往 store.example.com/de 上的德文版 store 服務,測試路徑比對:

    curl https://store.example.com/de --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
    

    輸出內容會確認要求是由 store-german Pod 處理:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "Gutentag!",
      "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal",
      "pod_name": "store-german-5cb6474c55-lq5pl",
      "pod_name_emoji": "🧞‍♀",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:35:37",
      "zone": "us-central1-a"
    }
    
  5. 使用 env: canary HTTP 標頭,將流量傳送至 store 服務的 Canary 版本:

    curl -H "env: canary" https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
    

    輸出內容會確認要求是由 store-v2 Pod 處理:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v2",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v2-5788476cbd-s9thb",
      "pod_name_emoji": "👩🏿",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:38:26",
      "zone": "us-central1-a"
    }
    

部署區域外部閘道

以下範例說明如何使用自管憑證和 HTTPRoute,公開商店應用程式,並將多個憑證附加至區域外部閘道。

為地區閘道建立 Proxy 子網路

建立使用區域外部應用程式負載平衡器的閘道之前,請務必設定僅限 Proxy 的子網路。在您使用區域外部應用程式負載平衡器的虛擬私有雲中,每個區域都必須有 external_managed_proxy 子網路。這個子網路會為負載平衡器 Proxy 提供內部 IP 位址。

建立憑證,確保用戶端流量安全

您可以使用憑證授權單位 (CA) 核發及驗證的憑證,也可以建立自行簽署的憑證。如要進一步瞭解如何建立憑證,請參閱「在 Kubernetes Secret 中儲存憑證」。

區域性閘道不支援 CertificateMap 或 Google 代管的 SSL 憑證。使用自行管理的區域 SSL 憑證或密鑰,確保用戶端與區域閘道之間的流量安全。如要進一步瞭解憑證和負載平衡器,請參閱「憑證和負載平衡器 Google Cloud 」 Google Cloud

建立區域型外部 HTTP(S) 閘道

  1. 為外部負載平衡器建立區域靜態 IP 位址。

    gcloud compute addresses create IP_ADDRESS_NAME \
      --region=COMPUTE_REGION \
      --network-tier=STANDARD
    

    更改下列內容:

    • IP_ADDRESS_NAME:新靜態 IP 位址的名稱。
    • COMPUTE_REGION:叢集執行的 Compute Engine 區域。
  2. 使用自行管理的憑證建立區域外部應用程式負載平衡器閘道,如下所示,並將資訊清單儲存為 regional-gateway.yaml

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: external-regional-http
      spec:
        gatewayClassName: gke-l7-regional-external-managed
        listeners:
        - name: https
          protocol: HTTPS
          port: 443
          tls:
            mode: Terminate
            certificateRefs:
            - name: store-example-com
        addresses:
        - type: NamedAddress
          value: IP_ADDRESS_NAME
    
  3. 套用 regional-gateway 資訊清單:

      kubectl apply -f regional-gateway.yaml
    
  4. 驗證設定。

      kubectl get gateway
    

    輸出結果會與下列內容相似:

    NAME            CLASS                              ADDRESS         READY   AGE
    external-http   gke-l7-regional-external-managed   35.118.32.224   True    49s
    

    如要取得更多詳細資料,請使用 describe 指令:

    kubectl describe gateway
    

    輸出結果會與下列內容相似:

    Name:         external-regional-http
    Namespace:    default
    Labels:       <none>
    ...
    Spec:
      Gateway Class Name:  gke-l7-regional-external-managed
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      https
        Port:      443
        Protocol:  HTTPS
        Tls:
          Certificate Refs:
            Group:
            Kind:   Secret
            Name:   store-example-com
          Mode:     Terminate
      ...
    

部署示範應用程式

您可以獨立部署應用程式和路徑,不必部署閘道。

如要進一步瞭解如何部署示範應用程式,請參閱「部署示範應用程式」。

建立 HTTPRoute

您必須建立 HTTPRoute,才能比對及篩選 HTTP 和 HTTPS 流量。

將流量傳送至應用程式

部署應用程式並建立 HTTPRoute 後,您就可以將流量傳遞至應用程式。

如要進一步瞭解如何將流量傳送至應用程式,請參閱「將流量傳送至應用程式」。

使用共用閘道

Gateway API 會使用不同的資源 (閘道和路徑資源) 部署負載平衡器和轉送規則。這與 Ingress 不同,後者會將所有內容合併為單一資源。透過在資源之間分配責任,Gateway 可讓負載平衡器及其轉送規則分別部署,並由不同使用者或團隊部署。這可讓閘道成為共用閘道,並附加許多不同的路徑,即使跨越不同命名空間,也能由獨立團隊完全擁有及管理。

針對共用閘道部署路徑

本範例以「部署內部閘道」中部署的 internal-http 閘道為基礎。

在這個範例中,網站團隊會部署應用程式、服務和 HTTPRoute,將來自 Gateway 的流量比對至這些服務。

  1. 部署範例應用程式:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/site.yaml
    
  2. 將下列資訊清單儲存到名為 site-route-internal.yaml 的檔案:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: site-internal
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "site.example.com"
      rules:
      - backendRefs:
        - name: site-v1
          port: 8080
    

    這個資訊清單說明 HTTPRoute,該 HTTPRoute 會比對所有流量,並將流量導向 site-v1 服務。site.example.com

  3. 將資訊清單套用至叢集:

    kubectl apply -f site-route-internal.yaml
    
  4. 確認 HTTPRoute 已附加至 Gateway:

    kubectl describe httproute.gateway.networking.k8s.io site-internal
    

    輸出結果會與下列內容相似:

    Status:
      Parents:
        Conditions:
          Last Transition Time:  2023-01-09T15:05:43Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2023-01-09T15:05:43Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   internal-http
          ...
    

    如果 Gateway 的 Accepted 條件為 True,表示 HTTPRoute 已成功繫結至 Gateway。如要進一步瞭解「狀態」欄位,請參閱路線狀態

  5. 確認流量已正確轉送至閘道:

    curl -H "host: site.example.com" GATEWAY_IP_ADDRESS
    curl -H "host: store.example.com" GATEWAY_IP_ADDRESS
    

    GATEWAY_IP_ADDRESS 替換為內部閘道的 IP 位址。

    您必須使用與閘道位於相同虛擬私有雲的虛擬機器 (VM)。

    輸出結果會與下列內容相似:

    {
      "cluster_name": "CLUSTER_NAME",
      "host_header": "site.example.com",
      "metadata": "site-v1",
      "pod_name": "site-v1-5d64fc4d7d-fz6f6",
      "pod_name_emoji": "👩🏼‍🍳",
      "project_id": "PROJECT_ID",
      "timestamp": "2022-11-02T19:07:01",
      "zone": "ZONE_NAME"
    }
    ...
    {
      "cluster_name": "CLUSTER_NAME",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "pod_name": "store-v1-6d8d58d78-vz8pn",
      "pod_name_emoji": "🧝🏻‍♂️",
      "project_id": "PROJECT_ID",
      "timestamp": "2022-11-02T19:07:01",
      "zone": "ZONE_NAME"
    }
    

設定 Gateway 預設後端

所有 gke-l7-* GatewayClass 都會針對不相符的流量傳回 HTTP 404。您可以透過明確的預設路徑設定預設後端,將不相符的流量傳送至使用者提供的服務。

即使沒有明確的後端定義,閘道也會設定為處理 404 (找不到) 和 500 (伺服器錯誤) 等錯誤代碼。預設行為可能因 Gateway 實作方式而異。如要進一步控管錯誤處理程序,建議您設定自訂後端。

以下 HTTPRoute 範例說明如何自訂預設後端。 如果您套用類似下列的 HTTPRoute,系統會優先採用該路由,而非隱含的預設後端:

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
  name: custom-default-backend
spec:
  parentRefs:
  - kind: Gateway
    name: my-internal-gateway
  rules:
  - backendRefs:
    - name: my-custom-default-backend-service
      port: 8080

這項 HTTPRoute 會比對特定閘道的所有流量。每個閘道只能有一條這類規則,否則規則會發生衝突,並套用優先順序

您可以透過預設後端,防止使用者建立預設路徑後端,將所有閘道流量轉送至該後端。如果新的 HTTPRoute 與現有 HTTPRoute 的轉送規則相衝突,系統一律會優先採用現有 HTTPRoute。

為閘道設定靜態 IP 位址

每個閘道都有一個 IP 位址,用來監聽流量。如果您未在閘道上指定 IP 位址,閘道控制器會自動提供 IP 位址。您也可以建立靜態 IP 位址,讓 IP 位址獨立於閘道生命週期存在。

部署閘道後,狀態欄位會顯示其 IP 位址:

kind: Gateway
...
status:
  addresses:
    - value: 10.15.32.3

視 GatewayClass 而定,系統會從下列子網路分配 IP 位址:

GatewayClasses 預設 IP 位址集區
  • gke-l7-rilb
  • gke-l7-rilb-mc
  • 主要節點 IPv4/IPv6 位址範圍的區域性私人 IP 位址
  • gke-l7-regional-external-managed
  • gke-l7-regional-external-managed-mc
  • Google 區域外部 IPv4/IPv6 範圍的區域公開 IP 位址
  • gke-l7-global-external-managed
  • gke-l7-global-external-managed-mc
  • gke-l7-gxlb
  • gke-l7-gxlb-mc
  • Google 全域外部 IPv4/IPv6 範圍的全域公開 IP 位址

    您可以在 addresses.NamedAddress 欄位中指定 IP 位址,不必與閘道相關。您可以在部署 Gateway 之前建立靜態 IP 位址資源,該資源會由 NamedAddress 參照。即使閘道遭到刪除,您仍可重複使用靜態 IP 位址。

    使用已命名的 IP 位址

    您可以指定 NamedAddress 來設定 IPv4 或 IPv6 位址。您必須先佈建靜態 IP 位址,才能建立閘道。

    1. 建立靜態 IP 位址資源:

      gcloud compute addresses create IP_ADDRESS_NAME \
          --purpose=SHARED_LOADBALANCER_VIP \
          --region=COMPUTE_REGION \
          --subnet=SUBNET \
          --project=PROJECT_ID
      

      更改下列內容:

      • IP_ADDRESS_NAME:新靜態 IP 位址的名稱
      • COMPUTE_REGION:如果是區域閘道,則為叢集執行的 Compute Engine 區域。全域外部閘道不需要這個旗標。
      • SUBNET:IP 位址的子網路。全域外部閘道不需要這個旗標。
      • PROJECT_ID:執行 GKE 叢集的專案。
    2. 將下列資訊清單儲存到名為 named-ip-gateway.yaml 的檔案:

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: internal-http
      spec:
        gatewayClassName: gke-l7-rilb
        listeners:
        - name: http
          protocol: HTTP
          port: 80
        addresses:
        - type: NamedAddress
          value: IP_ADDRESS_NAME
      

      這個資訊清單說明參照具名 IP 位址的閘道。

    3. 將資訊清單套用至叢集:

      kubectl apply -f named-ip-gateway.yaml
      
    4. 驗證閘道 IP 位址:

      kubectl describe gateway internal-http
      

      輸出結果會與下列內容相似:

      Name:         internal-http
      Namespace:    default
      Labels:       <none>
      ...
      Spec:
        Addresses:
          Type:              NamedAddress
          Value:             IP_ADDRESS_NAME
        Gateway Class Name:  gke-l7-rilb
        Listeners:
          Allowed Routes:
            Namespaces:
              From:  Same
          Name:      http
          Port:      80
          Protocol:  HTTP
      Status:
        Addresses:
          Type:   IPAddress
          Value:  10.15.32.103
      

    設定 HTTP 至 HTTPS 的重新導向

    Cloud Load Balancing 提供從 HTTP 重新導向至 HTTPS 的功能。外部應用程式負載平衡器會將未加密的 HTTP 要求重新導向至使用相同 IP 位址的 HTTPS 負載平衡器。建立 Gateway 時,如果啟用 HTTP 重新導向至 HTTPS 的功能,系統會自動建立這兩個負載平衡器。系統會自動將通訊埠 80 上閘道外部 IP 位址的要求,重新導向至通訊埠 443 上的相同外部 IP 位址。

    根據預設,閘道不會定義 HTTP 至 HTTPS 的重新導向。

    如要將 HTTP 流量重新導向至 HTTPS,請設定 Gateway 來處理 HTTP 和 HTTPS 流量。如果停用 HTTP 或 HTTPS,閘道就不會重新導向流量。

    以下範例說明如何使用 HTTP 到 HTTPS 的重新導向,確保從用戶端前往網路應用程式的流量一律重新導向至安全網頁。

    gke-l7-gxlbgke-l7-gxlb-mc GatewayClass 不支援 HTTP 至 HTTPS 的重新導向。如要進一步瞭解各 GatewayClass 支援的不同功能,請參閱「GatewayClass 功能」。

    從基礎架構命名空間重新導向 HTTP 流量

    在某些情況下,基礎架構或平台管理團隊與應用程式團隊之間沒有明確區別,因此防止 Gateway 遭到濫用可能會是一項挑戰。

    下列範例進一步限制 HTTP 監聽器的使用,防止應用程式團隊無意間使用不安全的通訊協定。這個範例會設定 Gateway,只允許 HTTPRoute 在路徑位於特定命名空間 (http-redirect) 時使用 HTTP 監聽器,同時向所有命名空間開放 HTTPS 監聽器。您可以使用 Kubernetes RBAC 限制 http-redirect 命名空間,避免應用程式團隊不慎在這個命名空間中建立 HTTPRoute。

    1. 建立閘道的命名空間。將資訊清單儲存為 gateway-namespace.yaml

      apiVersion: v1
      kind: Namespace
      metadata:
        name: gateway-infra
      
    2. 套用資訊清單:

      kubectl apply -f gateway-namespace.yaml
      
    3. 建立 Gateway 的命名空間,並將資訊清單儲存為 redirect-namespace.yaml

      apiVersion: v1
      kind: Namespace
      metadata:
        name: http-redirect
        labels:
          otherInfra: httpToHttps
      
      • 這個命名空間已設定特定標籤。
    4. 套用資訊清單:

      kubectl apply -f redirect-namespace.yaml
      
    5. 如要限制 http 接聽程式的使用,請使用下列資訊清單建立 Gateway。將資訊清單儲存為 external-gateway.yaml

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: external-http
        namespace: gateway-infra
      spec:
        gatewayClassName: gke-l7-global-external-managed
        listeners:
        - name: http
          protocol: HTTP
          port: 80
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: Selector
              selector:
                matchLabels:
                  otherInfra: httpToHttps
        - name: https
          protocol: HTTPS
          port: 443
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: All
          tls:
            mode: Terminate
            options:
              networking.gke.io/pre-shared-certs: store-example-com
        ```
      
      • namespace 欄位會指定在 gateway-infra 命名空間中建立 Gateway。

      • allowedRoutes 區段中的 namespaces 欄位會將 http 監聽器限制為與標籤 otherInfra: httpToHttps 相符的命名空間。

    6. 套用資訊清單:

      kubectl apply -f external-gateway.yaml
      
    7. 如要強制執行 HTTPS 重新導向,請使用下列資訊清單建立預設 HTTPRoute。將資訊清單儲存為 http-redirect.yaml

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: redirect
        namespace: http-redirect
      spec:
        parentRefs:
        - namespace: gateway-infra
          name: external-http
          sectionName: http
        rules:
        - filters:
          - type: RequestRedirect
            requestRedirect:
              scheme: https
      
      • sectionName 欄位會指示 Gateway 僅比對 http 接聽程式。RequestRedirect 篩選器會強制重新導向至 https 監聽器。
    8. 套用資訊清單:

      kubectl apply -f http-redirect.yaml
      
    9. 使用下列資訊清單為應用程式建立 Service。將資訊清單儲存為 service-deployment.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: store-v1
      spec:
        selector:
          app: store
          version: v1
        ports:
        - port: 8080
          targetPort: 8080
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: store-v1
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: store
            version: v1
        template:
          metadata:
            labels:
              app: store
              version: v1
          spec:
            containers:
            - name: whereami
              image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1
              ports:
              - containerPort: 8080
              env:
              - name: METADATA
                value: "store-v1"
      
    10. 套用資訊清單:

      kubectl apply -f service-deployment.yaml
      
    11. 使用下列資訊清單,為僅允許 HTTPS 的應用程式建立 HTTPRoute。將資訊清單儲存為 http-route.yaml

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: store-external
        labels:
          gateway: external-http
      spec:
        parentRefs:
        - name: external-http
          namespace: gateway-infra
          sectionName: https
        hostnames:
        - "store.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
      
    12. 套用資訊清單:

      kubectl apply -f http-route.yaml
      

    設定路徑重新導向和網址重新編寫

    路徑重新導向是指將傳入要求從一個網址路徑重新導向至另一個路徑。路徑重新導向可讓您在處理過時或已淘汰的網址時,變更網址結構。

    網址重寫 有助於在伺服器處理傳入網址前修改該網址。您可以藉此變更網址的結構或格式,但不會實際變更基礎內容或檔案結構。網址重寫有助於建立方便使用者和 SEO 的網址,方便記憶和理解。根據預設,系統不會設定路徑重新導向和網址重寫,您必須使用 HTTPRoute 中的篩選器,明確設定這些重新導向或重寫。

    GKE Gateway 支援路徑重新導向和網址重寫。詳情請參閱「HTTP 路徑重新導向和重寫」。

    設定路徑重新導向

    您可以設定路徑重新導向,取代網址中的完整路徑或前置字元。

    取代整個路徑

    1. 如要取代整個路徑,請在 HTTPRoute 中設定篩選器,將網址路徑中包含前置字串 /any-path 的任何網址,取代為嚴格值 /new-path

    2. 請按照下列方式建立 HTTPRoute 資訊清單,並命名為 store.yaml

        apiVersion: gateway.networking.k8s.io/v1beta1
        kind: HTTPRoute
        metadata:
          name: store
        spec:
          parentRefs:
            - kind: Gateway
              name: external-http
          hostnames:
          - store.example.com
          rules:
          - matches:
            - path:
                type: PathPrefix
                value: /any-path
            filters:
            - type: RequestRedirect
              requestRedirect:
                path:
                  type: ReplaceFullPath
                  replaceFullPath: /new-path
                statusCode: 302
      

      舉例來說,這份資訊清單會為 HTTPRoute 設定下列轉送規則:任何前往網址 https://store.example.com/any-path/... 的路徑都應重新導向至新位置 https://store.example.com/new-path/ (嚴格)。

    3. 套用資訊清單:

      kubectl apply -f store.yaml
      

    這項轉送規則會遵循嚴格的重新導向規則,也就是說,瀏覽器不會嘗試快取重新導向,而是重新導向至最新版本。

    僅替換前置字串

    1. 如要只取代前置字串,請在 HTTPRoute 中設定篩選器,將網址路徑中包含前置字串 /any-prefix 的任何網址,取代為嚴格值 /new-prefix

    2. 請按照下列方式建立 HTTPRoute 資訊清單,並命名為 store.yaml

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
        - matches:
            - path:
                type: PathPrefix
                value: /any-prefix
          filters:
          - type: RequestRedirect
            requestRedirect:
              path:
                type: ReplacePrefixMatch
                replacePrefixMatch: /new-prefix
              statusCode: 302
      

      舉例來說,這份資訊清單會為 HTTPRoute 設定下列轉送規則: 任何前往網址 https://store.example.com/any-path/v1/... 的路徑 都應重新導向至新位置 https://store.example.com/new-path/v1/... (僅限)。

    3. 套用資訊清單:

        kubectl apply -f store.yaml
      

    這項轉送規則會遵循唯一的重新導向規則,確保瀏覽器一律將您重新導向至預期網頁。

    設定網址重新編寫

    設定網址重寫,變更網址向使用者顯示的方式。您可以透過網址重寫功能,讓網址更方便使用者閱讀、提升 SEO 效果,或是將使用者重新導向至新網頁。

    重新編寫完整主機名稱

    如要重新編寫整個主機名稱:

    1. 在 HTTPRoute 中設定篩選器,指示 Gateway 將要求標頭中的 Host 資訊從 www.example.com 替換為 store.example.com,然後再將要求轉送至後端服務。

    2. 請按照下列方式建立 HTTPRoute 資訊清單,並命名為 www.yaml

        apiVersion: gateway.networking.k8s.io/v1beta1
        kind: HTTPRoute
        metadata:
          name: www
        spec:
          parentRefs:
            - kind: Gateway
              name: external-http
          hostnames:
          - www.example.com
          rules:
          - filters:
            - type: URLRewrite
              urlRewrite:
                hostname: store.example.com
            backendRefs:
            - name: store-v1
              port: 8080
      

      舉例來說,使用上述設定時,對 https://www.example.com 的任何要求都會轉送至後端服務,並使用 Host: store.example.com 標頭,而非 Host: www.example.com

    3. 套用資訊清單:

        kubectl apply -f www.yaml
      

    使用路徑修飾符重新編寫

    您可以將重寫功能與路徑修飾符合併使用,在將要求轉送至後端服務前,提供進階網址和路徑修改功能。

    如要使用路徑修飾符重新編寫,請按照下列步驟操作:

    1. 在 HTTPRoute 中設定篩選器,指示 Gateway 將要求標頭中的「Host」資訊從 www.example.com to store.example.com 替換為 /store,然後在將要求轉送至後端服務前,將值 /store 替換為 /

    2. 請按照下列方式建立 HTTPRoute 資訊清單,並命名為 www.yaml

        apiVersion: gateway.networking.k8s.io/v1beta1
        kind: HTTPRoute
        metadata:
          name: www
        spec:
          parentRefs:
            - kind: Gateway
              name: external-http
          hostnames:
          - www.example.com
          rules:
          - matches:
            - path:
                type: PathPrefix
                value: /store
            filters:
            - type: URLRewrite
              urlRewrite:
                hostname: store.example.com
                path:
                  type: ReplacePrefixMatch
                  replacePrefixMatch: /de
            backendRefs:
            - name: store-german
              port: 8080
      

      舉例來說,使用上述設定時,對 https://www.example.com/store/... 的任何要求都會轉送至後端服務,且要求標頭中會包含 Host: store.example.com (而非 Host: www.example.com),而 /store 會重新編寫為 /de

    3. 套用資訊清單:

      kubectl apply -f www.yaml
      

    驗證您的設定

    如要確認在建立含有網址重寫或路徑重新導向篩選器的 HTTPRoute 後,篩選器是否已套用,請執行下列操作:

    kubectl get httproute www -o yaml
    

    輸出結果會與下列內容相似:

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        annotations:
          kubectl.kubernetes.io/last-applied-configuration: |
            {"apiVersion":"gateway.networking.k8s.io/v1beta1","kind":"HTTPRoute","metadata":{"annotations":{},"name":"www","namespace":"default"},"spec":{"hostnames":["www.example.com"],"parentRefs":[{"kind":"Gateway","name":"external-http"}],"rules":[{"backendRefs":[{"name":"store-german","port":8080}],"filters":[{"type":"URLRewrite","urlRewrite":{"hostname":"store.example.com","path":{"replacePrefixMatch":"/de","type":"ReplacePrefixMatch"}}}],"matches":[{"path":{"type":"PathPrefix","value":"/store"}}]}]}}
        creationTimestamp: "2023-06-22T01:00:42Z"
        generation: 3
        name: www
        namespace: default
        resourceVersion: "51268631"
        uid: e516493e-806d-44d6-ae0d-1c9ff25682cf
      spec:
        hostnames:
        - www.example.com
        parentRefs:
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: external-http
        rules:
        - backendRefs:
          - group: ""
            kind: Service
            name: store-german
            port: 8080
            weight: 1
          filters:
          - type: URLRewrite
            urlRewrite:
              hostname: store.example.com
              path:
                replacePrefixMatch: /de
                type: ReplacePrefixMatch
          matches:
          - path:
              type: PathPrefix
              value: /store
      status:
        parents:
        - conditions:
          - lastTransitionTime: "2023-06-22T01:11:26Z"
            message: ""
            observedGeneration: 2
            reason: Accepted
            status: "True"
            type: Accepted
          - lastTransitionTime: "2023-06-22T01:11:26Z"
            message: ""
            observedGeneration: 2
            reason: ReconciliationSucceeded
            status: "True"
            type: Reconciled
          controllerName: networking.gke.io/gateway
          parentRef:
            group: gateway.networking.k8s.io
            kind: Gateway
            name: external-http
    
    

    如要取得更多詳細資料,請使用 describe 指令:

    kubectl describe httproute
    

    設定自訂要求和回應標頭

    自訂要求和回應標頭可讓您為 HTTP(S) 要求和回應指定其他標頭。視負載平衡器偵測到的資訊而定,這些標頭可能包含下列資訊:

    • 用戶端延遲時間
    • 用戶端 IP 位址的地理位置
    • TLS 連線的參數

    根據預設,傳送至後端服務或從後端服務接收的要求不會新增任何自訂標頭,您必須使用 HTTPRoute 中的篩選器,明確設定自訂標頭。

    如要設定自訂標頭,請在 HTTPRoute 的規則中新增篩選器區段,如下所示:

    設定自訂要求標頭

    使用 RequestHeaderModifier 篩選器建立 HTTPRoute 資訊清單,並儲存為 http-route-request.yaml:

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        <...>
        rules:
            filters:
              - type: RequestHeaderModifier
                requestHeaderModifier:
                  <...>
    

    套用資訊清單:

      kubectl apply -f http-route-request.yaml
    

    設定自訂回應標頭

    使用 ResponseHeaderModifier 篩選器建立 HTTPRoute 資訊清單,並儲存為 http-route-response.yaml:

    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: HTTPRoute
    metadata:
      name: store
    spec:
      <...>
      rules:
          filters:
            - type: ResponseHeaderModifier
              responseHeaderModifier:
                <...>
    

    套用資訊清單:

      kubectl apply -f http-route-response.yaml
    

    您可以新增、設定及移除標頭,詳情請參閱「Gateway API 實作」。您可以使用Google Cloud 支援的變數,透過自訂標頭設定 HTTPRoute。

    範例 1:

    如要設定 HTTPRoute,在將 HTTP 要求傳送至後端服務前,先將用戶端位置資訊新增至 HTTP 要求,請建立 HTTPRoute 資訊清單並命名為 external-http-request.yaml

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
          - matches:
            - path:
                type: PathPrefix
                value: /fr
            filters:
              - type: RequestHeaderModifier
                requestHeaderModifier:
                  add:
                    - name: X-Client-Geo-Location
                      value: "{client_region},{client_city}"
            backendRefs:
              - name: store-french
                port: 8080
    

    舉例來說,對於位於法國史特拉斯堡的用戶端,閘道會新增 X-Client-Geo-Location:FR,Strasbourg 標頭。

    範例 2:

    如要設定 HTTPRoute,加入自訂回應標頭來支援 HTTP 嚴格傳輸安全性,請建立 HTTPRoute 資訊清單,並將其命名為 external-http-response.yaml

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
          - matches:
            - path:
                type: PathPrefix
                value: /de
            filters:
              - type: ResponseHeaderModifier
                responseHeaderModifier:
                  add:
                    - name: Strict-Transport-Security
                      value: max-age=63072000
            backendRefs:
              - name: store-german
                port: 8080
    

    驗證您的設定

    1. 設定自訂要求和回應標頭後,請按照下列步驟驗證設定:

        kubectl get httproute
      

      輸出結果會與下列內容相似:

        NAME    HOSTNAMES               AGE
        store   ["store.example.com"]   4d23h
      
    2. 如要取得更多詳細資料,請使用 describe 指令:

        kubectl describe httproute
      

      輸出結果會與下列內容相似:

        Name:         store
        Namespace:    default
        Labels:       <none>
        Annotations:  <none>
        API Version:  gateway.networking.k8s.io/v1beta1
        Kind:         HTTPRoute
        Metadata:
          Creation Timestamp:  2023-05-27T00:51:01Z
          Generation:          5
          Resource Version:    25418887
          UID:                 2e07a1b8-420b-41b4-acd1-cecbfcd39f42
        Spec:
          Hostnames:
            store.example.com
          Parent Refs:
            Group:  gateway.networking.k8s.io
            Kind:   Gateway
            Name:   external-http
          Rules:
            Backend Refs:
              Group:
              Kind:    Service
              Name:    store-v1
              Port:    8080
              Weight:  1
            Matches:
              Path:
                Type:   PathPrefix
                Value:  /
            Backend Refs:
              Group:
              Kind:    Service
              Name:    store-v2
              Port:    8080
              Weight:  1
            Matches:
              Headers:
                Name:   env
                Type:   Exact
                Value:  canary
              Path:
                Type:   PathPrefix
                Value:  /
            Backend Refs:
              Group:
              Kind:    Service
              Name:    store-german
              Port:    8080
              Weight:  1
            Filters:
              Request Header Modifier:
                Add:
                  Name:   X-Client-Geo-Location
                  Value:  {client_region},{client_city}
              Type:       RequestHeaderModifier
            Matches:
              Path:
                Type:   PathPrefix
                Value:  /de
        Status:
          <...>
      

    路徑狀態

    HTTPRoute 資源會發出條件和事件,協助使用者瞭解 HTTPRoute 是否已成功繫結至一或多個閘道,或是遭到拒絕。

    HTTPRoute 條件

    HTTPRoute 條件會指出路徑和所繫結閘道的狀態。由於路徑可以繫結至多個閘道,因此這是閘道清單,以及路徑與每個閘道之間的個別條件。

    • Accepted=True 表示 HTTPRoute 已成功繫結至 Gateway。
    • Accepted=False 表示 HTTPRoute 已遭拒,無法與這個 Gateway 繫結。

    如果「閘道」Gateway bindings標題下方未列出任何閘道,表示 HTTPRoute 標籤和閘道標籤選取器可能不符。如果任何閘道都未選取您的路徑,就可能發生這種情況。

    HTTPRoute 事件

    HTTPRoute 事件會提供 HTTPRoute 狀態的詳細資料。事件會依下列原因分組:

    • 新增資源時會觸發 ADD 事件。
    • 資源更新時會觸發 UPDATE 個事件。
    • SYNC 事件是由定期對帳觸發。

    路徑合併、優先順序和驗證

    路徑優先順序

    Gateway API 會為具有重疊轉送規則的路徑,定義嚴格的優先順序規則,決定流量的相符方式。兩個重疊 HTTPRoute 之間的優先順序如下:

    1. 主機名稱合併:最長/最明確的主機名稱相符項目。
    2. 路徑合併:最長/最明確的路徑比對。
    3. 標頭合併:相符的 HTTP 標頭數量最多。
    4. 衝突:如果前三條規則未建立優先順序,則優先順序會授予時間戳記最舊的 HTTPRoute 資源。

    合併路線

    如果是 gke-l7 GatewayClass,特定 Gateway 的所有 HTTPRoute 都會合併到同一個 URL 對應資源。HTTPRoutes 的合併方式取決於 HTTPRoutes 之間的重疊類型。先前的範例中的 HTTPRoute 可拆分為三個不同的 HTTPRoute,以說明路徑合併和優先順序:

    1. 路徑合併:所有三個 HTTPRoute 都附加相同的 internal-http Gateway,因此會合併在一起。
    2. 主機名稱合併:所有三條路徑都符合 store.example.com,因此主機名稱規則會合併。
    3. 路徑合併:store-german-route 的路徑較明確 /de,因此不會進一步合併。store-v1-route 和 store-v2-route 也都與相同的 /* 路徑相符,因此會合併路徑。
    4. 標頭合併:store-v2-route 的 HTTP 標頭比對條件比 store-v1-route 更具體,因此不會進一步合併。
    5. 衝突:由於系統可根據主機名稱、路徑和標頭合併路徑,因此不會發生衝突,且所有轉送規則都會套用至流量。

    先前的範例中使用的單一 HTTPRoute 等於下列三個個別路徑:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-v1-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - kind: Service
          name: store-v1
          port: 8080
    ---
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-v2-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - headers:
          - type: Exact
            name: env
            value: canary
        backendRefs:
        - kind: Service
          name: store-v2
          port: 8080
    ---
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-german-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /de
        backendRefs:
        - kind: Service
          name: store-german
          port: 8080
    

    Kubernetes 閘道和 Istio 閘道

    請注意,Kubernetes Gateway API 和 Istio API 都有名為 Gateway 的資源。雖然兩者執行類似的功能,但並非相同資源。如果您在同一個 Kubernetes 叢集中使用 Istio 和 Gateway API,透過指令列使用 kubectl 時,這些名稱會重疊。kubectl get gateway 可能會傳回 Kubernetes Gateway 資源,而非 Istio Gateway 資源,反之亦然。

    $ kubectl api-resources
    NAME       SHORTNAMES   APIGROUP                       NAMESPACED   KIND
    gateways   gw           networking.istio.io/v1beta1    true         Gateway
    gateways   gtw          networking.k8s.io/v1beta1      true         Gateway
    

    如果您使用 Istio 並升級至 GKE 1.20 以上版本,建議開始使用 Gateway 資源簡稱或指定 API 群組。Kubernetes Gateway 的簡短名稱為 gtw,Istio Gateway 的簡短名稱為 gw。下列指令會分別傳回 Kubernetes Gateway 和 Istio Gateway 資源。

    # Kubernetes Gateway
    $ kubectl get gtw
    NAME                        CLASS
    multi-cluster-gateway       gke-l7-global-external-managed-mc
    
    $ kubectl get gateway.networking.x-k8s.io
    NAME                        CLASS
    multi-cluster-gateway       gke-l7-global-external-managed-mc
    
    # Istio Gateway
    $ kubectl get gw
    NAME               AGE
    bookinfo-gateway   64m
    
    $ kubectl get gateway.networking.istio.io
    NAME               AGE
    bookinfo-gateway   64m
    

    疑難排解

    該區域缺少 Proxy 專用子網路

    症狀:

    建立區域閘道 (內部或外部) 時,可能會發生下列問題:

    generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/[REGION_NAME]/targetHttpProxies/gkegw-x5vt-default-internal-http-[ID]'. A reserved managed proxy subnetwork with purpose REGIONAL_MANAGED_PROXY is required.
    

    原因:

    這則錯誤訊息表示閘道的區域中沒有僅限 Proxy 的子網路。

    解決方法:

    如要解決這個問題,請設定僅限 Proxy 的子網路

    該區域已有 Proxy 專用子網路,但用途有誤

    症狀:

    為區域性閘道 (內部或外部) 建立僅限 Proxy 的子網路時,可能會發生下列問題:

    ERROR: (gcloud.compute.networks.subnets.create) Could not fetch resource:
     - The resource 'projects/[PROJECT_NAME]/regions/[REGION_NAME]/subnetworks/[PROXY_ONLY_SUBNET_NAME]' already exists
    

    原因:

    這則錯誤訊息表示您嘗試在已有僅限 Proxy 子網路的區域中,建立區域僅限 Proxy 子網路。

    解決方法:

    如要解決這個問題,請按照下列步驟操作:

    1. 確認該區域中已存在僅限 Proxy 的子網路,並驗證其用途是否正確:

      1. 列出子網路,找出該區域中僅限 Proxy 的子網路:

        gcloud compute networks subnets list --regions=COMPUTE_REGION
        

        COMPUTE_REGION 替換為要建立區域閘道的 Compute Engine 區域。

      2. 說明該區域中的僅限 Proxy 子網路,找出其用途:

        gcloud compute networks subnets describe PROXY_ONLY_SUBNET \
            --region COMPUTE_REGION | grep -E 'name|purpose'
        

        PROXY_ONLY_SUBNET 取代為僅限 Proxy 的子網路。

      GKE Gateway 僅支援區域閘道 (內部或區域) 的「僅限 Proxy」REGIONAL_MANAGED_PROXY子網路。

    2. 如果地區中現有的僅限 Proxy 子網路是使用 INTERNAL_HTTPS_LOAD_BALANCER 用途建立,請將其用途遷移至 REGIONAL_MANAGED_PROXY

    沒有健康的上游

    症狀:

    建立閘道但無法存取後端服務時 (503 回應碼),可能會發生下列問題:

    no healthy upstream
    

    原因:

    這則錯誤訊息表示健康狀態檢查探測器找不到健康的後端服務。後端服務可能運作正常,但您可能需要自訂健康狀態檢查。

    解決方法:

    如要解決這個問題,請使用 HealthCheckPolicy,根據應用程式的需求自訂健康狀態檢查 (例如 /health)。

    後續步驟