利用 Cloud Run 服务健康状况自动执行跨区域故障切换

本文档介绍如何配置和部署具有自动故障切换和故障恢复功能的高可用性多区域 Cloud Run 服务。

Cloud Run 服务健康状况使用无服务器网络端点组 (NEG) 公开您的服务在每个区域中的汇总健康状况。

工作原理

自动故障切换会将来自全球外部应用负载平衡器或跨区域内部应用负载平衡器的传入请求通过区域级无服务器 NEG 路由到您的 Cloud Run 服务。各个容器实例运行就绪性探测,Cloud Run 会汇总这些探测以确定每个区域级服务的整体健康状况。

如果某个区域中的 Cloud Run 服务有 60% 或更多的实例通过了就绪性探测,则该服务健康状况良好并会接收流量。如果某个区域的健康状况不佳,负载均衡器会自动将流量重定向到健康状况良好的区域。健康状况不佳的区域恢复后,负载均衡器会逐渐恢复向其发送流量。

限制

以下限制适用于 Cloud Run 服务健康状况:

  • 您必须至少为每个区域配置一个服务级或修订版本级实例数下限,才能计算健康状况。您还可以使用 Cloud Monitoring 中的容器实例数指标来估算区域所需的实例数下限。
  • 故障切换至少需要两个来自不同区域的服务。否则,如果其中一个服务失败,系统会显示错误消息 no healthy upstream
  • 您无法在无服务器 NEG 中配置网址掩码或标签。
  • 您无法通过后端服务或负载均衡器启用 IAP。 直接从 Cloud Run 启用 IAP
  • 如果 Cloud Run 服务被删除,Cloud Run 不会向负载均衡器报告不健康状况。
  • 启动新实例时,系统不会计入第一次就绪性探测,因此请求可能会在变为健康状况不佳之前短暂地路由到新启动的服务。
  • Cloud Run 服务健康状况是根据所有实例计算得出的。 没有探测的修订版本会被视为未知。负载均衡器会将未知实例视为健康状况良好。
  • 如果实例快速崩溃,服务健康状况计算可能会产生不准确的结果。

最佳做法

您可以结合使用就绪性探测、流量拆分和实例数下限,以安全、逐步地执行发布。这样,您就可以在提升新修订版本之前,在单个“Canary”区域中验证其健康状况,确保负载均衡器仅将流量发送到健康状况良好的区域级后端。

在您自己的应用上配置探测时,请在服务代码中添加 HTTP/1 端点(Cloud Run 默认端点,而非 HTTP/2)以响应探测。端点名称(例如 /startup/health/are_you_ready)必须与探测配置中的 path 相匹配。HTTP 健康检查端点可从外部访问,并且遵循与外部公开的任何其他 HTTP 服务端点相同的原则。

您可以针对未使用就绪性探测或 Cloud Run 服务健康状况的现有 Cloud Run 服务发布服务修订版本。请一次对一个区域执行以下流程,以安全部署新修订版本:

  1. 在配置了就绪性探测的单个“Canary”区域中部署新修订版本。

  2. 向新修订版本发送少量流量(例如 1%)。

  3. 在服务级层使用非零实例数下限,而不是在修订版本级层使用。

  4. 检查就绪性探测指标 (run.googleapis.com/container/instance_count_with_readiness),确保新实例健康状况良好。

  5. 逐步增加流向新修订版本的流量百分比。在逐步增加流量的过程中,监控负载均衡器使用的区域级 Cloud Run 服务健康状况指标 (run.googleapis.com/service_health_count)。 在有足够的流量路由到新修订版本之前,Cloud Run 服务健康状况会报告 UNKNOWN

  6. 在修订版本收到 100% 的流量且区域级 Cloud Run 服务健康状况稳定且良好后,针对所有其他区域重复此流程。

教程:配置自动故障切换

本教程将指导您完成以下操作:将示例 Go 应用部署到两个区域,设置使用无服务器 NEG 的全球外部应用负载平衡器,以及测试自动故障切换。

