迁移到多集群网络

Last reviewed 2022-02-17 UTC

多集群网络是一款有价值的工具,可用于实现区域高可用性、通过全球分布式用户邻近区域缩短延迟时间以及组织之间的团队隔离等用例。Google Kubernetes Engine (GKE) 为多集群网络提供内置功能,您可以在一组 GKE 集群中大规模启用和使用这些功能。此功能还能够让您在 GKE Standard 和 Autopilot 之间组合或迁移已部署的基础设施,以满足每个应用的架构需求。

借助 GKE Autopilot 集群,Google 负责管理基础设施,包括控制平面和节点。如果要改为配置和管理节点,不妨使用 GKE 提供的标准模式。如需详细了解模式之间的差异,请参阅选择集群操作模式

本页面通过多个部署拓扑演示了这些功能。您将学习如何获取部署在单个 GKE 集群中的应用,并将其迁移到跨 GKE Standard 和 Autopilot 集群进行多集群部署。您可以使用 GKE 多集群 Service 来处理东-西流量,使用多集群网关启用多集群北-南网络。

本页面面向使用或计划使用 GKE 跨多个 Kubernetes 集群部署服务的云架构师和运营团队。在阅读本页面内容之前,请确保您熟悉 Kubernetes

多集群 Service 和多集群网关

Kubernetes 可以在不同的云可用区使用单个控制层面运行,从而为您的服务提供弹性和更高的可用性。更进一步的,GKE 提供了 GKE 多集群 Service (MCS),它提供了跨集群服务发现和调用机制。使用此功能的服务可通过具有虚拟 IP 地址的集群进行发现和访问,这与集群中可访问的 ClusterIP Service 的行为相匹配。此方法具有以下优势:

  • Service 可以在同一区域内的多个集群中或在不同区域(东-西流量)之间进行负载均衡。
  • 可以实现跨区域服务的高可用性选项。
  • 有状态工作负载和无状态工作负载可以跨单独的集群进行部署和管理。
  • 跨集群使用共享服务。

如需详细了解如何部署 MCS,请参阅配置多集群Service

GKE 提供了使用 GKE Gateway Controller的 Kubernetes Gateway API 实现。网关允许 GKE 部署 Google Cloud 负载均衡器,为 GKE 上部署的服务提供入站(北-南)流量路由。GKE 还提供多集群网关 (MCG),它可以扩展 GKE 网关控制器以预配负载均衡器,以将流量路由到不同 GKE 集群上部署的服务。

下图展示了将 MCS 和 MCG 结合使用时,您可以从一个控制层面管理服务部署和流量路由的互补性方面:

多集群 Service 有助于在集群中的服务之间进行通信,而多集群网关会部署负载均衡器,以跨集群路由流量。

如需了解详情,请参阅部署多集群网关

迁移概览

GKE 多集群网络功能可受益于各种配置文件的工作负载。例如,您可能具有无状态组件,而由于爆发流量的模型更经济高效,您希望将其迁移到 Autopilot。

或者,您可能希望将应用前端放置在更靠近用户的位置。此方法可提供更短的延迟时间和缓存,从而改善应用性能和用户体验。同时,您可能具有一些应用所依赖的有状态组件,这些组件只能位于一个位置。此配置需要北-男、多集群负载均衡,以将客户端流量发送到该位置的正确集群。您还需要东-西多集群负载均衡,以跨集群发送流量以到达有状态组件。

本页面使用 Online Boutique 云微服务演示应用来演示多集群模式,该模式可用于增强单地区演示的部署。从应用的单地区版本开始。然后,您可以使用多集群 Service 和多集群网关添加高可用性和弹性元素,并利用 Autopilot 减少运营工作量。

初始单集群部署

在下图中,Online Boutique 应用最初部署到名为 std-west 的单个 GKE Standard 模式集群,并使用 LoadBalancer Service 公开:

一个标准模式 GKE 集群,用于运行使用常规 HTTP 外部 LoadBalancer 服务公开的所有服务。

迁移到多集群 Service

在下一个中间步骤中,您将创建两个额外的集群,无状态服务部署在其他区域中。您在与单个 std-west GKE Standard 集群不同的两个独立区域中创建两个名为 auto-east 和 auto-central 的 GKE Autopilot 集群,并将这些集群注册到 Google Cloud 舰队

