处理来自多个区域的流量

通过在多个区域部署服务,并将用户路由到最近的区域,您可以更快地将响应返回给全球各地的用户。跨多个区域部署可实现低延迟和更高的可用性,以便在区域服务中断时提供支持。

由于 Cloud Run 服务会部署到个别区域,因此您需要将服务部署到多个区域,然后为服务配置全球负载均衡

将服务部署到多个区域

您可以使用以下方法之一将同一服务部署到多个区域:

部署多区域服务

本部分介绍了如何通过单个 gcloud CLI 命令部署和配置多区域服务。

  • 如需创建和部署多区域服务,请使用 --regions 标志运行 gcloud beta run deploy 命令:

    gcloud beta run deploy SERVICE_NAME \
      --image=IMAGE_URL \
      --regions=REGIONS

    替换以下内容:

    • SERVICE_NAME:您要部署的多区域服务的名称。
    • IMAGE_URL:对容器映像的引用,例如 us-docker.pkg.dev/cloudrun/container/hello:latest
    • REGIONS:您要部署到多个区域的列表。例如 us-central1,asia-east1

更新多区域服务

您可以通过运行 gcloud beta run multi-region services 命令来更新多区域 Cloud Run 服务,使用与更新 Cloud Run 服务相同的设置。如需在多区域服务中添加或移除区域,请运行 gcloud beta run multi-region-services update 命令。

  • 如需将该多区域服务添加到其他一个或多个区域,请使用 --add-regions 标志:

    gcloud beta run multi-region-services update SERVICE_NAME \
      --add-regions=REGIONS
  • 如需从一个或多个区域中移除该多区域服务,请使用 --remove-regions 标志:

    gcloud beta run multi-region-services update SERVICE_NAME \
      --remove-regions=REGIONS

    替换以下内容:

  • SERVICE_NAME:您要更新的多区域服务的名称。

  • REGIONS:您要向其中添加服务或从中移除服务的一个或多个区域。例如 us-central1,asia-east1

删除多区域服务

  • 如需删除多区域服务,请运行 gcloud beta run multi-region-services delete 命令:

    gcloud beta run multi-region-services delete SERVICE_NAME

    SERVICE_NAME 替换为您要删除的多区域服务的名称。

配置全球负载均衡

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

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

创建负载均衡器

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

gcloud CLI

  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 已创建或更新它们。

配置区域级网络端点组

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

gcloud CLI

  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(未找到网页)”响应。如果您需要将对 http:// 网址的请求重定向到 https:// 协议,则必须按照以下说明创建额外的网址映射和转发规则:

gcloud CLI

  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 部署搭配使用