在本教程中,您将学习以下操作:

  1. 准备示例应用
  2. 在两个区域中部署具有就绪性探测的 Cloud Run 服务
  3. 设置全球外部应用负载平衡器
  4. 通过无服务器 NEG 添加服务
  5. 测试故障切换

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

您可使用 价格计算器 根据您的预计使用情况来估算费用。

新 Google Cloud 用户可能有资格获得免费试用

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

  3. 启用 Artifact Registry API、Cloud Build API、Cloud Run Admin API、Network Services API 和 Compute Engine API。

    启用 API 所需的角色

    如需启用 API,您需要拥有 serviceusage.services.enable 权限。如果您 创建了项目,则可能已通过 Owner 角色 (roles/owner) 拥有此权限。否则,您可以通过 Service Usage Admin 角色 (roles/serviceusage.serviceUsageAdmin) 获得此权限。 了解如何授予角色

    启用 API

  4. 安装并初始化 gcloud CLI
  5. 更新组件:
    gcloud components update
  6. 设置本教程中使用的配置变量:
    PROJECT_ID= gcloud config set core/project PROJECT_ID
    PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)")
    SERVICE=health-example
    REGION_A=us-west1
    REGION_B=europe-west1
    PROJECT_ID 替换为您的 Google Cloud 项目 ID。

设置所需角色

如需使用 build 从源代码进行部署,您或您的管理员必须为 Cloud Build 服务帐号授予以下 IAM 角色。

点击可查看 Cloud Build 服务账号需要的角色

除非您替换此行为,否则 Cloud Build 会自动使用 Compute Engine 默认服务账号作为默认 Cloud Build 服务账号来构建源代码和 Cloud Run 资源。为了让 Cloud Build 能够构建来源,请让管理员向项目的 Compute Engine 默认服务账号授予 Cloud Run Builder (roles/run.builder):

  gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=serviceAccount:PROJECT_NUMBER-compute@ \
      --role=roles/run.builder
  

PROJECT_NUMBER 替换为您的 Google Cloud项目编号,将 PROJECT_ID 替换为您的 Google Cloud项目 ID。如需详细了解如何查找项目 ID 和项目编号,请参阅创建和管理项目

向 Compute Engine 默认服务账号授予 Cloud Run Builder 角色需要几分钟时间才能传播

如需获得 服务身份 访问文件和 Cloud Storage 存储桶所需的权限,请让您的 管理员为服务身份授予 Storage Admin (roles/storage.admin) 角色。 如需详细了解 Cloud Storage 角色和权限,请参阅 适用于 Cloud Storage 的 IAM

如需查看与 Cloud Run 关联的 IAM 角色和权限的列表,请参阅 Cloud Run IAM 角色Cloud Run IAM 权限。如果您的 Cloud Run 服务与Google Cloud API(例如 Cloud 客户端库)进行交互,请参阅服务身份配置指南。如需详细了解如何授予角色,请参阅 部署权限管理访问权限

准备示例应用

如需检索可用的代码示例,请执行以下操作:

  1. 将示例代码库克隆到您的本地机器:

    git clone https://github.com/GoogleCloudPlatform/golang-samples
    
  2. 切换到包含 Cloud Run 示例代码的目录:

    cd golang-samples/run/service-health
    

在两个区域中部署具有就绪性探测的 Cloud Run 服务

故障切换至少需要两个服务来自 不同区域。如需在两个不同的区域中部署具有就绪性探测的服务,请运行以下命令。如果您偏好使用 Terraform,请参阅部署多区域服务 并确保添加就绪性探测配置

  1. 从源目录在 us-west1europe-west1 中部署服务 health-example。您需要至少一个实例数下限才能使用就绪性探测配置服务健康状况:

    gcloud run deploy $SERVICE \
    --source=. \
    --regions=$REGION_A,$REGION_B \
    --min=10 \
    --readiness-probe httpGet.path="/are_you_ready"
    
  2. 在系统提示时通过响应 y 来响应任何提示,以安装所需 API。您只需为项目执行一次此操作。如果您尚未按照“准备工作”部分中的说明为其他 提示设置默认值 ,请通过提供平台和区域来响应这些提示。