舰队是一种 Google Cloud 概念,舰队以逻辑方式组织集群和其他资源,让您可以使用和管理多集群功能,并在您的所有系统中应用一致的政策。

您可以使用 ServiceExport 将 onlineboutique 命名空间中 std-west 集群上的 cartservice 导出到新的舰队集群。您将在三个集群上都部署 Online Boutique 的前端 Service,并通过 ClusterIP 服务公开该服务。然后,使用 ServiceExports 将服务导出到集群组。Online Boutique 的中间件层等服务(如 productcatalogshippingadservice)也会部署到所有三个集群中。

在队列的任何集群中运行的 Pod 可以通过向该服务的 ClusterSet URI 发送请求来访问导出的 Service。请求路由到支持服务的端点。

前端 Service 能够在本地集群中使用中间件服务(例如 productcatalogservicecurrencyservice)。此架构有助于将传入请求保持在前端响应请求的区域本地,并避免不必要的区域间网络流量费用。

下图展示了两项多集群 Service。无状态前端 Service 将部署到三个集群,有状态后端 cartservice 会部署到一个集群。该图还显示,在此中间步骤中,前端服务的入站流量仍然使用由前端外部 LoadBalancer Service 创建的区域级外部直通式网络负载平衡器路由到 us-west1 中的原始 GKE Standard 集群:

多集群 Service 在三个 GKE 集群中运行,但流量仍然使用常规 HTTP 外部 LoadBalancer 服务定向到单个集群。

迁移到多集群网关

在最后一步中,您使用多集群网关将前端 Service 的入站流量从集群客户端请求路由到集群中多个集群中的服务。

名为 config-central 的第四个集群会添加到队列中,用于托管和管理作为此配置的一部分创建的网关HTTPRoute 资源的配置。HTTPRoute 资源会将 / 前缀映射到前端 ServiceImport。将 Online Boutique 的前端的流量发送到其中一个可用区域中运行状况良好的端点。此方法使 Online Boutique 应用架构具有高可用性的元素。

在下图中,多集群网关部署了一个全局 Cloud 负载均衡器,该负载均衡器将外部流量路由到部署在三个应用集群上的每个集群的无状态前端 Service。

多集群 Service 在三个 GKE 集群中运行,并且流量现在使用多集群外部网关分布在所有集群的前端服务中。

在最终状态下,这种有规律的模式展示了应用的有状态部分(cartserviceredis-cart)和无状态部分(frontendemailservicecheckoutservicerecommendationservicepaymentserviceproductcatalogservicecurrencyserviceshippingserviceadservice)之间的松散耦合。虽然不属于本页面讨论范围,但此方法为您提供了未来向有状态服务层增添弹性和高可用性的机会。

目标

  • 创建和配置 GKE Standard 和 Autopilot 集群。
  • 将 Online Boutique 部署到地区 GKE Standard 集群。
  • 导出多集群 Services
  • 将清单部署到 Standard 集群和 Autopilot 集群。
  • 启用并配置多集群网关。
  • 测试多区域应用行为。

费用

在本文档中,您将使用 Google Cloud的以下收费组件:

如需根据您的预计使用情况来估算费用,请使用价格计算器

新 Google Cloud 用户可能有资格申请免费试用

准备工作

您的组织定义的安全限制条件可能会导致您无法完成以下步骤。如需了解相关问题排查信息,请参阅在受限的 Google Cloud 环境中开发应用

在开始之前,请确保满足以下要求:

  • 建议您为本指南使用一个新项目,因为最简单的清理是在完成项目后将其删除。
  • 本指南假定您具有Google Cloud 项目的 Owner IAM 角色。对于生产或实际设置,最佳做法是将权限范围限定为最小权限。如需了解详情,请参阅安全使用 IAM明确验证每次访问尝试
  • 熟悉 Online Boutique 微服务演示应用架构。

准备环境

