处理来自多个区域的流量

如需更快地响应面向全球用户的响应,您需要在多个区域部署服务,并将用户路由到最近的区域。

由于 Cloud Run 服务会部署到各个区域,因此您需要配置外部应用负载均衡器以将用户路由到服务的不同区域。

本指南介绍了如何通过由代管式 TLS 证书保护的网域配置外部应用负载均衡器,该负载均衡器指向一个全球任播 IP 地址(用于将用户路由到已部署您的服务的最近 Google 数据中心)。

当区域级 Cloud Run 服务无响应或开始返回错误时,本指南中所述的架构不会自动将请求路由到其他区域。如需提高多区域服务的可用性,您可以配置离群值检测,以根据 HTTP 错误率识别不健康的 Cloud Run 服务,并将某些请求分流到另一个区域。

创建负载均衡器

创建外部负载均衡器涉及创建各种网络资源并将它们连接在一起:

命令行

  1. 预留静态 IP 地址,这样您就无需在重新创建负载平衡器时更新 DNS 记录。
    gcloud compute addresses create --global SERVICE_IP
    在上述命令中,将 SERVICE_IP 替换为 IP 地址资源的名称(例如 myservice-ip)。

    此 IP 地址是一个全球任播 IPv4 地址,可路由到 Google 数据中心或离访问者最近的接入点。

  2. 创建后端服务。
    gcloud compute backend-services create --global BACKEND_NAME

    在上述命令中,将 BACKEND_NAME 替换为您要提供给后端服务的名称(例如 myservice-backend)。

  3. 创建网址映射。
    gcloud compute url-maps create URLMAP_NAME --default-service=BACKEND_NAME

    URLMAP_NAME 替换为您要提供给网址映射的名称(例如 myservice-urlmap)。

  4. 为您的网域创建代管式 TLS 证书,以处理 HTTPS 流量。(将 example.com 替换为您的域名。)
    gcloud compute ssl-certificates create CERT_NAME \
      --domains=example.com

    CERT_NAME 替换为您希望代管式 SSL 证书具有的名称(例如 myservice-cert)。

  5. 创建一个目标 HTTPS 代理。
    gcloud compute target-https-proxies create HTTPS_PROXY_NAME \
      --ssl-certificates=CERT_NAME \
      --url-map=URLMAP_NAME

    HTTPS_PROXY_NAME 替换为您要提供给目标 HTTPS 代理的名称(例如 myservice-https)。

  6. 创建一条转发规则,将您创建的网络资源连接到 IP 地址。
    gcloud compute forwarding-rules create --global FORWARDING_RULE_NAME \
      --target-https-proxy=HTTPS_PROXY_NAME \
      --address=SERVICE_IP \
      --ports=443

    FORWARDING_RULE_NAME 替换为您要创建的转发规则资源的名称(例如 myservice-lb)。

Terraform

除本部分介绍的步骤外,您还可以使用全球 HTTP 负载均衡器 Terraform 模块