设置全球外部应用负载平衡器

如需设置全球外部应用负载平衡器以在 us-west1europe-west1 之间路由流量,请按照以下步骤操作。如果您偏好使用 Terraform 预配负载均衡器, 请参阅创建全球外部应用负载均衡器

  1. 创建后端服务:

    gcloud compute backend-services create $SERVICE-bs \
      --load-balancing-scheme=EXTERNAL_MANAGED \
      --global
    
  2. 设置全球静态外部 IP 地址以访问负载 均衡器:

    gcloud compute addresses create $SERVICE-ip \
      --network-tier=PREMIUM \
      --ip-version=IPV4 \
      --global
    
  3. 创建网址映射以将传入请求路由到相应后端服务:

    gcloud compute url-maps create $SERVICE-lb \
      --default-service $SERVICE-bs
    
  4. 创建一个目标 HTTP 代理,以将请求路由到您的网址映射:

    gcloud compute target-http-proxies create $SERVICE-hp \
    --url-map=$SERVICE-lb
    
  5. 创建转发规则以将传入请求路由到相应代理:

    gcloud compute forwarding-rules create $SERVICE-fr \
      --load-balancing-scheme=EXTERNAL_MANAGED \
      --network-tier=PREMIUM \
      --address=$SERVICE-ip \
      --target-http-proxy=$SERVICE-hp \
      --global \
      --ports=80
    

通过无服务器 NEG 添加服务

如需使用无服务器 NEG 添加您在 us-west1europe-west1 中部署的服务,请按照以下步骤操作。如果您偏好使用 Terraform 预配无服务器 NEG, 请参阅配置区域级网络端点组

  1. 创建无服务器网络端点组 (NEG) ,以便在us-west1europe-west1中用于您的 Cloud Run 服务:

    gcloud compute network-endpoint-groups create $SERVICE-neg-$REGION_A \
        --region $REGION_A \
        --network-endpoint-type=serverless \
        --cloud-run-service=$SERVICE
    
    gcloud compute network-endpoint-groups create $SERVICE-neg-$REGION_B \
        --region $REGION_B \
        --network-endpoint-type=serverless \
        --cloud-run-service=$SERVICE
    
  2. 将无服务器 NEG 作为后端添加到 us-west1europe-west1 中的后端服务:

    gcloud compute backend-services add-backend $SERVICE-bs \
        --global \
        --network-endpoint-group=$SERVICE-neg-$REGION_A \
        --network-endpoint-group-region=$REGION_A
    
    gcloud compute backend-services add-backend $SERVICE-bs \
        --global \
        --network-endpoint-group=$SERVICE-neg-$REGION_B \
        --network-endpoint-group-region=$REGION_B
    

如需了解其他配置选项,请参阅设置使用 Cloud Run的全球外部应用负载平衡器。

报告区域级健康状况

如需汇总区域级 Cloud Run 服务健康状况并向负载均衡器报告健康或不健康状况,请执行以下步骤:

  1. 在多个区域中部署具有一个或多个实例数下限的 Cloud Run 服务修订版本。运行以下命令以使用您在上一步中配置的就绪性探测:

    gcloud run deploy SERVICE_NAME \
    --regions=REGION_A,REGION_B \
    --min=MIN_INSTANCES

    替换以下内容:

    • SERVICE_NAME:服务的名称。
    • REGION_AREGION_B:服务修订版本的不同区域 。例如,将 REGION_A 设置为 us-central1 并将 REGION_B 设置为 europe-west1
    • MIN_INSTANCES:要保持备用状态以准备接收请求的容器实例数量。 您必须将最小值设置为 1 或以上。
  2. 在每个容器实例上配置 gRPC 或 HTTP 就绪性探测

  3. 配置全球外部应用负载平衡器跨区域内部应用负载平衡器 ,以将流量从健康状况不佳的区域转移出去。

  4. 为每个区域中的每个 Cloud Run 服务设置无服务器 NEG

  5. 配置后端服务以与无服务器 NEG 连接。

