複数のリージョンからのトラフィックを処理する

複数のリージョンにサービスをデプロイし、最も近いリージョンにユーザーをルーティングすることで、世界中のユーザーに迅速にレスポンスを返すことができます。複数のリージョンにデプロイすると、低レイテンシとリージョンの停止時の高可用性が実現されます。

Cloud Run サービスは個々のリージョンにデプロイされるため、サービスを複数のリージョンにデプロイしてから、サービスのグローバル ロード バランシングを構成する必要があります。

サービスを複数のリージョンにデプロイする

次のいずれかの方法で、同じサービスを複数のリージョンにデプロイできます。

マルチリージョン サービスをデプロイする

このセクションでは、1 つの 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

マルチリージョン サービスを更新する

マルチリージョン Cloud Run サービスを更新するには、Cloud Run サービスを更新する場合と同じ設定を使用して gcloud beta run multi-region services コマンドを実行します。マルチリージョン サービスにリージョンを追加または削除するには、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 は、削除するマルチリージョン サービスの名前に置き換えます。

グローバル ロード バランシングの構成

このセクションでは、グローバル エニーキャスト IP アドレスを指しているマネージド TLS 証明書で保護されたドメインを使用して外部アプリケーション ロードバランサを構成する方法を説明します。これにより、ユーザーは、サービスがデプロイされている最寄りの Google データセンターに転送されます。

このセクションで説明するアーキテクチャでは、リージョンの Cloud Run サービスが応答しなくなったり、エラーが返されたりしても、リクエストが別のリージョンに自動的にルーティングされることはありません。マルチリージョン サービスの可用性を向上させるには、外れ値検出を構成して、正常でない Cloud Run サービスを HTTP エラー率に基づいて識別し、一部のリクエストを別のリージョンに分散します。

ロードバランサを作成する

外部ロードバランサを作成するには、さまざまなネットワーク リソースを作成し、相互に接続する必要があります。

gcloud CLI

  1. 静的 IP アドレスを予約することにより、ロードバランサを再作成するときに DNS レコードを更新する必要がなくなります。
    gcloud compute addresses create --global SERVICE_IP
    上記のコマンドの SERVICE_IP は、IP アドレス リソースの名前(myservice-ip など)に置き換えます。

    この IP アドレスは、訪問者に最も近い Google データセンターまたはポイント オブ プレゼンスにルーティングするグローバル エニーキャスト IPv4 アドレスです。

  2. バックエンド サービスを作成します。
    gcloud compute backend-services create --global BACKEND_NAME

    上記のコマンドで、BACKEND_NAME をバックエンド サービスに付ける名前(myservice-backend など)に置き換えます。

  3. URL マップを作成します。
    gcloud compute url-maps create URLMAP_NAME --default-service=BACKEND_NAME

    URLMAP_NAME は、URL マップに付ける名前(myservice-urlmap など)に置き換えます。

  4. HTTPS トラフィックを処理するために、ドメインのマネージド TLS 証明書を作成します。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 アドレスは、訪問者に最も近い Google データセンターまたはポイント オブ プレゼンスにルーティングするグローバル エニーキャスト IPv4 アドレスです。

  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. URL マップを構成します。

    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)を新しい URL マップリソース(myservice-lb-urlmap)に接続します。これらの値は、独自の値に変更できます。

  4. HTTPS トラフィックを処理するために、ドメインのマネージド TLS 証明書を作成します。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-proxy を使用して google_compute_target_https_proxy リソースを作成し、以前に作成した TLS 証明書(myservice-ssl-cert)と URL マッピング リソース(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-proxy を使用して google_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 プロジェクトを設定します。

      このコマンドは、プロジェクトごとに 1 回だけ実行する必要があります。これは任意のディレクトリで実行できます。

      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 を初期化します。これは、ディレクトリごとに 1 回だけ行う必要があります。
      terraform init

      必要に応じて、最新バージョンの Google プロバイダを使用する場合は、-upgrade オプションを使用します。

      terraform init -upgrade

    変更を適用する

    1. 構成を確認して、Terraform が作成または更新するリソースが想定どおりであることを確認します。
      terraform plan

      必要に応じて構成を修正します。

    2. 次のコマンドを実行し、プロンプトで「yes」と入力して、Terraform 構成を適用します。
      terraform apply

      Terraform に「Apply complete!」のメッセージが表示されるまで待ちます。

    3. Google Cloud プロジェクトを開いて結果を表示します。Google Cloud コンソールの UI でリソースに移動して、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 サービスでは、認証情報の生成時にリクエストの対象とする受信者(オーディエンス)を宣言するクライアント認証が必要です。

オーディエンスは通常ターゲット サービスの正式な URL であり、Cloud Run サービスの場合、デフォルトでは末尾が run.app の URL が生成されます。ただし、マルチリージョン デプロイでは、クライアントはリクエストのルーティング先のリージョン サービスを事前に知ることはできません。したがって、マルチリージョン デプロイでは、カスタム オーディエンスを使用するようにサービスを構成します。

ロードバランサのプロビジョニングを待つ

ロードバランサの IP アドレスでドメインを構成した後は、DNS レコードが反映されるまで待つ必要があります。同様に、マネージド TLS 証明書がドメインに発行され、HTTPS トラフィックがグローバルに配信可能になるまで待つ必要があります。

ロードバランサがトラフィックの配信を開始するまでに最大で 30 分かかることがあります。

準備ができたら、ウェブサイトの URL の先頭に 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:// URL へのリクエストを https:// プロトコルにリダイレクトする必要がある場合は、次の手順に沿って追加の URL マップと転送ルールを作成する必要があります。

gcloud CLI

  1. リダイレクト ルールで URL マップを作成します。

    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 は、作成する URL マップリソースの名前(myservice-httpredirect など)で置き換えます。

  2. URL マップを使用してターゲット HTTP プロキシを作成します。

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

    HTTP_PROXY_NAME は、作成するターゲット HTTP プロキシの名前(myservice-http など)に置き換えます。

  3. 同じ予約済み IP アドレスのポート 80 での転送ルールを作成します。

    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. リダイレクト ルールで URL マップリソースを作成します。

    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. 新しく作成した URL マップリソース(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. 同じ予約済み IP アドレス リソース(myservice-http-proxy)のポート 80 での転送ルールを作成します。

    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 push サブスクリプションを使用する

デフォルトでは、Pub/Sub サービスは Pub/Sub サービスがメッセージを格納するのと同じ Google Cloud リージョン内の push エンドポイントにメッセージを配信します。この動作を回避するには、マルチリージョンの Cloud Run デプロイで認証済みの Pub/Sub push サブスクリプションを使用するをご覧ください。