在本指南中,您将使用 Cloud Shell 输入命令。Cloud Shell 让您能够使用Google Cloud 控制台中的命令行,并且包含 Google Cloud SDK 和其他工具,例如 Google Cloud CLI。Cloud Shell 在Google Cloud 控制台底部显示为一个窗口。初始化可能需要几分钟,但窗口会立即显示。

  1. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

  2. 在 Cloud Shell 中,定义本指南中使用的环境变量。 请将 PROJECT_ID 替换为您自己的项目 ID:

    export PROJECT=PROJECT_ID
    gcloud config set project ${PROJECT}
    
  3. 启用此页面上所述步骤所需的服务:

    gcloud services enable \
        gkehub.googleapis.com \
        multiclusteringress.googleapis.com \
        dns.googleapis.com \
        trafficdirector.googleapis.com \
        cloudresourcemanager.googleapis.com \
        multiclusterservicediscovery.googleapis.com \
        container.googleapis.com
    
    gcloud container fleet multi-cluster-services enable
    

    多集群 Service 可管理 Google Cloud 组件,例如 Cloud DNS、防火墙规则和 Cloud Service Mesh,因此还必须启用这些 API。如需了解详情,请参阅 Cloud Service Mesh 概览

    输出类似于以下示例:

    Operation "operations/acf.p2-822685001869-ee4ebe78-6dd8-465e-b0fd-3b0e5f964bad"
    finished successfully.
    
    Waiting for Feature Multi-cluster Services to be created...done.
    
  4. 验证多集群 Service 是否显示 ACTIVE 状态:

    gcloud container fleet multi-cluster-services describe
    

    输出类似于以下示例:

    createTime: '2021-11-30T21:59:25.245190894Z'
    name: projects/PROJECT_ID/locations/global/features/multiclusterservicediscovery
    resourceState:
      state: ACTIVE
    spec: {}
    updateTime: '2021-11-30T21:59:27.459063070Z'
    

    如果状态的值不是 ACTIVE,请参阅多集群 Service 问题排查详情

创建和配置 GKE 集群

为了演示本指南中的多集群模式,您需要在三个单独的云区域中使用三个应用集群,并使用一个集群来托管网关资源的配置。您可以使用与项目关联的集群注册所有集群。一个 Google Cloud 项目只能包含一个队列。此项目称为队列宿主项目。

