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

世界中のユーザーに迅速にレスポンスを返すには、複数のリージョンにサービスをデプロイし、最も近いリージョンにユーザーをルーティングする必要があります。

Cloud Run サービスは個々のリージョンにデプロイされるため、サービスの別のリージョンにユーザーをルーティングするように外部アプリケーション ロードバランサを構成する必要があります。

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

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

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

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

コマンドライン

  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 によって作成または更新されたことを確認します。

複数のリージョンにデプロイする

使用可能な Cloud Run のリージョンにサービスをデプロイします。管理を容易にするため、複数のリージョンで同じサービス名を使用できます。

コマンドライン

  1. サービスを利用可能にするリージョンを選択します。
  2. Cloud Run サービスを個々のリージョンにデプロイします。
  3. gcloud run deploy SERVICE_NAME \
    --allow-unauthenticated \
    --image=IMAGE_URL \
    --region=REGION

    次の変数を置き換えます。

    • REGION は、デプロイ先のいずれか 1 つのリージョンに置き換えます。
    • SERVICE_NAME は、実際のサービスの名前に置き換えます。複数のリージョンで同じサービス名を使用すると、マルチリージョン デプロイを簡単にトラッキングできるようになります。
    • IMAGE_URL: コンテナ イメージへの参照(us-docker.pkg.dev/cloudrun/container/hello:latest など)。Artifact Registry を使用する場合は、リポジトリ REPO_NAME がすでに作成されている必要があります。URL の形式は REGION-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]

  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 料金を適用

  • asia-east1(台湾)
  • asia-northeast1(東京)
  • asia-northeast2(大阪)
  • europe-north1(フィンランド) リーフアイコン 低 CO2
  • europe-southwest1(マドリッド)
  • europe-west1(ベルギー) リーフアイコン 低 CO2
  • europe-west4(オランダ)
  • europe-west8(ミラノ)
  • europe-west9(パリ) リーフアイコン 低 CO2
  • me-west1(テルアビブ)
  • us-central1(アイオワ) リーフアイコン 低 CO2
  • us-east1(サウスカロライナ)
  • us-east4(北バージニア)
  • us-east5(コロンバス)
  • us-south1(ダラス)
  • us-west1(オレゴン) リーフアイコン 低 CO2

ティア 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(ロンドン、イギリス) リーフアイコン 低 CO2
  • europe-west3(フランクフルト、ドイツ) リーフアイコン 低 CO2
  • europe-west6(チューリッヒ、スイス) リーフアイコン 低 CO2
  • me-central1(ドーハ)
  • me-central2(ダンマーム)
  • northamerica-northeast1(モントリオール) リーフアイコン 低 CO2
  • northamerica-northeast2(トロント) リーフアイコン 低 CO2
  • southamerica-east1(サンパウロ、ブラジル) リーフアイコン 低 CO2
  • southamerica-west1(サンティアゴ、チリ) リーフアイコン 低 CO2
  • 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 サービスでは、認証情報の生成時にリクエストの対象とする受信者(オーディエンス)を宣言するクライアント認証が必要です。

オーディエンスは通常ターゲット サービスの正式な 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 マップと転送ルールを作成する必要があります。

コマンドライン

  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 サブスクリプションを使用するをご覧ください。