本頁說明如何部署 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 個。 超過這個上限可能會影響效能或導致延遲時間增加。
您無法使用 FrontendConfig 或 BackendConfig 設定 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
更改下列內容:
CLUSTER_NAME
:現有叢集的名稱。CLUSTER_LOCATION
:叢集的 Compute Engine 地區或區域。
--gateway-api=standard
標記會指示 GKE 隨叢集安裝 v1beta1
CRD。
驗證叢集
建立或升級叢集後,GKE Gateway 控制器會自動安裝 GatewayClass。控制器可能需要幾分鐘才能辨識 CRD 並安裝 GatewayClass。
確認 Gateway API 已在 GKE 控制層中啟用:
gcloud container clusters describe CLUSTER_NAME \ --location=CLUSTER_LOCATION \ --format json
輸出結果大致如下。如果這個輸出內容為空白,請重新執行叢集更新指令。
"networkConfig": { ... "gatewayApiConfig": { "channel": "CHANNEL_STANDARD" }, ... },
確認 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 位址。
建立僅限 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
。
驗證僅限 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。
將下列 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 連線,要求可能會失敗。
在叢集中部署閘道:
kubectl apply -f gateway.yaml
確認閘道已正確部署。部署所有資源可能需要幾分鐘的時間。
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 規格。
將商店應用程式 (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。
確認應用程式部署成功:
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
確認服務已部署:
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,以便連線至商店應用程式。
將下列 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
在叢集中部署 HTTProute:
kubectl apply -f store-route.yaml
store
HTTPRoute 會使用parentRefs
屬性繫結至internal-http
Gateway。這些轉送規則會設定在基礎負載平衡器上,如下圖所示:這些轉送規則會以以下方式處理 HTTP 流量:
- 傳送至
store.example.com/de
的流量會轉送至服務store-german
。 - 如果傳送至
store.example.com
的流量包含 HTTP 標頭"env: canary"
,就會導向服務store-v2
。 - 其餘傳送至
store.example.com
的流量會導向服務store-v1
。
- 傳送至
確認 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", <...>
確認 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 提出的要求可能會失敗。
從閘道擷取 IP 位址,以便將流量傳送至應用程式:
kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}"
輸出內容為 IP 位址。
從可連線至叢集的虛擬機器 (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" }
前往
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" }
最後,使用
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 建立憑證,確保叢集上執行的應用程式安全無虞。
啟用 Certificate Manager API:
gcloud services enable certificatemanager.googleapis.com
建立憑證對應關係:
gcloud beta certificate-manager maps create store-example-com-map
將 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
:私密金鑰檔案名稱。
詳情請參閱「建立私密金鑰和憑證」。
建立
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 規格。
在本節中,您將建立閘道。應用程式團隊可以部署獨立的路徑,並安全地將其附加至閘道,藉此透過閘道將應用程式公開至網際網路。
將下列資訊清單儲存到名為
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: HTTPS
和port: 443
:指定閘道公開通訊埠 443,以處理 HTTPS 流量。這些欄位會啟用 TLS。networking.gke.io/certmap: store-example-com-map
:指定 Certificate Manager 中憑證對應的名稱。
由於 TLS 是透過 Certificate Manager 設定,因此沒有 TLS 區段。設定時使用
networking.gke.io/certmap
註解。將資訊清單套用至叢集:
kubectl apply -f gateway.yaml
GKE 可能需要幾分鐘的時間才能部署資源。
確認閘道已成功部署:
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 規格。
將範例應用程式部署至叢集:
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
。確認應用程式已成功部署:
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
確認服務是否已成功部署:
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。
將下列資訊清單儲存到名為
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。將資訊清單套用至叢集:
kubectl apply -f store-route-external.yaml
store
HTTPRoute 會使用parentRefs
屬性繫結至external-http
Gateway。下圖顯示在基礎負載平衡器上設定的路由規則:轉送規則會依下列方式處理 HTTP 流量:
- 流量會透過
store.example.com/de
路由傳送至服務store-german
。 - HTTP 標頭為
"env: canary"
的store.example.com
流量會路由至服務store-v2
。 - 其餘流量會轉送至服務
store-v1
。store.example.com
- 流量會透過
確認 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", ...
確認 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 <...>
將流量傳送至應用程式
閘道、路徑和應用程式現已部署至叢集,您可以將流量傳遞至應用程式。
取得閘道的 IP 位址:
kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}"
輸出內容為 IP 位址。
建立 VM:
gcloud cloud-shell ssh
從 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" }
前往
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" }
使用
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) 閘道
為外部負載平衡器建立區域靜態 IP 位址。
gcloud compute addresses create IP_ADDRESS_NAME \ --region=COMPUTE_REGION \ --network-tier=STANDARD
更改下列內容:
IP_ADDRESS_NAME
:新靜態 IP 位址的名稱。COMPUTE_REGION
:叢集執行的 Compute Engine 區域。
使用自行管理的憑證建立區域外部應用程式負載平衡器閘道,如下所示,並將資訊清單儲存為
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
套用
regional-gateway
資訊清單:kubectl apply -f regional-gateway.yaml
驗證設定。
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 的流量比對至這些服務。
部署範例應用程式:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/site.yaml
將下列資訊清單儲存到名為
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
將資訊清單套用至叢集:
kubectl apply -f site-route-internal.yaml
確認 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。如要進一步瞭解「狀態」欄位,請參閱路線狀態。確認流量已正確轉送至閘道:
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 位址集區 |
---|---|
|
主要節點 IPv4/IPv6 位址範圍的區域性私人 IP 位址 |
|
Google 區域外部 IPv4/IPv6 範圍的區域公開 IP 位址 |
|
Google 全域外部 IPv4/IPv6 範圍的全域公開 IP 位址 |
您可以在 addresses.NamedAddress
欄位中指定 IP 位址,不必與閘道相關。您可以在部署 Gateway 之前建立靜態 IP 位址資源,該資源會由 NamedAddress
參照。即使閘道遭到刪除,您仍可重複使用靜態 IP 位址。
使用已命名的 IP 位址
您可以指定 NamedAddress
來設定 IPv4 或 IPv6 位址。您必須先佈建靜態 IP 位址,才能建立閘道。
建立靜態 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 叢集的專案。
將下列資訊清單儲存到名為
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 位址的閘道。
將資訊清單套用至叢集:
kubectl apply -f named-ip-gateway.yaml
驗證閘道 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-gxlb
和 gke-l7-gxlb-mc
GatewayClass 不支援 HTTP 至 HTTPS 的重新導向。如要進一步瞭解各 GatewayClass 支援的不同功能,請參閱「GatewayClass 功能」。
從基礎架構命名空間重新導向 HTTP 流量
在某些情況下,基礎架構或平台管理團隊與應用程式團隊之間沒有明確區別,因此防止 Gateway 遭到濫用可能會是一項挑戰。
下列範例進一步限制 HTTP 監聽器的使用,防止應用程式團隊無意間使用不安全的通訊協定。這個範例會設定 Gateway,只允許 HTTPRoute 在路徑位於特定命名空間 (http-redirect) 時使用 HTTP 監聽器,同時向所有命名空間開放 HTTPS 監聽器。您可以使用 Kubernetes RBAC 限制 http-redirect 命名空間,避免應用程式團隊不慎在這個命名空間中建立 HTTPRoute。
建立閘道的命名空間。將資訊清單儲存為
gateway-namespace.yaml
:apiVersion: v1 kind: Namespace metadata: name: gateway-infra
套用資訊清單:
kubectl apply -f gateway-namespace.yaml
建立 Gateway 的命名空間,並將資訊清單儲存為
redirect-namespace.yaml
:apiVersion: v1 kind: Namespace metadata: name: http-redirect labels: otherInfra: httpToHttps
- 這個命名空間已設定特定標籤。
套用資訊清單:
kubectl apply -f redirect-namespace.yaml
如要限制 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
相符的命名空間。
套用資訊清單:
kubectl apply -f external-gateway.yaml
如要強制執行 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 監聽器。
套用資訊清單:
kubectl apply -f http-redirect.yaml
使用下列資訊清單為應用程式建立 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"
套用資訊清單:
kubectl apply -f service-deployment.yaml
使用下列資訊清單,為僅允許 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
套用資訊清單:
kubectl apply -f http-route.yaml
設定路徑重新導向和網址重新編寫
路徑重新導向是指將傳入要求從一個網址路徑重新導向至另一個路徑。路徑重新導向可讓您在處理過時或已淘汰的網址時,變更網址結構。
網址重寫 有助於在伺服器處理傳入網址前修改該網址。您可以藉此變更網址的結構或格式,但不會實際變更基礎內容或檔案結構。網址重寫有助於建立方便使用者和 SEO 的網址,方便記憶和理解。根據預設,系統不會設定路徑重新導向和網址重寫,您必須使用 HTTPRoute 中的篩選器,明確設定這些重新導向或重寫。
GKE Gateway 支援路徑重新導向和網址重寫。詳情請參閱「HTTP 路徑重新導向和重寫」。
設定路徑重新導向
您可以設定路徑重新導向,取代網址中的完整路徑或前置字元。
取代整個路徑
如要取代整個路徑,請在 HTTPRoute 中設定篩選器,將網址路徑中包含前置字串
/any-path
的任何網址,取代為嚴格值/new-path
。請按照下列方式建立
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/
(嚴格)。套用資訊清單:
kubectl apply -f store.yaml
這項轉送規則會遵循嚴格的重新導向規則,也就是說,瀏覽器不會嘗試快取重新導向,而是重新導向至最新版本。
僅替換前置字串
如要只取代前置字串,請在 HTTPRoute 中設定篩選器,將網址路徑中包含前置字串
/any-prefix
的任何網址,取代為嚴格值/new-prefix
。請按照下列方式建立
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/...
(僅限)。套用資訊清單:
kubectl apply -f store.yaml
這項轉送規則會遵循唯一的重新導向規則,確保瀏覽器一律將您重新導向至預期網頁。
設定網址重新編寫
設定網址重寫,變更網址向使用者顯示的方式。您可以透過網址重寫功能,讓網址更方便使用者閱讀、提升 SEO 效果,或是將使用者重新導向至新網頁。
重新編寫完整主機名稱
如要重新編寫整個主機名稱:
在 HTTPRoute 中設定篩選器,指示 Gateway 將要求標頭中的
Host
資訊從www.example.com
替換為store.example.com
,然後再將要求轉送至後端服務。請按照下列方式建立
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
。套用資訊清單:
kubectl apply -f www.yaml
使用路徑修飾符重新編寫
您可以將重寫功能與路徑修飾符合併使用,在將要求轉送至後端服務前,提供進階網址和路徑修改功能。
如要使用路徑修飾符重新編寫,請按照下列步驟操作:
在 HTTPRoute 中設定篩選器,指示 Gateway 將要求標頭中的「Host」資訊從 www.example.com
to store.example.com
替換為/store
,然後在將要求轉送至後端服務前,將值/store
替換為/
。請按照下列方式建立
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
。套用資訊清單:
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
驗證您的設定
設定自訂要求和回應標頭後,請按照下列步驟驗證設定:
kubectl get httproute
輸出結果會與下列內容相似:
NAME HOSTNAMES AGE store ["store.example.com"] 4d23h
如要取得更多詳細資料,請使用 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 之間的優先順序如下:
- 主機名稱合併:最長/最明確的主機名稱相符項目。
- 路徑合併:最長/最明確的路徑比對。
- 標頭合併:相符的 HTTP 標頭數量最多。
- 衝突:如果前三條規則未建立優先順序,則優先順序會授予時間戳記最舊的 HTTPRoute 資源。
合併路線
如果是 gke-l7
GatewayClass,特定 Gateway 的所有 HTTPRoute 都會合併到同一個 URL 對應資源。HTTPRoutes 的合併方式取決於 HTTPRoutes 之間的重疊類型。先前的範例中的 HTTPRoute 可拆分為三個不同的 HTTPRoute,以說明路徑合併和優先順序:
- 路徑合併:所有三個 HTTPRoute 都附加相同的
internal-http
Gateway,因此會合併在一起。 - 主機名稱合併:所有三條路徑都符合
store.example.com
,因此主機名稱規則會合併。 - 路徑合併:store-german-route 的路徑較明確
/de
,因此不會進一步合併。store-v1-route 和 store-v2-route 也都與相同的/*
路徑相符,因此會合併路徑。 - 標頭合併:store-v2-route 的 HTTP 標頭比對條件比 store-v1-route 更具體,因此不會進一步合併。
- 衝突:由於系統可根據主機名稱、路徑和標頭合併路徑,因此不會發生衝突,且所有轉送規則都會套用至流量。
先前的範例中使用的單一 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 子網路。
解決方法:
如要解決這個問題,請按照下列步驟操作:
確認該區域中已存在僅限 Proxy 的子網路,並驗證其用途是否正確:
列出子網路,找出該區域中僅限 Proxy 的子網路:
gcloud compute networks subnets list --regions=COMPUTE_REGION
將
COMPUTE_REGION
替換為要建立區域閘道的 Compute Engine 區域。說明該區域中的僅限 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
子網路。如果地區中現有的僅限 Proxy 子網路是使用
INTERNAL_HTTPS_LOAD_BALANCER
用途建立,請將其用途遷移至REGIONAL_MANAGED_PROXY
。
沒有健康的上游
症狀:
建立閘道但無法存取後端服務時 (503 回應碼),可能會發生下列問題:
no healthy upstream
原因:
這則錯誤訊息表示健康狀態檢查探測器找不到健康的後端服務。後端服務可能運作正常,但您可能需要自訂健康狀態檢查。
解決方法:
如要解決這個問題,請使用 HealthCheckPolicy
,根據應用程式的需求自訂健康狀態檢查 (例如 /health
)。
後續步驟
- 進一步瞭解閘道控制器。
- 瞭解如何使用政策設定閘道資源。
- 如要瞭解其他 Gateway 設定,請參閱 Gateway API 說明文件。