在本文档中,所有 GKE 集群都部署在同一项目中。共享 VPC 网络是在此项目中创建的,该项目也是舰队的项目。

  1. 创建 Standard 和 Autopilot GKE 集群,并将这些集群注册到项目的舰队:

    gcloud container clusters create std-west \
        --location us-west1-a \
        --num-nodes=6 \
        --enable-ip-alias \
        --release-channel regular \
        --workload-pool=${PROJECT}.svc.id.goog \
        --gateway-api=standard \
        --enable-fleet \
        --async \
    
    gcloud container clusters create-auto auto-east \
        --location us-east1 \
        --release-channel regular \
        --enable-fleet \
        --async
    
    gcloud container clusters create-auto auto-central \
        --location us-central1 \
        --release-channel regular \
        --enable-fleet \
        --async
    
    gcloud container clusters create config-central \
        --location us-central1 \
        --num-nodes=1 \
        --enable-ip-alias \
        --release-channel regular \
        --workload-pool=${PROJECT}.svc.id.goog \
        --gateway-api=standard \
        --enable-fleet \
        --async
    

    GKE Autopilot 集群上默认启用适用于 GKE 的工作负载身份联合,因此您不必使用 --workload-pool 标志,就像您在创建 GKE Standard 集群一样。

  2. 等待集群的状态PROVISIONING 更改为 RUNNING。该过程最多可能需要运行 10 分钟。您可以使用监控循环来监控进度:

    watch -n 20 --difference=permanent "gcloud container clusters list"
    

    输出类似于以下示例:

    NAME: auto-central
    LOCATION: us-central1
    MASTER_VERSION: 1.21.5-gke.1802
    MASTER_IP: 107.178.213.138
    MACHINE_TYPE: e2-medium
    NODE_VERSION: 1.21.5-gke.1802
    NUM_NODES: 3
    STATUS: PROVISIONING
    
    NAME: config-central
    LOCATION: us-central1
    MASTER_VERSION: 1.21.5-gke.1802
    MASTER_IP:
    MACHINE_TYPE: e2-medium
    NODE_VERSION: 1.21.5-gke.1802
    NUM_NODES: 9
    STATUS: PROVISIONING
    
    NAME: auto-east
    LOCATION: us-east1
    MASTER_VERSION: 1.21.5-gke.1802
    MASTER_IP: 35.229.88.209
    MACHINE_TYPE: e2-medium
    NODE_VERSION: 1.21.5-gke.1802
    NUM_NODES: 3
    STATUS: PROVISIONING
    
    NAME: std-west
    LOCATION: us-west1-a
    MASTER_VERSION: 1.21.5-gke.1802
    MASTER_IP: 35.197.93.113
    MACHINE_TYPE: e2-medium
    NODE_VERSION: 1.21.5-gke.1802
    NUM_NODES: 6
    STATUS: PROVISIONING
    
  3. 在所有集群都处于 RUNNING 状态后,按 CTRL-C 中断命令。

  4. 添加 Identity and Access Management (IAM) 政策绑定,以向队列宿主项目 MCS 服务账号授予其自己项目的 Network User 角色:

    gcloud projects add-iam-policy-binding ${PROJECT} \
        --member "serviceAccount:${PROJECT}.svc.id.goog[gke-mcs/gke-mcs-importer]" \
        --role "roles/compute.networkViewer"
    

    您可以使用适用于 GKE 的工作负载身份联合向 MCS 服务授予对您的项目 VPC 网络配置的读取权限。因此,队列宿主项目的 MCS 导入程序 GKE 服务账号需要此角色。

    输出类似于以下示例:

    - members:
      - serviceAccount:PROJECT_ID.svc.id.goog[gke-mcs/gke-mcs-importer]
      role: roles/compute.networkViewer
    [...]
    
  5. 在舰队宿主项目中创建 IAM 绑定,将 GKE Service Agent 角色分配给项目的 GKE 舰队服务账号:

    gcloud projects add-iam-policy-binding ${PROJECT} \
        --member "serviceAccount:service-{${PROJECT}}@gcp-sa-gkehub.iam.gserviceaccount.com" \
        --role roles/gkehub.serviceAgent
    
  6. 在舰队宿主项目中创建 IAM 绑定,将 MCS Service Agent 角色分配给项目的 MCS 服务账号。

    gcloud projects add-iam-policy-binding ${PROJECT} \
        --member "serviceAccount:service-{${PROJECT}}@gcp-sa-mcsd.iam.gserviceaccount.com" \
        --role roles/multiclusterservicediscovery.serviceAgent
    
  7. 连接到集群并生成 kubeconfig 条目:

    gcloud container clusters get-credentials std-west \
        --location us-west1-a --project $PROJECT
    
    gcloud container clusters get-credentials auto-east \
        --location us-east1 --project $PROJECT
    
    gcloud container clusters get-credentials auto-central \
        --location us-central1 --project $PROJECT
    
    gcloud container clusters get-credentials config-central \
        --location us-central1 --project $PROJECT
    

    对于每个命令,输出类似于以下示例:

    Fetching cluster endpoint and auth data.
    kubeconfig entry generated for std-west.
    
  8. 重命名集群的上下文,以便在本页面的其余部分更轻松地使用集群:

    kubectl config rename-context \
        gke_${PROJECT}_us-west1-a_std-west \
        std-west
    
    kubectl config rename-context \
        gke_${PROJECT}_us-east1_auto-east \
        auto-east
    
    kubectl config rename-context \
        gke_${PROJECT}_us-central1_auto-central \
        auto-central
    
    kubectl config rename-context \
        gke_${PROJECT}_us-central1_config-central \
        config-central
    

    在本指南中,上下文根据其位置命名。虽然您可以提供备用名称,但本指南中的其余步骤将使用此步骤中使用的名称。

在 GKE Standard 上部署 Online Boutique

