本文將說明如何完成下列工作:
- 部署透過 GKE 閘道和 Cloud Service Mesh 公開的全球分散式應用程式。
- 結合 Cloud Load Balancing 和 Cloud Service Mesh,向多個用戶端公開應用程式。
- 將負載平衡器與部署在多個Google Cloud 區域的服務網格整合。
本部署指南適用於平台管理員。也適合執行 Cloud Service Mesh 的進階實務工作者。這些操作說明也適用於 GKE 上的 Istio。
架構
下圖顯示服務網格的預設 Ingress 拓撲:外部 TCP/UDP 負載平衡器,可公開單一叢集上的 Ingress 閘道 Proxy:
本部署指南使用 Google Kubernetes Engine (GKE) Gateway 資源。具體來說,這項功能會使用多叢集閘道,在分布於兩個區域的多個 Autopilot 叢集前方設定多區域負載平衡。
上圖顯示資料在雲端進入和網格進入情境中的流動方式。詳情請參閱相關參考架構文件中的架構圖說明。
目標
- 在 Google Cloud 上將一對 GKE Autopilot 叢集部署至同一個機群。
- 將以 Istio 為基礎的 Cloud Service Mesh 部署到相同機群。
- 使用 GKE Gateway 設定負載平衡器,終止公開 HTTPS 流量。
- 將公用 HTTPS 流量直接導向 Cloud Service Mesh 代管的應用程式,這些應用程式部署在多個叢集和區域。
- 將 whereami 範例應用程式部署至這兩個 Autopilot 叢集。
成本最佳化
在本文件中,您將使用下列 Google Cloud計費元件:
- Google Kubernetes Engine
- Cloud Load Balancing
- Cloud Service Mesh
- Multi Cluster Ingress
- Google Cloud Armor
- Certificate Manager
- Cloud Endpoints
如要根據預測用量估算費用,請使用 Pricing Calculator。
完成本文所述工作後,您可以刪除建立的資源,避免繼續計費,詳情請參閱「清除所用資源」。
事前準備
-
在 Google Cloud 控制台的專案選擇器頁面中,選取或建立 Google Cloud 專案。
選取或建立專案所需的角色
- 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您在專案中獲派角色,即可選取該專案。
-
建立專案:如要建立專案,您需要專案建立者角色 (
roles/resourcemanager.projectCreator),其中包含resourcemanager.projects.create權限。瞭解如何授予角色。
-
在 Google Cloud 控制台中啟用 Cloud Shell。
您將透過 Cloud Shell 執行本次部署作業的所有終端機指令。
設定預設 Google Cloud 專案:
export PROJECT=PROJECT_ID export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)") gcloud config set project PROJECT_ID將
PROJECT_ID替換為要用於這項部署作業的專案 ID。建立目前使用的目錄:
mkdir -p ${HOME}/edge-to-mesh-multi-region cd ${HOME}/edge-to-mesh-multi-region export WORKDIR=`pwd`
建立 GKE 叢集
在本節中,您將建立 GKE 叢集,用來代管應用程式和支援基礎架構,這些項目會在稍後建立。
在 Cloud Shell 中,建立新的
kubeconfig檔案。這個步驟可確保您不會與現有的 (預設)kubeconfig檔案發生衝突。touch edge2mesh_mr_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfig定義建立 GKE 叢集和其中資源時使用的環境變數。修改預設區域選項,以符合您的需求。
export CLUSTER_1_NAME=edge-to-mesh-01 export CLUSTER_2_NAME=edge-to-mesh-02 export CLUSTER_1_REGION=us-central1 export CLUSTER_2_REGION=us-east4 export PUBLIC_ENDPOINT=frontend.endpoints.PROJECT_ID.cloud.goog啟用本指南中使用的 Google Cloud API:
gcloud services enable \ container.googleapis.com \ mesh.googleapis.com \ gkehub.googleapis.com \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ certificatemanager.googleapis.com在
CLUSTER_1_REGION中建立含私人節點的 GKE Autopilot 叢集。使用--async旗標,避免等待第一個叢集佈建並向機群註冊:gcloud container clusters create-auto --async \ ${CLUSTER_1_NAME} --region ${CLUSTER_1_REGION} \ --release-channel rapid \ --enable-private-nodes --enable-fleet在
CLUSTER_2_REGION中建立並註冊第二個 Autopilot 叢集:gcloud container clusters create-auto \ ${CLUSTER_2_NAME} --region ${CLUSTER_2_REGION} \ --release-channel rapid \ --enable-private-nodes --enable-fleet確認叢集正在執行。最多可能需要 20 分鐘,所有叢集才會開始運作:
gcloud container clusters list輸出結果會與下列內容相似:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS STACK_TYPE edge-to-mesh-01 us-central1 1.35.5-gke.1000000 34.31.166.104 ek-standard-8 1.35.5-gke.1000000 1 RUNNING IPV4 edge-to-mesh-02 us-east4 1.35.5-gke.1000000 35.245.233.88 ek-standard-8 1.35.5-gke.1000000 1 RUNNING IPV4
收集
CLUSTER_1_NAME的憑證。您是以非同步方式建立CLUSTER_1_NAME,因此可以在叢集佈建期間執行其他指令。gcloud container clusters get-credentials ${CLUSTER_1_NAME} \ --region ${CLUSTER_1_REGION}如要清楚瞭解 Kubernetes 內容的名稱,請將其重新命名為叢集名稱:
kubectl config rename-context gke_PROJECT_ID_${CLUSTER_1_REGION}_${CLUSTER_1_NAME} ${CLUSTER_1_NAME} kubectl config rename-context gke_PROJECT_ID_${CLUSTER_2_REGION}_${CLUSTER_2_NAME} ${CLUSTER_2_NAME}
安裝服務網格
在本節中,您將使用 Fleet API 設定代管 Cloud Service Mesh。使用 Fleet API 啟用 Cloud Service Mesh,可透過宣告式方法佈建服務網格。
在 Cloud Shell 中,為機群啟用 Cloud Service Mesh:
gcloud container fleet mesh enable啟用自動控制層和資料平面管理:
gcloud container fleet mesh update \ --management automatic \ --memberships ${CLUSTER_1_NAME},${CLUSTER_2_NAME}等待約 20 分鐘。然後確認控制層狀態為
ACTIVE:gcloud container fleet mesh describe輸出結果會與下列內容相似:
createTime: '2026-06-04T23:40:02.666228685Z' membershipSpecs: projects/497535075790/locations/us-central1/memberships/edge-to-mesh-01: mesh: management: MANAGEMENT_AUTOMATIC projects/497535075790/locations/us-east4/memberships/edge-to-mesh-02: mesh: management: MANAGEMENT_AUTOMATIC membershipStates: projects/497535075790/locations/us-central1/memberships/edge-to-mesh-01: servicemesh: conditions: - code: VPCSC_GA_SUPPORTED details: This control plane supports VPC-SC GA. documentationLink: http://cloud.google.com/service-mesh/docs/managed/vpc-sc severity: INFO controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' implementation: TRAFFIC_DIRECTOR state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: 'Revision ready for use: asm-managed-rapid.' updateTime: '2026-06-04T23:45:52.958139396Z' projects/497535075790/locations/us-east4/memberships/edge-to-mesh-02: servicemesh: conditions: - code: VPCSC_GA_SUPPORTED details: This control plane supports VPC-SC GA. documentationLink: http://cloud.google.com/service-mesh/docs/managed/vpc-sc severity: INFO controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' implementation: TRAFFIC_DIRECTOR state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: 'Revision ready for use: asm-managed-rapid.' updateTime: '2026-06-04T23:45:54.621862416Z' name: projects/e2m-mc-h2c/locations/global/features/servicemesh resourceState: state: ACTIVE spec: {} updateTime: '2026-06-04T23:40:55.123874541Z'
部署外部應用程式負載平衡器,並建立 Ingress 閘道
在本節中,您將透過 GKE Gateway 控制器部署外部應用程式負載平衡器,並為兩個叢集建立 Ingress 閘道。gateway 和 gatewayClass 資源會自動佈建負載平衡器,並執行後端健康狀態檢查。如要在負載平衡器上提供 TLS 終止功能,請建立 Certificate Manager 資源,並將其附加至負載平衡器。此外,您可以使用端點,自動為應用程式佈建公用 DNS 名稱。
在兩個叢集上安裝 Ingress 閘道
為確保安全,建議您在與網格控制層不同的命名空間中部署 Ingress 閘道。
在 Cloud Shell 中,於每個叢集上建立專屬的
ingress-gateway命名空間:kubectl --context=${CLUSTER_1_NAME} create namespace ingress-gateway kubectl --context=${CLUSTER_2_NAME} create namespace ingress-gateway將命名空間標籤新增至
ingress-gateway命名空間:kubectl --context=${CLUSTER_1_NAME} label namespace ingress-gateway istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} label namespace ingress-gateway istio-injection=enabled輸出結果會與下列內容相似:
namespace/ingress-gateway labeled
使用
istio-injection=enabled為ingress-gateway命名空間加上標籤,可指示 Cloud Service Mesh 在部署 Pod 時,自動插入 Envoy Sidecar Proxy。產生自行簽署的憑證,以供日後使用:
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \ -subj "/CN=frontend.endpoints.PROJECT_ID.cloud.goog/O=Edge2Mesh Inc" \ -keyout ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ -out ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt憑證可在負載平衡器與服務網格 Ingress 閘道之間,提供額外的加密層。此外,這項功能也支援以 HTTP/2 為基礎的通訊協定,例如 gRPC。如要瞭解如何將自行簽署的憑證附加至 Ingress 閘道,請參閱後續的「建立外部 IP 位址、DNS 記錄和 TLS 憑證資源」一節。
如要為 GFE 到網格的連線使用 HTTP/2,但不需要自己的加密,可以使用 H2C。
如要進一步瞭解 Ingress 閘道憑證的規定,請參閱「從負載平衡器到後端的加密」。
在每個叢集上建立 Kubernetes 密鑰,用來儲存自行簽署的憑證:
kubectl --context ${CLUSTER_1_NAME} -n ingress-gateway create secret tls \ edge2mesh-credential \ --key=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ --cert=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt kubectl --context ${CLUSTER_2_NAME} -n ingress-gateway create secret tls \ edge2mesh-credential \ --key=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ --cert=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt如要與外部應用程式負載平衡器整合,請建立 kustomize 變體,設定 Ingress 閘道資源:
mkdir -p ${WORKDIR}/asm-ig/base cat <<EOF > ${WORKDIR}/asm-ig/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/anthos-service-mesh-samples/docs/ingress-gateway-asm-manifests/base EOF mkdir ${WORKDIR}/asm-ig/variant cat <<EOF > ${WORKDIR}/asm-ig/variant/role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: asm-ingressgateway namespace: ingress-gateway rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"] EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: asm-ingressgateway namespace: ingress-gateway roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: asm-ingressgateway subjects: - kind: ServiceAccount name: asm-ingressgateway EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/service-proto-type.yaml apiVersion: v1 kind: Service metadata: name: asm-ingressgateway namespace: ingress-gateway spec: ports: - name: status-port port: 15021 protocol: TCP targetPort: 15021 - name: http port: 80 targetPort: 8080 appProtocol: HTTP - name: https port: 443 targetPort: 8443 appProtocol: HTTP2 type: ClusterIP EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/gateway.yaml apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: asm-ingressgateway namespace: ingress-gateway spec: servers: - port: number: 443 name: https protocol: HTTPS hosts: - "*" # IMPORTANT: Must use wildcard here when using SSL, as SNI isn't passed from GFE tls: mode: SIMPLE credentialName: edge2mesh-credential EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/kustomization.yaml namespace: ingress-gateway resources: - ../base - role.yaml - rolebinding.yaml patches: - path: service-proto-type.yaml target: kind: Service - path: gateway.yaml target: kind: Gateway EOF將 Ingress 閘道設定套用至這兩個叢集:
kubectl --context ${CLUSTER_1_NAME} apply -k ${WORKDIR}/asm-ig/variant kubectl --context ${CLUSTER_2_NAME} apply -k ${WORKDIR}/asm-ig/variant
使用多叢集服務將 Ingress 閘道 Pod 公開至負載平衡器
在本節中,您將透過ServiceExport自訂資源匯出 Ingress 閘道 Pod。您必須透過ServiceExport自訂資源匯出 Ingress 閘道 Pod,原因如下:
- 讓負載平衡器在多個叢集中處理 Ingress 閘道 Pod。
- 允許 Ingress 閘道 Pod 將要求 Proxy 至服務網格內執行的服務。
在 Cloud Shell 中,為機群啟用多叢集服務 (MCS):
gcloud container fleet multi-cluster-services enable授予 MCS 專案或機群的必要 IAM 權限:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:PROJECT_ID.svc.id.goog[gke-mcs/gke-mcs-importer]" \ --role "roles/compute.networkViewer"建立
ServiceExportYAML 檔案:cat <<EOF > ${WORKDIR}/svc_export.yaml kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: asm-ingressgateway namespace: ingress-gateway EOF將
ServiceExportYAML 檔案套用至兩個叢集:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/svc_export.yaml如果收到下列錯誤訊息,請稍候片刻,等待 MCS 自訂資源定義 (CRD) 安裝完成。然後重新執行指令,將
ServiceExportYAML 檔案套用至兩個叢集。error: resource mapping not found for name: "asm-ingressgateway" namespace: "ingress-gateway" from "svc_export.yaml": no matches for kind "ServiceExport" in version "net.gke.io/v1" ensure CRDs are installed first
建立外部 IP 位址、DNS 記錄和 TLS 憑證資源
在本節中,您將建立網路資源,支援稍後在這個部署作業中建立的負載平衡資源。
在 Cloud Shell 中,保留靜態外部 IP 位址:
gcloud compute addresses create mcg-ip --globalGKE Gateway 資源會使用靜態 IP 位址。即使重新建立外部負載平衡器,IP 位址也不會改變。
取得靜態 IP 位址並儲存為環境變數:
export MCG_IP=$(gcloud compute addresses describe mcg-ip --global --format "value(address)") echo ${MCG_IP}如要建立穩定且容易辨識的閘道 IP 位址對應關係,您必須擁有公開 DNS 記錄。
您可以選擇任何 DNS 供應商和自動化機制。這項部署作業使用 Endpoints,而非建立受管理 DNS 區域。Endpoints 會為外部 IP 位址提供免費的 Google 管理 DNS 記錄。
執行下列指令,建立名為
dns-spec.yaml的 YAML 檔案:cat <<EOF > ${WORKDIR}/dns-spec.yaml swagger: "2.0" info: description: "Cloud Endpoints DNS" title: "Cloud Endpoints DNS" version: "1.0.0" paths: {} host: "frontend.endpoints.PROJECT_ID.cloud.goog" x-google-endpoints: - name: "frontend.endpoints.PROJECT_ID.cloud.goog" target: "${MCG_IP}" EOFdns-spec.yaml檔案會以frontend.endpoints.PROJECT_ID.cloud.goog的形式定義公開 DNS 記錄,其中PROJECT_ID是專屬專案 ID。部署
dns-spec.yaml檔案,建立 DNS 項目。這項程序需要幾分鐘才能完成。gcloud endpoints services deploy ${WORKDIR}/dns-spec.yaml使用 Certificate Manager 為上一步建立的 DNS 項目名稱建立憑證:
gcloud certificate-manager certificates create mcg-cert \ --domains="frontend.endpoints.PROJECT_ID.cloud.goog"Google 代管的 TLS 憑證可用於終止負載平衡器的連入用戶端要求。
建立憑證對應組合:
gcloud certificate-manager maps create mcg-cert-map負載平衡器會透過您在下一個步驟中建立的憑證對應組合項目,參照憑證。
為本節稍早建立的憑證建立憑證對應關係:
gcloud certificate-manager maps entries create mcg-cert-map-entry \ --map="mcg-cert-map" \ --certificates="mcg-cert" \ --hostname="frontend.endpoints.PROJECT_ID.cloud.goog"
建立後端服務政策和負載平衡器資源
在本節中,您將完成下列工作:
- 建立含有規則的 Cloud Armor 安全性政策。
- 建立政策,讓負載平衡器透過您先前建立的
ServiceExportYAML 檔案,檢查 Ingress 閘道 Pod 的回應能力。 - 使用 GKE Gateway API 建立負載平衡器資源。
- 使用
GatewayClass自訂資源設定特定負載平衡器類型。 - 為機群啟用多叢集負載平衡,並將其中一個叢集指定為機群的設定叢集。
在 Cloud Shell 建立 Cloud Armor 安全性政策:
gcloud compute security-policies create edge-fw-policy \ --description "Block XSS attacks"為安全性政策建立規則:
gcloud compute security-policies rules create 1000 \ --security-policy edge-fw-policy \ --expression "evaluatePreconfiguredExpr('xss-stable')" \ --action "deny-403" \ --description "XSS attack filtering"建立安全政策的 YAML 檔案,並透過對應的
ServiceImportYAML 檔案參照ServiceExportYAML 檔案:cat <<EOF > ${WORKDIR}/cloud-armor-backendpolicy.yaml apiVersion: networking.gke.io/v1 kind: GCPBackendPolicy metadata: name: cloud-armor-backendpolicy namespace: ingress-gateway spec: default: securityPolicy: edge-fw-policy targetRef: group: net.gke.io kind: ServiceImport name: asm-ingressgateway EOF將 Cloud Armor 政策套用至兩個叢集:
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml建立自訂 YAML 檔案,讓負載平衡器對兩個叢集中的 Ingress 閘道 Pod 的 Envoy 健康狀態端點 (路徑
/healthz/ready上的連接埠15021) 執行健康狀態檢查:cat <<EOF > ${WORKDIR}/ingress-gateway-healthcheck.yaml apiVersion: networking.gke.io/v1 kind: HealthCheckPolicy metadata: name: ingress-gateway-healthcheck namespace: ingress-gateway spec: default: config: httpHealthCheck: port: 15021 portSpecification: USE_FIXED_PORT requestPath: /healthz/ready type: HTTP targetRef: group: net.gke.io kind: ServiceImport name: asm-ingressgateway EOF將上一個步驟中建立的自訂 YAML 檔案套用至兩個叢集:
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml為機群啟用多叢集負載平衡,並將
CLUSTER_1_NAME指定為設定叢集:gcloud container fleet ingress enable \ --config-membership=${CLUSTER_1_NAME} \ --location=${CLUSTER_1_REGION}在車隊中授予 Gateway 控制器的 IAM 權限:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-multiclusteringress.iam.gserviceaccount.com" \ --role "roles/container.admin"透過參照
gke-l7-global-external-managed-mcgatewayClass和先前建立的靜態 IP 位址,建立負載平衡器 YAML 檔案:cat <<EOF > ${WORKDIR}/frontend-gateway.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-http namespace: ingress-gateway annotations: networking.gke.io/certmap: mcg-cert-map spec: gatewayClassName: gke-l7-global-external-managed-mc listeners: - name: http # list the port only so we can redirect any incoming http requests to https protocol: HTTP port: 80 - name: https protocol: HTTPS port: 443 allowedRoutes: kinds: - kind: HTTPRoute addresses: - type: NamedAddress value: mcg-ip EOF將
frontend-gatewayYAML 檔案套用至兩個叢集。除非您將其他設定叢集指定為授權叢集,否則只有CLUSTER_1_NAME具有授權:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml建立名為
default-httproute.yaml的HTTPRouteYAML 檔案,指示 Gateway 資源將要求傳送至 Ingress Gateway:cat << EOF > ${WORKDIR}/default-httproute.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: default-httproute namespace: ingress-gateway spec: parentRefs: - name: external-http namespace: ingress-gateway sectionName: https rules: - backendRefs: - group: net.gke.io kind: ServiceImport name: asm-ingressgateway port: 443 EOF將上一個步驟中建立的
HTTPRouteYAML 檔案套用至兩個叢集:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute.yaml如要執行從 HTTP 到 HTTP(S) 的重新導向,請建立名為
default-httproute-redirect.yaml的額外HTTPRouteYAML 檔案:cat << EOF > ${WORKDIR}/default-httproute-redirect.yaml kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-to-https-redirect-httproute namespace: ingress-gateway spec: parentRefs: - name: external-http namespace: ingress-gateway sectionName: http rules: - filters: - type: RequestRedirect requestRedirect: scheme: https statusCode: 301 EOF將重新導向
HTTPRouteYAML 檔案套用至兩個叢集:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml檢查 Gateway 資源,確認負載平衡器部署進度:
kubectl --context=${CLUSTER_1_NAME} describe gateway external-http -n ingress-gateway輸出內容會顯示您在這個部分輸入的資訊。
部署 whereami 範例應用程式
本指南會使用 whereami 做為範例應用程式,直接回報哪些叢集正在回覆要求。以下章節會在兩個叢集分別設定 whereami 的部署作業:frontend 部署作業和 backend 部署作業。
frontend 部署作業是第一個收到要求的作業。接著呼叫 backend 部署作業。
這個模型用於展示多服務應用程式架構。frontend 和 backend 服務會部署到這兩個叢集。
在 Cloud Shell 中,為兩個叢集建立 whereami
frontend和 whereamibackend的命名空間,並啟用命名空間插入功能:kubectl --context=${CLUSTER_1_NAME} create ns frontend kubectl --context=${CLUSTER_1_NAME} label namespace frontend istio-injection=enabled kubectl --context=${CLUSTER_1_NAME} create ns backend kubectl --context=${CLUSTER_1_NAME} label namespace backend istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} create ns frontend kubectl --context=${CLUSTER_2_NAME} label namespace frontend istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} create ns backend kubectl --context=${CLUSTER_2_NAME} label namespace backend istio-injection=enabled為 whereami
backend建立 kustomize 變體:mkdir -p ${WORKDIR}/whereami-backend/base cat <<EOF > ${WORKDIR}/whereami-backend/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/kubernetes-engine-samples/quickstarts/whereami/k8s EOF mkdir ${WORKDIR}/whereami-backend/variant cat <<EOF > ${WORKDIR}/whereami-backend/variant/cm-flag.yaml apiVersion: v1 kind: ConfigMap metadata: name: whereami data: BACKEND_ENABLED: "False" # assuming you don't want a chain of backend calls METADATA: "backend" EOF cat <<EOF > ${WORKDIR}/whereami-backend/variant/service-type.yaml apiVersion: "v1" kind: "Service" metadata: name: "whereami" spec: type: ClusterIP EOF cat <<EOF > ${WORKDIR}/whereami-backend/variant/kustomization.yaml nameSuffix: "-backend" namespace: backend labels: - includeSelectors: true includeTemplates: true pairs: app: whereami-backend resources: - ../base patches: - path: cm-flag.yaml target: kind: ConfigMap - path: service-type.yaml target: kind: Service EOF將 whereami
backend變體套用至兩個叢集:kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-backend/variant kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-backend/variant為 whereami
frontend建立 kustomize 變體:mkdir -p ${WORKDIR}/whereami-frontend/base cat <<EOF > ${WORKDIR}/whereami-frontend/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/kubernetes-engine-samples/quickstarts/whereami/k8s EOF mkdir whereami-frontend/variant cat <<EOF > ${WORKDIR}/whereami-frontend/variant/cm-flag.yaml apiVersion: v1 kind: ConfigMap metadata: name: whereami data: BACKEND_ENABLED: "True" BACKEND_SERVICE: "http://whereami-backend.backend.svc.cluster.local" EOF cat <<EOF > ${WORKDIR}/whereami-frontend/variant/service-type.yaml apiVersion: "v1" kind: "Service" metadata: name: "whereami" spec: type: ClusterIP EOF cat <<EOF > ${WORKDIR}/whereami-frontend/variant/kustomization.yaml nameSuffix: "-frontend" namespace: frontend labels: - includeSelectors: true includeTemplates: true pairs: app: whereami-frontend resources: - ../base patches: - path: cm-flag.yaml target: kind: ConfigMap - path: service-type.yaml target: kind: Service EOF將 whereami
frontend變體套用至兩個叢集:kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-frontend/variant kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-frontend/variant建立
VirtualServiceYAML 檔案,將要求轉送至 whereamifrontend:cat << EOF > ${WORKDIR}/frontend-vs.yaml apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: whereami-vs namespace: frontend spec: gateways: - ingress-gateway/asm-ingressgateway hosts: - 'frontend.endpoints.PROJECT_ID.cloud.goog' http: - route: - destination: host: whereami-frontend port: number: 80 EOF將
frontend-vsYAML 檔案套用至兩個叢集:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-vs.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-vs.yaml現在您已將
frontend-vs.yaml部署至兩個叢集,請嘗試呼叫叢集的公開端點:curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq輸出結果會與下列內容相似:
{ "backend_result": { "cluster_name": "edge-to-mesh-02", "gce_instance_id": "8396338201253702608", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "whereami-backend.backend.svc.cluster.local", "metadata": "backend", "node_name": "gk3-edge-to-mesh-02-pool-2-675f6abf-645h", "pod_ip": "10.124.0.199", "pod_name": "whereami-backend-7cbdfd788-8mmnq", "pod_name_emoji": "📸", "pod_namespace": "backend", "pod_service_account": "whereami-backend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T03:46:24", "zone": "us-east4-b" }, "cluster_name": "edge-to-mesh-01", "gce_instance_id": "1047264075324910451", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "frontend.endpoints.e2m-mcg-01.cloud.goog", "metadata": "frontend", "node_name": "gk3-edge-to-mesh-01-pool-2-d687e3c0-5kf2", "pod_ip": "10.54.1.71", "pod_name": "whereami-frontend-69c4c867cb-dgg8t", "pod_name_emoji": "🪴", "pod_namespace": "frontend", "pod_service_account": "whereami-frontend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T03:46:24", "zone": "us-central1-c" }
如果多次執行 curl 指令,您會發現回應 (來自 frontend 和 backend) 來自不同區域。負載平衡器會在回應中提供地理位置路由。也就是說,負載平衡器會將用戶端的要求轉送至最近的現用叢集,但要求仍會隨機送達。要求偶爾會從一個區域傳送到另一個區域,這會增加延遲時間和費用。
在下一節中,您會在服務網格中實作地區負載平衡,確保要求留在本地。
為 whereami 啟用及測試地區負載平衡
在本節中,您將在服務網格中實作區域負載平衡,確保要求在本機處理。您也會執行一些測試,瞭解 whereami 如何處理各種失敗情境。
當您向 whereami frontend 服務提出要求時,負載平衡器會將要求傳送至相對於用戶端延遲時間最短的叢集。也就是說,網格內的 Ingress 閘道 Pod 會將要求負載平衡至兩個叢集中的 whereami frontend Pod。本節將在網格中啟用地區負載平衡,解決這個問題。
在 Cloud Shell 中,建立
DestinationRuleYAML 檔案,啟用區域性負載平衡區域容錯移轉至frontend服務:cat << EOF > ${WORKDIR}/frontend-dr.yaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: frontend namespace: frontend spec: host: whereami-frontend.frontend.svc.cluster.local trafficPolicy: connectionPool: http: maxRequestsPerConnection: 0 loadBalancer: simple: LEAST_REQUEST localityLbSetting: enabled: true outlierDetection: consecutive5xxErrors: 1 interval: 1s baseEjectionTime: 1m EOF上述程式碼範例只會為
frontend服務啟用本機路由。您還需要額外設定來處理後端。將
frontend-drYAML 檔案套用至兩個叢集:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-dr.yaml建立
DestinationRuleYAML 檔案,啟用區域性負載平衡區域容錯移轉至backend服務:cat << EOF > ${WORKDIR}/backend-dr.yaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: backend namespace: backend spec: host: whereami-backend.backend.svc.cluster.local trafficPolicy: connectionPool: http: maxRequestsPerConnection: 0 loadBalancer: simple: LEAST_REQUEST localityLbSetting: enabled: true outlierDetection: consecutive5xxErrors: 1 interval: 1s baseEjectionTime: 1m EOF將
backend-drYAML 檔案套用至兩個叢集:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/backend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/backend-dr.yaml將兩組
DestinationRuleYAML 檔案套用至兩個叢集後,要求仍會保留在要求路由至的叢集。如要測試
frontend服務的容錯移轉,請減少主要叢集中 Ingress 閘道的副本數量。從多區域負載平衡器的角度來看,這項動作會模擬叢集故障。這會導致叢集無法通過負載平衡器健康狀態檢查。本範例使用
CLUSTER_1_REGION中的叢集。您應該只會看到CLUSTER_2_REGION中叢集的回應。將主要叢集中 Ingress 閘道的副本數減少至零,並呼叫公開端點,確認要求已容錯移轉至其他叢集:
kubectl --context=${CLUSTER_1_NAME} -n ingress-gateway scale --replicas=0 deployment/asm-ingressgateway輸出應會如下所示:
$ curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq { "backend_result": { "cluster_name": "edge-to-mesh-02", "gce_instance_id": "2717459599837162415", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "whereami-backend.backend.svc.cluster.local", "metadata": "backend", "node_name": "gk3-edge-to-mesh-02-pool-2-675f6abf-dxs2", "pod_ip": "10.124.1.7", "pod_name": "whereami-backend-7cbdfd788-mp8zv", "pod_name_emoji": "🏌🏽♀", "pod_namespace": "backend", "pod_service_account": "whereami-backend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T05:41:18", "zone": "us-east4-b" }, "cluster_name": "edge-to-mesh-02", "gce_instance_id": "6983018919754001204", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "frontend.endpoints.e2m-mcg-01.cloud.goog", "metadata": "frontend", "node_name": "gk3-edge-to-mesh-02-pool-3-d42ddfbf-qmkn", "pod_ip": "10.124.1.142", "pod_name": "whereami-frontend-69c4c867cb-xf8db", "pod_name_emoji": "🏴", "pod_namespace": "frontend", "pod_service_account": "whereami-frontend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T05:41:18", "zone": "us-east4-b" }如要恢復一般流量路徑,請將叢集中的 Ingress 閘道副本還原為原始值:
kubectl --context=${CLUSTER_1_NAME} -n ingress-gateway scale --replicas=3 deployment/asm-ingressgateway將主要區域中的副本數量減少至 0,模擬
backend服務發生故障:kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=0 deployment/whereami-backend確認
frontend服務的回應是透過負載平衡器來自us-central1主要區域,而backend服務的回應來自us-east4次要區域。輸出內容也應包含來自主要區域 (
us-central1) 的frontend服務回應,以及來自次要區域 (us-east4) 的backend服務回應,符合預期。將後端服務副本還原為原始值,即可恢復正常流量轉送:
kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=3 deployment/whereami-backend
您現在有一個全域 HTTP(S) 負載平衡器,可做為服務網格代管多區域應用程式的前端。
清除所用資源
如要避免系統向您的 Google Cloud 帳戶收取本次部署所用資源的費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。
刪除專案
- 前往 Google Cloud 控制台的「Manage resources」(管理資源) 頁面。
- 在專案清單中選取要刪除的專案,然後點選「Delete」(刪除)。
- 在對話方塊中輸入專案 ID,然後按一下 [Shut down] (關閉) 以刪除專案。
刪除個別資源
如要保留在此部署作業中使用的 Google Cloud 專案,請刪除個別資源:
在 Cloud Shell 中,刪除
HTTPRoute資源:kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/default-httproute.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/default-httproute.yaml刪除 GKE Gateway 資源:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml刪除政策:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/cloud-armor-backendpolicy.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/cloud-armor-backendpolicy.yaml刪除服務匯出項目:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yaml刪除 Cloud Armor 資源:
gcloud --project=PROJECT_ID compute security-policies rules delete 1000 --security-policy edge-fw-policy --quiet gcloud --project=PROJECT_ID compute security-policies delete edge-fw-policy --quiet刪除 Certificate Manager 資源:
gcloud --project=PROJECT_ID certificate-manager maps entries delete mcg-cert-map-entry --map="mcg-cert-map" --quiet gcloud --project=PROJECT_ID certificate-manager maps delete mcg-cert-map --quiet gcloud --project=PROJECT_ID certificate-manager certificates delete mcg-cert --quiet刪除端點 DNS 項目:
gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quiet刪除靜態 IP 位址:
gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quiet刪除 GKE Autopilot 叢集。這個步驟需要幾分鐘才能完成。
gcloud --project=PROJECT_ID container clusters delete ${CLUSTER_1_NAME} --region ${CLUSTER_1_REGION} --quiet gcloud --project=PROJECT_ID container clusters delete ${CLUSTER_2_NAME} --region ${CLUSTER_2_REGION} --quiet
後續步驟
- 瞭解更多 GKE 閘道提供的功能,可與服務網格搭配使用。
- 瞭解 GKE 適用的不同類型 Cloud Load Balancing。
- 瞭解 Cloud Service Mesh 提供的功能。
- 如要查看更多參考架構、圖表和最佳做法,請瀏覽 Cloud Architecture Center。
貢獻者
作者:
- Alex Mattson | 應用程式專員工程師
- Mark Chilvers | 應用程式專員工程師
其他貢獻者:
- Abdelfettah Sghiouar | Cloud 開發人員服務代表
- Greg Bray | 客戶工程師
- Paul Revello | 雲端解決方案架構師
- Valavan Rajakumar | 主要企業架構師