将以下内容添加到 Terraform 文件(例如 main.tf)中:

  1. 配置 IP 地址:

    resource "google_compute_global_address" "lb_default" {
      provider = google-beta
      name     = "myservice-service-ip"
    
      # Use an explicit depends_on clause to wait until API is enabled
      depends_on = [
        google_project_service.compute_api
      ]
    }
    output "load_balancer_ip_addr" {
      value = google_compute_global_address.lb_default.address
    }

    将您的 IP 地址资源名称配置为 myservice-service-ip。您可以将此项更改为您自己的值。此 IP 地址是一个全球任播 IPv4 地址,可路由到 Google 数据中心或离访问者最近的接入点。

  2. 创建和配置后端服务:

    resource "google_compute_backend_service" "lb_default" {
      provider              = google-beta
      name                  = "myservice-backend"
      load_balancing_scheme = "EXTERNAL_MANAGED"
    
      backend {
        group = google_compute_region_network_endpoint_group.lb_default[0].id
      }
    
      backend {
        group = google_compute_region_network_endpoint_group.lb_default[1].id
      }
    
      # Use an explicit depends_on clause to wait until API is enabled
      depends_on = [
        google_project_service.compute_api,
      ]
    }

    此资源将后端服务配置为名为 myservice-backend。您可以将此项更改为您自己的值。

  3. 配置网址映射:

    resource "google_compute_url_map" "lb_default" {
      provider        = google-beta
      name            = "myservice-lb-urlmap"
      default_service = google_compute_backend_service.lb_default.id
    
      path_matcher {
        name            = "allpaths"
        default_service = google_compute_backend_service.lb_default.id
        route_rules {
          priority = 1
          url_redirect {
            https_redirect         = true
            redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
          }
        }
      }
    }

    将后端服务资源 (myservice-backend) 连接到新的网址映射资源 (myservice-lb-urlmap)。您可以将它们更改为您自己的值。

  4. 为您的网域创建代管式 TLS 证书,以传送 HTTPS 流量。将 example.com 替换为 google_compute_managed_ssl_certificate 资源中的域名:

    resource "google_compute_managed_ssl_certificate" "lb_default" {
      provider = google-beta
      name     = "myservice-ssl-cert"
    
      managed {
        domains = ["example.com"]
      }
    }
  5. 配置 HTTPS 代理:

    resource "google_compute_target_https_proxy" "lb_default" {
      provider = google-beta
      name     = "myservice-https-proxy"
      url_map  = google_compute_url_map.lb_default.id
      ssl_certificates = [
        google_compute_managed_ssl_certificate.lb_default.name
      ]
      depends_on = [
        google_compute_managed_ssl_certificate.lb_default
      ]
    }

    创建目标名称为 myservice-https-proxygoogle_compute_target_https_proxy 资源,并连接之前创建的 TLS 证书 (myservice-ssl-cert) 和网址映射资源 (myservice-lb-urlmap)。您可以将它们更改为您自己的值。

  6. 配置转发规则:

    resource "google_compute_global_forwarding_rule" "lb_default" {
      provider              = google-beta
      name                  = "myservice-lb-fr"
      load_balancing_scheme = "EXTERNAL_MANAGED"
      target                = google_compute_target_https_proxy.lb_default.id
      ip_address            = google_compute_global_address.lb_default.id
      port_range            = "443"
      depends_on            = [google_compute_target_https_proxy.lb_default]
    }

    创建目标名称为 myservice-https-proxygoogle_compute_global_forwarding_rule 资源,并连接先前创建的 HTTPS 代理目标 (myservice-https-proxy) 和 IP 地址资源 (myservice-service-ip)。您可以将它们更改为您自己的值。

  7. 应用此配置:

    如需在 Google Cloud 项目中应用 Terraform 配置,请完成以下部分中的步骤。

    准备 Cloud Shell

    1. 启动 Cloud Shell
    2. 设置要在其中应用 Terraform 配置的默认 Google Cloud 项目。

      您只需为每个项目运行一次以下命令,即可在任何目录中运行它。

      export GOOGLE_CLOUD_PROJECT=PROJECT_ID

      如果您在 Terraform 配置文件中设置显式值,则环境变量会被替换。

    准备目录

    每个 Terraform 配置文件都必须有自己的目录(也称为“根模块”)。

    1. Cloud Shell 中,创建一个目录,并在该目录中创建一个新文件。文件名必须具有 .tf 扩展名,例如 main.tf。在本教程中,该文件称为 main.tf
      mkdir DIRECTORY && cd DIRECTORY && touch main.tf
    2. 如果您按照教程进行操作,可以在每个部分或步骤中复制示例代码。

      将示例代码复制到新创建的 main.tf 中。

      (可选)从 GitHub 中复制代码。如果端到端解决方案包含 Terraform 代码段,则建议这样做。

    3. 查看和修改要应用到您的环境的示例参数。
    4. 保存更改。
    5. 初始化 Terraform。您只需为每个目录执行一次此操作。
      terraform init

      (可选)如需使用最新的 Google 提供程序版本,请添加 -upgrade 选项:

      terraform init -upgrade

    应用更改

    1. 查看配置并验证 Terraform 将创建或更新的资源是否符合您的预期:
      terraform plan

      根据需要更正配置。

    2. 通过运行以下命令并在提示符处输入 yes 来应用 Terraform 配置:
      terraform apply

      等待 Terraform 显示“应用完成!”消息。

    3. 打开您的 Google Cloud 项目以查看结果。在 Google Cloud 控制台的界面中找到资源,以确保 Terraform 已创建或更新它们。

部署到多个区域

将 Service 部署可用的 Cloud Run 区域。为了便于管理,您可以在多个区域中使用相同的服务名称。

命令行

  1. 选择要在其中提供服务的区域
  2. 将 Cloud Run 服务部署到各个区域。
  3. gcloud run deploy SERVICE_NAME \
    --allow-unauthenticated \
    --image=IMAGE_URL \
    --region=REGION

    执行以下变量替换操作:

    • REGION 替换为您要用作部署目标的其中一个区域。
    • SERVICE_NAME 替换为您的服务名称。在多个区域中使用相同的服务名称可让您更轻松地跟踪多区域部署。
    • IMAGE_URL 替换为对容器映像的引用,例如 us-docker.pkg.dev/cloudrun/container/hello:latest。 如果您使用 Artifact Registry,则必须预先创建制品库 REPO_NAME。网址格式为 LOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG
  4. 对每个区域重复执行上述步骤。

Terraform