在演示部署的第一步中,您将全套 Online Boutique 应用服务部署到 us-west1 中的单个 GKE Standard 集群 std-west

  1. std-west 上创建命名空间 onlineboutique

    kubectl create namespace onlineboutique --context std-west
    

    输出类似于以下示例:

    namespace/onlineboutique created
    
  2. 克隆 Online Boutique GitHub 代码库并设置 WORKDIR 变量:

    cd ~
    
    git clone --branch release/v0.4.1 \
        https://github.com/GoogleCloudPlatform/microservices-demo.git
    
    cd microservices-demo/release && export WORKDIR=`pwd`
    
  3. std-west 上部署 Online Boutique。此过程为 Online Boutique 的所有微服务创建 DeploymentsServices,并包含一个在外部公开 Online Boutique 前端服务的 LoadBalancer 类型 Service:

    cd $WORKDIR
    
    kubectl apply -f kubernetes-manifests.yaml \
        -n onlineboutique --context=std-west
    
  4. 等待 LoadBalancer Service 获取外部 IP:

    watch -n 20 --difference=permanent \
         "kubectl get svc frontend-external -n onlineboutique --context=std-west"
    

    一开始,输出类似于以下示例:

    NAME                TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
    frontend-external   LoadBalancer   10.60.5.62   <pending>     80:30359/TCP   43s
    

    Service 准备就绪后,EXTERNAL-IP 列将显示负载均衡器的公共 IP 地址。

  5. Service 准备就绪后,获取负载均衡器的外部 IP 地址,并使用 curl 来验证前端是否已准备就绪。如果此 curl 命令返回错误,请稍等片刻,然后重试:

      curl $(kubectl get svc frontend-external \
          -n onlineboutique --context=std-west \
          -o=jsonpath="{.status.loadBalancer.ingress[0].ip}") | \
            grep -e Cluster -e Zone -e Pod
    

    curl 命令的成功输出类似于以下示例:

    <b>Cluster: </b>std-west<br/>
    <b>Zone: </b>us-west1-a<br/>
    <b>Pod: </b>frontend-b7bddcc97-wdjsk
    

您现在有一个在 us-west1-a 中运行的单地区版本的 Online Boutique。 您还可以使用网络浏览器导航到分配给 frontend-external LoadBalancer Service 的外部 IP,以访问应用并观察其行为。初始部署如下图所示:

单个标准模式 GKE 集群,用于运行通过常规 HTTP 外部 LoadBalancer 服务公开的所有服务。

将 cartservice 导出为多集群 Service

在本部分中,您将开始向应用添加高可用性元素。您将后端 cartservice 作为多集群 Service 导出到 GKE Autopilot 集群。

  1. 在其余集群上创建命名空间 onlineboutique

    kubectl create namespace onlineboutique --context auto-east
    
    kubectl create namespace onlineboutique --context auto-central
    
    kubectl create namespace onlineboutique --context config-central
    

    对于每个命令,输出类似于以下示例:

    namespace/onlineboutique created
    
  2. cartservicestd-west 集群导出到 ClusterSet 中的所有其他集群。ServiceExport 对象使用 GKE 多集群 Service 注册 cartservice 服务,以便导出到队列中存在命名空间 onlineboutique 的所有集群。如需了解详情,请参阅注册服务以进行导出

    cat <<EOF>> $WORKDIR/cartservice-export.yaml
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
     namespace: onlineboutique
     name: cartservice
    
    EOF
    
    kubectl apply -f $WORKDIR/cartservice-export.yaml \
        -n onlineboutique --context=std-west
    

将应用清单应用于多集群模式

在本部分中,您将应用两个精选清单来部署多集群模式。这些清单包含您之前应用于 std-west 集群的 kubernetes-manifests.yaml 的选定部分:

  • 第一个清单用于前端 DeploymentServiceServiceExport
  • 第二个清单用于将中间件 Servicesemailservicecheckoutservicerecommendationservicepaymentserviceproductcatalogservicecurrencyserviceshippingserviceadservice)部署到正在运行前端的所有区域。通过将请求长时间保留在某个区域本地,可以避免产生不必要的区域间网络流量费用。

在队列的任何集群中运行的 Pod 可以通过采用格式 SERVICE_NAME.NAMESPACE.svc.clusterset.local 向该服务的 ClusterSet URI 发送请求来访问导出的 Service。例如,所有三个示例集群中的前端 Deployments 都能够通过向 cartservice.onlineboutique.svc.clusterset.local 发出请求来使用 onlineboutique 命名空间中的 cartservice