了解如何将示例 Cloud Run 应用部署到两个具有就绪性探测的区域

测试和验证故障切换

如需测试故障切换以确保 Cloud Run 服务的可靠性和弹性,请按照以下步骤操作:

  1. 运行以下命令以获取负载均衡器的 IP 地址:

    LBIP=$(gcloud compute addresses describe $SERVICE-ip --global --format='value(address)')
    
  2. 可选:如果您的服务需要进行身份验证,请向负载均衡器发送请求:

    curl  -H "Authorization: Bearer $(gcloud auth print-identity-token)" $LBIP
    
  3. 运行 echo $LBIP 命令以获取 LBIP 变量的值。此命令会输出负载平衡器的 IP 地址。例如,11.22.33.44

  4. 如需测试故障切换,请前往 http://LOAD_BALANCER_IP 网址,其中 LOAD_BALANCER_IP 是您在上一步中获得的值。 在服务区域 部分中,点击相应区域的切换按钮。这会指定健康状况良好的区域和处理流量的实例:

    利用 Cloud Run 服务健康状况自动执行跨区域故障切换

监控健康检查

设置 Cloud Run 服务健康状况后,无服务器 NEG 会收集 Cloud Monitoring 服务健康状况指标。您可以查看现有区域级服务的健康状况。

如果某个区域中的服务健康状况不佳,负载均衡器会将流量从健康状况不佳的区域转移到健康状况良好的区域。该区域再次变为健康状况良好后,流量也会恢复。

通过多区域部署使用经过身份验证的 Pub/Sub 推送订阅

默认情况下,Pub/Sub 服务将消息传送到 Pub/Sub 服务存储消息的同一 Google Cloud 区域中的推送端点。如需查看此行为的解决方法,请参阅 将经过身份验证的 Pub/Sub 推送订阅与多区域 Cloud Run 部署搭配使用

替代方案:配置手动故障切换

如果您需要手动配置流量以故障切换到健康状况良好的区域,而无需依赖探测,请修改全球外部应用负载平衡器网址映射。

  1. 如需更新全球外部应用负载平衡器网址映射,请使用 --global 标志从后端服务中移除 NEG:

    gcloud compute backend-services remove-backend BACKEND_NAME \
    --network-endpoint-group=NEG_NAME \
    --network-endpoint-group-region=REGION \
    --global
    

    替换以下内容:

    • BACKEND_NAME:后端服务的名称。
    • NEG_NAME:网络端点组资源的名称,例如 myservice-neg-uscentral1
    • REGION:在其中创建 NEG 以及要从中移除服务的区域。例如 us-central1,asia-east1
  2. 如需确认健康状况良好的区域现在正在处理流量,请前往 https://<domain-name>

为避免您的 Google Cloud 账号产生额外费用,请删除您在本教程中部署的所有 资源。

删除项目

如果您为本教程创建了一个新项目,请删除项目。 如果您使用的是某个现有项目,并且需要保留此项目但不保留在本教程中所做的更改,请删除为本教程创建的资源

为了避免产生费用,最简单的方法是删除您为本教程创建的项目。

要删除项目,请执行以下操作:

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

    转到“管理资源”

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

删除教程资源

  1. 删除您在本教程中部署的 Cloud Run 服务。Cloud Run 服务在收到请求之前不会产生费用。

    如需删除 Cloud Run 服务,请运行以下命令:

    gcloud run services delete SERVICE-NAME

    SERVICE-NAME 替换为服务的名称。

    您还可以通过Google Cloud 控制台删除 Cloud Run 服务。

  2. 移除您在教程设置过程中添加的 gcloud 默认区域配置:

     gcloud config unset run/region
    
  3. 移除项目配置:

     gcloud config unset project
    

后续步骤