run_regions 变量中指定的每个区域配置服务。

resource "google_cloud_run_v2_service" "run_default" {
  provider = google-beta
  count    = length(local.run_regions)
  name     = "myservice-run-app-${local.run_regions[count.index]}"
  location = local.run_regions[count.index]

  deletion_protection = false # set to "true" in production

  template {
    containers {
      image = "us-docker.pkg.dev/cloudrun/container/hello"
    }
  }

  # Use an explicit depends_on clause to wait until API is enabled
  depends_on = [
    google_project_service.run_api
  ]
}

循环遍历 run_regions 变量中指定的所有区域,并按如下所示命名每个新服务:myservice-run-app-${var.run_regions[count.index]}。用同样的方法定义服务位置。将默认映像 us-docker.pkg.dev/cloudrun/container/hello" 替换为您自己的映像。

Cloud Run 位置

Cloud Run 是区域级的,这意味着运行 Cloud Run 服务的基础架构位于特定区域,并且由 Google 代管,以便在该区域内的所有可用区以冗余方式提供。

选择用于运行 Cloud Run 服务的区域时,主要考虑该区域能否满足您的延迟时间、可用性或耐用性要求。通常,您可以选择距离用户最近的区域,但除此之外,您还应该考虑 Cloud Run 服务使用的其他 Google Cloud 产品的位置。跨多个位置使用 Google Cloud 产品可能会影响服务的延迟时间和费用。

Cloud Run 可在以下区域使用:

基于层级 1 价格

基于层级 2 价格

  • africa-south1(约翰内斯堡)
  • asia-east2(香港)
  • asia-northeast3(韩国首尔)
  • asia-southeast1(新加坡)
  • asia-southeast2 (雅加达)
  • asia-south1(印度孟买)
  • asia-south2(印度德里)
  • australia-southeast1(悉尼)
  • australia-southeast2(墨尔本)
  • europe-central2(波兰,华沙)
  • europe-west10(柏林) 叶形图标 二氧化碳排放量低
  • europe-west12(都灵)
  • europe-west2(英国伦敦) 叶形图标 二氧化碳排放量低
  • europe-west3(德国法兰克福) 叶形图标 二氧化碳排放量低
  • europe-west6(瑞士苏黎世) 叶形图标 二氧化碳排放量低
  • me-central1(多哈)
  • me-central2(达曼)
  • northamerica-northeast1(蒙特利尔) 叶形图标 二氧化碳排放量低
  • northamerica-northeast2(多伦多) 叶形图标 二氧化碳排放量低
  • southamerica-east1(巴西圣保罗) 叶形图标 二氧化碳排放量低
  • southamerica-west1(智利圣地亚哥) 叶形图标 二氧化碳排放量低
  • us-west2(洛杉矶)
  • us-west3(盐湖城)
  • us-west4(拉斯维加斯)

如果您已创建 Cloud Run 服务,则可以在 Google Cloud 控制台中的 Cloud Run 信息中心内查看区域。

配置区域级网络端点组

对于您在上一步中部署的每个区域,您需要创建无服务器网络端点组 (NEG),并按照以下说明将其添加到后端服务:

命令行

  1. REGION 中为 Cloud Run 服务创建网络端点组:

    gcloud compute network-endpoint-groups create NEG_NAME \
                --region=REGION \
                --network-endpoint-type=SERVERLESS \
                --cloud-run-service=SERVICE_NAME

    在上述命令中,进行如下替换:

    • NEG_NAME 替换为网络端点组资源的名称。 (例如“myservice-neg-uscentral1”)
    • REGION 替换为部署服务的 [region][loc]。
    • SERVICE_NAME 替换为您的服务名称。
  2. 将网络端点组添加到后端服务:

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

    指定您在上一步为该区域创建的 NEG_NAME

  3. 对每个区域重复上述步骤。

Terraform

  1. 为在 run_regions 变量中指定的每个区域配置 Cloud Run 服务的网络端点组(名称为 myservice-neg):

    resource "google_compute_region_network_endpoint_group" "lb_default" {
      provider              = google-beta
      count                 = length(local.run_regions)
      name                  = "myservice-neg"
      network_endpoint_type = "SERVERLESS"
      region                = local.run_regions[count.index]
      cloud_run {
        service = google_cloud_run_v2_service.run_default[count.index].name
      }
    }
  2. 配置后端服务以连接网络端点组 (myservice-neg):

    resource "google_compute_backend_service" "lb_default" {
      provider              = google-beta
      name                  = "myservice-backend"
      load_balancing_scheme = "EXTERNAL_MANAGED"
    
      backend {
        group = google_compute_region_network_endpoint_group.lb_default[0].id
      }
    
      backend {
        group = google_compute_region_network_endpoint_group.lb_default[1].id
      }
    
      # Use an explicit depends_on clause to wait until API is enabled
      depends_on = [
        google_project_service.compute_api,
      ]
    }