因此,在每个清单中,cartservice 的主机名都更新为其 ClusterSet URI。这一步至关重要。如果此服务主机名未更新,则前端 Service 将要求使用 kube-dns 以获取 cartservice 而不是 cartservice.onlineboutique.svc.clusterset.local。此行为会导致 cartservice 本地版本不可用的集群出现 HTTP Status 500 错误,并导致前端 pod 运行状况不佳。

  1. 为包含清单的 GitHub 代码库设置环境变量:

    export MANIFEST_REPO_PATH=https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/cluster-migration
    
  2. 应用清单以将前端层部署到所有三个工作负载集群中:

    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-frontend-manifests.yaml \
        -n onlineboutique --context=std-west
    
    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-frontend-manifests.yaml \
        -n onlineboutique --context=auto-east
    
    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-frontend-manifests.yaml \
        -n onlineboutique --context=auto-central
    
  3. 应用清单以将中间件层部署到所有三个工作负载集群:

    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-middleware-manifests.yaml \
        -n onlineboutique --context=std-west
    
    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-middleware-manifests.yaml \
        -n onlineboutique --context=auto-east
    
    kubectl apply -f ${MANIFEST_REPO_PATH}/onlineboutique-middleware-manifests.yaml \
        -n onlineboutique --context=auto-central
    

现在,您已经有前端 DeploymentServiceServiceExportstd-westauto-eastauto-central 集群中处于活动状态。您还在每个集群中在本地运行了 Online Boutique 中间件服务。但是,外部流量仍然仅路由到 us-west1 中的初始集群中运行的 Service,如下图所示:

多集群 Service 在三个 GKE 集群中运行,但流量仍然使用常规 HTTP 外部 LoadBalancer 服务定向到单个集群。

启用和配置多集群网关

在本部分中,您将流量路由到所有三个集群中的前端的外部负载均衡。为了实现这种配置,请使用多集群网关 (MCG)。这些设置 MCG 的步骤遵循启用多集群网关中更详细的说明。

