本文將透過實例,引導您部署內部多叢集閘道,將虛擬私有雲網路內的流量,轉送至在兩個不同 GKE 叢集中執行的應用程式。
多叢集閘道提供強大的方式,可管理部署在多個 GKE 叢集中的服務流量。使用 Google 的全球負載平衡基礎架構,即可為應用程式建立單一進入點,簡化管理作業並提升可靠性。在本教學課程中,您將使用範例 store 應用程式模擬實際情況,也就是線上購物服務由不同團隊擁有及營運,並部署在共用 GKE 叢集的機群中。
事前準備
部署多叢集閘道前,需要先完成一些環境準備作業。繼續操作前,請按照「準備多叢集閘道環境」一文的步驟操作:
最後,請先查看 GKE Gateway 控制器的限制和已知問題,再於環境中使用控制器。
跨區域部署內部多叢集閘道
您可以部署多叢集閘道,在多個區域的 GKE 叢集之間提供第 7 層內部負載平衡。這些閘道會使用 gke-l7-cross-regional-internal-managed-mc GatewayClass。這個 GatewayClass 會佈建由 Google Cloud 管理的跨區域內部應用程式負載平衡器,並啟用虛擬私有 IP 位址,供虛擬私有雲網路中的用戶端存取。只要使用閘道要求這些區域中的位址,即可透過所選區域的前端公開這些閘道。內部 VIP 可以是單一 IP 位址,也可以是多個區域中的 IP 位址,每個區域各有一個 IP 位址 (在閘道中指定)。流量會導向至最接近且健康狀態良好的後端 GKE 叢集,該叢集可處理要求。
必要條件
使用專案 ID 設定
gcloud環境,藉此設定專案和殼層:export PROJECT_ID="YOUR_PROJECT_ID" gcloud config set project ${PROJECT_ID}在不同地區建立 GKE 叢集。
這個範例使用兩個叢集,分別是
us-west1中的gke-west-1和us-east1中的gke-east-1。確認已啟用 Gateway API (--gateway-api=standard),且叢集已註冊至機群。gcloud container clusters create gke-west-1 \ --location=us-west1-a \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --project=${PROJECT_ID} \ --enable-fleet \ --gateway-api=standard gcloud container clusters create gke-east-1 \ --location=us-east1-c \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --project=${PROJECT_ID} \ --enable-fleet \ --gateway-api=standard重新命名背景資訊,方便存取:
gcloud container clusters get-credentials gke-west-1 \ --location=us-west1-a \ --project=${PROJECT_ID} gcloud container clusters get-credentials gke-east-1 \ --location=us-east1-c \ --project=${PROJECT_ID} kubectl config rename-context gke_${PROJECT_ID}_us-west1-a_gke-west-1 gke-west1 kubectl config rename-context gke_${PROJECT_ID}_us-east1-c_gke-east-1 gke-east1啟用多叢集服務 (MCS) 和多叢集 Ingress (MCI/Gateway):
gcloud container fleet multi-cluster-services enable --project=${PROJECT_ID} # Set the config membership to one of your clusters (e.g., gke-west-1) # This cluster will be the source of truth for multi-cluster Gateway and Route resources. gcloud container fleet ingress enable \ --config-membership=projects/${PROJECT_ID}/locations/us-west1/memberships/gke-west-1 \ --project=${PROJECT_ID}設定僅限 Proxy 的子網路。 在 GKE 叢集所在區域和負載平衡器運作區域中,您必須建立 Proxy 專用子網路。跨區域內部應用程式負載平衡器需要將這個子網路的用途設為
GLOBAL_MANAGED_PROXY。# Proxy-only subnet for us-west1 gcloud compute networks subnets create us-west1-proxy-only-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=us-west1 \ --network=default \ --range=10.129.0.0/23 # Choose an appropriate unused CIDR range # Proxy-only subnet for us-east1 gcloud compute networks subnets create us-east1-proxy-only-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=us-east1 \ --network=default \ --range=10.130.0.0/23 # Choose an appropriate unused CIDR range如果您未使用預設網路,請將
default替換為虛擬私有雲網路的名稱。確認 CIDR 範圍不得重複或重疊。將
store等示範應用程式部署至這兩個叢集。gke-networking-recipes中的store.yaml範例檔案會建立store命名空間和部署作業。kubectl apply --context gke-west1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml kubectl apply --context gke-east1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml在每個叢集中建立 Kubernetes
Service資源和ServiceExport資源,從各個叢集匯出服務,讓機群中的服務可供探索。以下範例會從每個叢集匯出一般store服務和特定區域服務 (store-west-1、store-east-1),全部位於store命名空間內。適用於
gke-west1:cat << EOF | kubectl apply --context gke-west1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: store --- apiVersion: v1 kind: Service metadata: name: store-west-1 # Specific to this cluster namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store-west-1 # Exporting the region-specific service namespace: store EOF適用於
gke-east1:cat << EOF | kubectl apply --context gke-east1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: store --- apiVersion: v1 kind: Service metadata: name: store-east-1 # Specific to this cluster namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store-east-1 # Exporting the region-specific service namespace: store EOF檢查 ServiceImports: 確認
ServiceImport資源已在store命名空間內的每個叢集中建立。建立這些項目可能需要幾分鐘時間。bash kubectl get serviceimports --context gke-west1 -n store kubectl get serviceimports --context gke-east1 -n store您應該會看到列出的store、store-west-1和store-east-1(或根據傳播情況列出的相關項目)。
設定內部多區域閘道
定義參照 gke-l7-cross-regional-internal-managed-mc GatewayClass 的 Gateway 資源。將這個資訊清單套用至指定設定叢集,例如 gke-west-1。
您可以在 spec.addresses 欄位中,要求特定區域的臨時 IP 位址,或使用預先分配的靜態 IP 位址。
如要使用臨時 IP 位址,請將下列
Gateway資訊清單儲存為cross-regional-gateway.yaml:# cross-regional-gateway.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-cross-region-gateway namespace: store # Namespace for the Gateway resource spec: gatewayClassName: gke-l7-cross-regional-internal-managed-mc addresses: # Addresses across regions. Address value is allowed to be empty or matching # the region name. - type: networking.gke.io/ephemeral-ipv4-address/us-west1 value: "us-west1" - type: networking.gke.io/ephemeral-ipv4-address/us-east1 value: "us-east1" listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute # Only allow HTTPRoute to attach以下清單定義了先前 YAML 檔案中的部分欄位:
metadata.namespace:建立 Gateway 資源的命名空間,例如store。spec.gatewayClassName:GatewayClass 的名稱。必須為gke-l7-cross-regional-internal-managed-mc。spec.listeners.allowedRoutes.kinds:可附加的 Route 物件類型,例如HTTPRoute。spec.addresses:type: networking.gke.io/ephemeral-ipv4-address/REGION:要求臨時 IP 位址。value:指定地址的區域,例如"us-west1"或"us-east1"。
將資訊清單套用至設定叢集,例如
gke-west1:kubectl apply --context gke-west1 -f cross-regional-gateway.yaml
將 HTTPRoute 附加至 Gateway
定義 HTTPRoute 資源來管理流量轉送,並將這些資源套用至設定叢集。
將下列
HTTPRoute資訊清單儲存為store-route.yaml:# store-route.yaml kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store-route namespace: store labels: gateway: cross-regional-internal spec: parentRefs: - name: internal-cross-region-gateway namespace: store # Namespace where the Gateway is deployed hostnames: - "store.example.internal" # Hostname clients will use rules: - matches: # Rule for traffic to /west - path: type: PathPrefix value: /west backendRefs: - group: net.gke.io # Indicates a multi-cluster ServiceImport kind: ServiceImport name: store-west-1 # Targets the ServiceImport for the west cluster port: 8080 - matches: # Rule for traffic to /east - path: type: PathPrefix value: /east backendRefs: - group: net.gke.io kind: ServiceImport name: store-east-1 # Targets the ServiceImport for the east cluster port: 8080 - backendRefs: # Default rule for other paths (e.g., /) - group: net.gke.io kind: ServiceImport name: store # Targets the generic 'store' ServiceImport (any region) port: 8080以下清單定義了先前 YAML 檔案中的部分欄位:
spec.parentRefs:將這個路徑附加至store命名空間中的internal-cross-region-gateway。spec.hostnames:代表用戶端用來存取服務的主機名稱。spec.rules:定義轉送邏輯。本範例使用路徑型轉送:/west流量會傳送至store-west-1ServiceImport。/east流量會傳送至store-east-1ServiceImport。- 所有其他流量 (例如
/) 都會前往一般storeServiceImport。
backendRefs:group: net.gke.io和kind: ServiceImport目標多叢集服務。
將
HTTPRoute資訊清單套用至設定叢集:kubectl apply --context gke-west1 -f store-route.yaml
確認閘道和路徑的狀態
檢查閘道狀態:
kubectl get gateway internal-cross-region-gateway -n store -o yaml --context gke-west1尋找
type:Programmedand狀態為「True」的條件 (. You should see IP addresses assigned in thestatus.addressesfield, corresponding to the regions you specified (e.g., one forus-west1and one forus-east1)。檢查 HTTPRoute 狀態:
kubectl get httproute store-route -n store -o yaml --context gke-west1在
status.parents[].conditions中尋找含有type: Accepted(或ResolvedRefs) 和status: "True"的條件。
確認流量
將 IP 位址指派給閘道後,您可以從位於虛擬私有雲網路內,且位於其中一個區域的用戶端 VM,或位於可連線至閘道 IP 位址的區域,測試流量。
擷取閘道 IP 位址。
下列指令會嘗試剖析 JSON 輸出內容。您可能需要根據確切的結構調整
jsonpath。kubectl get gateway cross-region-gateway -n store --context gke-west1 -o=jsonpath="{.status.addresses[*].value}".這項指令的輸出內容應包含 VIP,例如
VIP1_WEST或VIP2_EAST。傳送測試要求: 從虛擬私有雲中的用戶端 VM:
# Assuming VIP_WEST is an IP in us-west1 and VIP_EAST is an IP in us-east1 # Traffic to /west should ideally be served by gke-west-1 curl -H "host: store.example.internal" http://VIP_WEST/west curl -H "host: store.example.internal" http://VIP_EAST/west # Still targets store-west-1 due to path # Traffic to /east should ideally be served by gke-east-1 curl -H "host: store.example.internal" http://VIP_WEST/east # Still targets store-east-1 due to path curl -H "host: store.example.internal" http://VIP_EAST/east # Traffic to / (default) could be served by either cluster curl -H "host: store.example.internal" http://VIP_WEST/ curl -H "host: store.example.internal" http://VIP_EAST/回覆應包含
store應用程式的詳細資料,指出哪個後端 Pod 處理了要求,例如cluster_name或zone。
使用靜態 IP 位址
您可以改用預先分配的靜態內部 IP 位址,而非臨時 IP 位址。
在要使用的區域中建立靜態 IP 位址:
gcloud compute addresses create cross-region-gw-ip-west --region us-west1 --subnet default --project=${PROJECT_ID} gcloud compute addresses create cross-region-gw-ip-east --region us-east1 --subnet default --project=${PROJECT_ID}如果未使用預設子網路,請將
default替換為要分配 IP 位址的子網路名稱。這些子網路是一般子網路,而非僅限 Proxy 的子網路。修改
cross-regional-gateway.yaml檔案中的spec.addresses部分,更新閘道資訊清單:# cross-regional-gateway-static-ip.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-cross-region-gateway # Or a new name if deploying alongside namespace: store spec: gatewayClassName: gke-l7-cross-regional-internal-managed-mc addresses: - type: networking.gke.io/named-address-with-region # Use for named static IP value: "regions/us-west1/addresses/cross-region-gw-ip-west" - type: networking.gke.io/named-address-with-region value: "regions/us-east1/addresses/cross-region-gw-ip-east" listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute套用更新後的 Gateway 資訊清單。
kubectl apply --context gke-west1 -f cross-regional-gateway.yaml
非預設子網路的特別注意事項
使用非預設子網路時,請注意下列事項:
相同虛擬私有雲網路:所有使用者建立的資源 (例如靜態 IP 位址、僅限 Proxy 的子網路和 GKE 叢集) 都必須位於相同的虛擬私有雲網路。
位址子網路:為閘道建立靜態 IP 位址時,系統會從指定區域中的一般子網路分配位址。
叢集子網路命名:每個區域都必須有一個子網路,名稱與 MCG 設定叢集所在的子網路相同。
- 舉例來說,如果您的
gke-west-1設定叢集位於projects/YOUR_PROJECT/regions/us-west1/subnetworks/my-custom-subnet,則您要求位址的地區也必須有my-custom-subnet子網路。如果您要求us-east1和us-centra1地區的位址,則這些地區也必須存在名為my-custom-subnet的子網路。
- 舉例來說,如果您的
清除所用資源
完成本文件的練習後,請按照下列步驟移除資源,以免您的帳戶產生不必要的費用:
刪除叢集。
如果叢集不需要註冊用於其他用途,請取消註冊機群叢集。
停用
multiclusterservicediscovery功能:gcloud container fleet multi-cluster-services disable停用多叢集 Ingress:
gcloud container fleet ingress disable停用 API:
gcloud services disable \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ --project=PROJECT_ID
疑難排解
內部閘道的 Proxy 專用子網路不存在
如果內部閘道上顯示下列事件,表示該區域沒有僅限 Proxy 的子網路。如要解決這個問題,請部署僅限 Proxy 的子網路。
generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/us-west1/targetHttpProxies/gkegw-x5vt-default-internal-http-2jzr7e3xclhj'. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.
沒有健康的上游
症狀:
建立閘道但無法存取後端服務時 (503 回應碼),可能會發生下列問題:
no healthy upstream
原因:
這則錯誤訊息表示健康狀態檢查探測器找不到健康狀態良好的後端服務。後端服務可能運作正常,但您可能需要自訂健康狀態檢查。
解決方法:
如要解決這個問題,請使用 HealthCheckPolicy,根據應用程式的需求自訂健康狀態檢查 (例如 /health)。
後續步驟
- 進一步瞭解 Gateway 控制器。