在您的网域中配置 DNS 记录

如需将域名指向您创建的转发规则,您需要使用您创建的 IP 地址更新其 DNS 记录。

  1. 通过运行以下命令找到负载均衡器的预留 IP 地址:

      gcloud compute addresses describe --global SERVICE_IP --format='value(address)'

    SERVICE_IP 替换为您之前创建的 IP 地址的名称。此命令会将 IP 地址输出到输出内容中。

  2. 使用此 IP 地址添加 A 记录,以更新网域的 DNS 记录。

在使用经过身份验证的服务时配置自定义受众群体

经过身份验证的服务受 IAM 保护。 此类 Cloud Run 服务需要在凭据生成时声明请求的预期接收者(受众群体)的客户端身份验证。

受众群体通常是目标服务的完整网址,默认情况下,对于 Cloud Run 服务,该网址是一个生成的以 run.app 结尾的网址。但是,在多区域部署中,客户端无法预先知道请求将路由到哪个区域级服务。因此,对于多区域部署,请将您的服务配置为使用自定义受众群体

等待负载均衡器预配

使用负载平衡器 IP 地址配置网域后,您需要等待 DNS 记录传播。同样,您需要等待一段时间,让系统为您的网域颁发代管式 TLS 证书,并且代管式 TLS 证书准备好开始在全球范围内提供 HTTPS 流量。

负载均衡器最多可能需要 30 分钟才能开始处理流量。

准备就绪后,请访问前缀为 https:// 的网址,试一试。

验证状态

  1. 如需检查您的 DNS 记录传播的状态,请使用 dig 命令行实用程序:

    dig A +short example.com

    输出应显示您在 DNS 记录中配置的 IP 地址。

  2. 检查代管式证书颁发的状态,运行以下命令:

    gcloud compute ssl-certificates describe CERT_NAME

    CERT_NAME 替换为您之前为 SSL 证书资源选择的名称。

    输出内容应显示包含 status: ACTIVE 的行。

设置 HTTP 到 HTTPS 的重定向

默认情况下,转发规则仅处理单个协议,因此向 http:// 端点发出的请求将返回 404 Not Found 响应。如果您需要将对 http:// 网址的请求重定向到 https:// 协议,则需要按照以下说明创建额外的网址映射和转发规则:

命令行

  1. 使用重定向规则创建网址映射。

    gcloud compute url-maps import HTTP_URLMAP_NAME \
              --global \
              --source /dev/stdin <<EOF
            name: HTTP_URLMAP_NAME
            defaultUrlRedirect:
              redirectResponseCode: MOVED_PERMANENTLY_DEFAULT
              httpsRedirect: True
            EOF

    HTTP_URLMAP_NAME 替换为您将创建的网址映射资源的名称(例如 myservice-httpredirect)。

  2. 使用网址映射创建目标 HTTP 代理。

    gcloud compute target-http-proxies create HTTP_PROXY_NAME \
              --url-map=HTTP_URLMAP_NAME

    HTTP_PROXY_NAME 替换为您将创建的目标 HTTP 代理的名称(例如 myservice-http)。

  3. 在端口 80 上使用相同的预留 IP 地址创建转发规则。

    gcloud compute forwarding-rules create --global HTTP_FORWARDING_RULE_NAME \
              --target-http-proxy=HTTP_PROXY_NAME \
              --address=SERVICE_IP \
              --ports=80 \
            

    HTTP_FORWARDING_RULE_NAME 替换为您将创建的新转发规则的名称(例如 myservice-httplb)。

Terraform

  1. 使用重定向规则创建网址映射资源。

    resource "google_compute_url_map" "https_default" {
      provider = google-beta
      name     = "myservice-https-urlmap"
    
      default_url_redirect {
        redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
        https_redirect         = true
        strip_query            = false
      }
    }
  2. 使用新创建的网址映射资源 (myservice-https-urlmap) 创建目标 HTTP 代理:

    resource "google_compute_target_http_proxy" "https_default" {
      provider = google-beta
      name     = "myservice-http-proxy"
      url_map  = google_compute_url_map.https_default.id
    
      depends_on = [
        google_compute_url_map.https_default
      ]
    }
  3. 在端口 80 上使用相同的预留 IP 地址资源 (myservice-http-proxy) 创建转发规则。

    resource "google_compute_global_forwarding_rule" "https_default" {
      provider   = google-beta
      name       = "myservice-https-fr"
      target     = google_compute_target_http_proxy.https_default.id
      ip_address = google_compute_global_address.lb_default.id
      port_range = "80"
      depends_on = [google_compute_target_http_proxy.https_default]
    }

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

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