在这些步骤中,您将使用 config-central 集群来托管网关资源的配置。

  1. 确认所有集群都已成功注册到舰队:

    gcloud container fleet memberships list --project=$PROJECT
    

    以下示例输出表明所有集群都已成功注册:

    NAME: auto-central
    EXTERNAL_ID: 21537493-32ea-4a41-990d-02be2c1b319f
    
    NAME: config-central
    EXTERNAL_ID: 4369423e-ea7b-482d-a0eb-93b560e67b98
    
    NAME: std-west
    EXTERNAL_ID: 7fcb048b-c796-476b-9698-001a00f91ab3
    
    NAME: auto-east
    EXTERNAL_ID: aae2d2ff-b861-4a38-bcaf-612f14810012
    
  2. config-central 集群上安装 Gateway API 自定义资源定义

    kubectl --context=config-central kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.5.0" \
        | kubectl apply -f -
    

    此步骤会安装 Gateway API 自定义资源定义,包括 GatewayClassGatewayHTTPRoute 资源。自定义资源定义由 Kubernetes 网络特殊兴趣组维护。安装后,您可以使用 GKE 网关控制器。

  3. 为您的舰队启用多集群 Ingress(如果尚未启用)。启用此功能也会启用多集群网关控制器。

    gcloud container fleet ingress enable \
        --config-membership=config-central \
        --project=$PROJECT
    
    gcloud container fleet ingress describe --project=$PROJECT
    

    输出类似于以下示例:

    createTime: '2021-12-08T23:10:52.505888854Z'
    name: projects/PROJECT_ID/locations/global/features/multiclusteringress
    resourceState:
      state: ACTIVE
    spec:
      multiclusteringress:
        configMembership: projects/zl-mcs-expf61cbd13/locations/global/memberships/config-central
    state:
      state:
        code: OK
        description: Ready to use
        updateTime: '2021-12-08T23:11:37.994971649Z'
    updateTime: '2021-12-08T23:11:38.098244178Z'
    

    如果状态的值不是 ACTIVE,请参阅多集群 Ingress 的问题排查和操作

  4. 确认 config-central 集群上有 GatewayClasses

    kubectl get gatewayclasses --context=config-central
    

    输出类似于以下示例:

    NAME                                  CONTROLLER                  AGE
    gke-l7-global-external-managed        networking.gke.io/gateway   18s
    gke-l7-global-external-managed-mc     networking.gke.io/gateway   19s
    gke-l7-regional-external-managed      networking.gke.io/gateway   18s
    gke-l7-regional-external-managed-mc   networking.gke.io/gateway   19s
    gke-l7-gxlb                           networking.gke.io/gateway   74s
    gke-l7-gxlb-mc                        networking.gke.io/gateway   16s
    gke-l7-rilb                           networking.gke.io/gateway   74s
    gke-l7-rilb-mc                        networking.gke.io/gateway   16s
    

    不同的 GatewayClass 资源具有不同的功能。如需详细了解何时使用类型,请参阅 GatewayClass 功能

  5. external-http 网关资源部署到 config-central

    cat <<EOF>> $WORKDIR/external-http-gateway.yaml
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: external-http
      namespace: onlineboutique
    spec:
      gatewayClassName: gke-l7-global-external-managed-mc
      listeners:
      - protocol: HTTP
        port: 80
        name: http
    EOF
    
    kubectl apply -f external-http-gateway.yaml \
        -n onlineboutique --context=config-central
    

    gatewayClassName 字段所示,此资源属于 GatewayClass gke-l7-global-external-managed-mc,后者管理第 7 层外部 Cloud Load Balancing 并公开多集群应用。

  6. config-central 上部署名为 public-frontend-routeHTTPRoute

    cat <<EOF>> $WORKDIR/public-frontend-route.yaml
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: public-frontend-route
      namespace: onlineboutique
    spec:
      parentRefs:
      - name: "external-http"
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /
        backendRefs:
        - name: frontend
          group: net.gke.io
          kind: ServiceImport
          port: 80
    EOF
    
    kubectl apply -f public-frontend-route.yaml \
        -n onlineboutique --context=config-central
    

    当您部署 HTTPRoute 资源时,该资源会创建外部第 7 层 Cloud Load Balancing 资源并公开由在 std-westauto-eastauto-central 集群中运行的前端服务提供支持的前端 ServiceImport

    下图显示部署多集群网关后,流量如何路由到三个应用集群上的任何一个前端前端多集群 Service:

    多集群 Service 在三个 GKE 集群中运行,并且流量现在使用多集群外部网关分布在所有集群的前端服务中。

  7. 等待负载均衡器准备好已预配的外部 IP 地址,然后继续执行下一步。分配 IP 地址最多可能需要 10 分钟时间。您可以使用监控循环来监控进度。负载均衡器的名称采用 gkemcg-onlineboutique-external-http-k09mfhk74gop 格式:

    watch -n 20 --difference=permanent \
        "gcloud compute forwarding-rules list \
            | grep -A 5 NAME..*external-http"
    

    输出类似于以下示例:

    NAME: gkemcg-onlineboutique-external-http-k09mfhk74gop
    REGION:
    IP_ADDRESS: 34.149.29.176
    IP_PROTOCOL: TCP
    TARGET: gkemcg-onlineboutique-external-http-k09mfhk74gop
    
  8. 负载均衡器准备就绪后,在 Cloud Shell 中运行以下命令,以导出通过 external-http-gateway.yaml 应用创建的负载均衡器的外部 IP 地址public-frontend-route.yaml 清单:

    export EXTERNAL_LB_IP=$(kubectl --context=config-central \
                                -n onlineboutique get gateway external-http \
                                -o=jsonpath='{.status.addresses[0].value}')
    
  9. 使用适当的标头向负载均衡器发送请求后,它会返回前端服务传送的 HTML 内容。例如,由于您配置了 HTTPRoute 资源以将 store.example.com 主机名映射到前端 ServiceImport,因此在发出 HTTP 请求时必须提供 HOST 标头。如果以下 curl 示例返回错误,请等待几分钟,然后重试:

    curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
        grep -e Cluster -e Zone -e Pod
    

    curl 命令的成功输出类似于以下示例:

    <b>Cluster: </b>auto-central<br/>
    <b>Zone: </b>us-central1-f<br/>
    <b>Pod: </b>frontend-7c7d596ddc-jdh8f
    

测试应用多区域路由行为

使用多集群 Service 和多集群网关的一项强大功能是将外部请求路由到地理位置最近的集群。

如需测试应用多区域行为,请生成源自已部署集群的各个区域的流量。创建三个小型 pod,每个服务集群一个(std-westauto-eastauto-central),这可用于将 HTTP 请求发送到负载均衡器端点。结果使您可查看哪个前端 Pod 在响应。

  1. 创建客户端 pod:

    kubectl run --context=std-west \
                --image=radial/busyboxplus:curl client-west \
                -- sh -c 'while sleep 3600; do :; done'
    
    kubectl run --context=auto-east \
                --image=radial/busyboxplus:curl client-east \
                -- sh -c 'while sleep 3600; do :; done'
    
    kubectl run --context=auto-central \
                --image=radial/busyboxplus:curl client-central \
                -- sh -c 'while sleep 3600; do :; done'
    
  2. 在 pod 运行完毕之后,使用 curl 命令从 std-west 集群中的客户端 Pod 向负载均衡器端点发送请求并查看响应

    kubectl exec -it --context=std-west client-west \
        -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
               grep -e Cluster -e Zone -e Pod
    

    curl 命令的成功输出类似于以下示例:

    <b>Cluster: </b>std-west<br/>
    <b>Zone: </b>us-west1-a<br/>
    <b>Pod: </b>frontend-7cf48b79cf-trzc4
    
  3. auto-east 集群的客户端 Pod 运行相同的 curl 请求,并查看响应:

    kubectl exec -it --context=auto-east client-east \
        -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
               grep -e Cluster -e Zone -e Pod
    

    curl 命令的成功输出类似于以下示例:

    <b>Cluster: </b>auto-east<br/>
    <b>Zone: </b>us-east1-d<br/>
    <b>Pod: </b>frontend-6784b6df98-scdws
    

    由于这是一个 Autopilot 集群,因此集群可能需要预配其他资源来调度 Pod。如果您看到输出类似于以下示例,请稍等片刻,然后重试:

     Error from server (BadRequest): pod client-east does not have a host assigned
    
  4. auto-central 集群中的客户端 Pod 运行 curl,并检查响应:

    kubectl exec -it --context=auto-central client-central \
        -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
            grep -e Cluster -e Zone -e Pod
    

    curl 命令的成功输出类似于以下示例:

    <b>Cluster: </b>auto-central<br/>
    <b>Zone: </b>us-central1-b<br/>
    <b>Pod: </b>frontend-6784b6df98-x2fv4
    

    这些结果确认流量路由到距离请求来源最近的位置中的相应 pod。

测试应用多区域弹性

除了高效的流量路由之外,在多个区域运行服务还可以提供在罕见但仍然可能出现的基础架构故障情况下的弹性。

通过删除特定集群中的前端 Deployments 来测试行为,然后从这些区域的客户端 Pod 重试 curl 命令。观察应用是否仍然可用,并查看响应请求的 Pod 的位置。

  1. std-west 集群中的 client-west Pod 中运行 curl 命令,并可以看到结果来自 us-west1 中的前端:

    kubectl exec -it --context=std-west client-west \
        -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP  | \
               grep -e Cluster -e Zone -e Pod
    

    curl 命令的成功输出类似于以下示例:

    <b>Cluster: </b>std-west<br/>
    <b>Zone: </b>us-west1-a<br/>
    <b>Pod: </b>frontend-7cf48b79cf-trzc4
    
  2. 删除 std-west 集群中的前端 Deployment

    kubectl delete deploy frontend \
        -n onlineboutique --context=std-west
    

    输出类似于以下示例:

    deployment.apps "frontend" deleted
    
  3. std-west 集群中的 client-west Pod 发送另一个请求。您应该看到来自 auto-eastauto-central 集群的其余部分之一的前端 Deployments 的响应:

    kubectl exec -it --context=std-west client-west \
        -- curl -H 'HOST: store.example.com' $EXTERNAL_LB_IP | \
               grep -e Cluster -e Zone -e Pod
    

    类似以下示例的输出表明响应此请求的运行状况良好的 Pod 的位置:

    <b>Cluster: </b>auto-central<br/>
    <b>Zone: </b>us-central1-b<br/>
    <b>Pod: </b>frontend-6784b6df98-x2fv4
    

    <b>Cluster: </b>auto-east<br/>
    <b>Zone: </b>us-east1-d<br/>
    <b>Pod: </b>frontend-6784b6df98-scdws
    

    多次运行该命令以查看交替结果。

在此演示部署中,您已使用多集群 Service 和多集群网关向 Online Boutique 应用添加了弹性和地理分布元素。请求会路由到最近的地理区域,即使某个地区中的前端或中间件服务遇到问题,最终用户仍然可以成功使用该应用。

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

  1. 在 Google Cloud 控制台中,前往管理资源页面。

    转到“管理资源”

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

后续步骤