Cloud Storage のグローバル エンドポイントとリージョン エンドポイントへの Cloud Run プライベート アクセス

1. はじめに

Google API エンドポイント

Google Cloud API には、サービスにアクセスするためのさまざまなタイプのエンドポイントが用意されています。これらのエンドポイントは、主にリクエストのルーティング、データの所在地、リージョン分離の処理方法が異なります。

API エンドポイントのタイプについては、プロダクト ドキュメントをご覧ください。

グローバル エンドポイント、リージョン エンドポイント、ロケーション エンドポイントの内訳は次のとおりです。

  1. グローバル エンドポイント
  • 形式: {service}.googleapis.com(例: storage.googleapis.com)
  • 説明: これらのエンドポイントは、サービスへの単一のグローバル アクセス ポイントを提供します。URL にリージョンは指定されません。
  • ルーティング: リクエストは、グローバル Google Front End(GFE)とグローバル サービス ロード バランシングによってルーティングされます。通常、レイテンシを最小限に抑えるために、最も近い正常なリージョンにトラフィックを転送します。
  • TLS 終端: クライアントに最も近い GFE で行われます。これは、データまたはリソースが存在する Google Cloud リージョンの外部にある可能性があります。
  • データの所在地: 保証なし 。転送中のデータには保証はありません。GFE で復号化された後、データがリージョン境界を越える可能性があります。
  • リージョン分離: 限定的。バックエンドはリージョンに配置されることが多いですが、エントリ ポイントとロード バランシングはグローバルです。つまり、グローバル インフラストラクチャの一部で問題が発生すると、他のリージョンのサービスに影響する可能性があります。
  • ユースケース: 地理的に分散したユーザーのレイテンシを短縮することが重要で、転送中のデータの所在地を厳密に管理することが主な懸念事項ではない、汎用的なアクセス。
  1. リージョン エンドポイント(REP)
  • 形式: {service}.{location}.rep.googleapis.com(例: storage.us-east1.rep.googleapis.com)
  • 説明: 強力なリージョン分離とデータの所在地保証を提供するように設計されています。ロケーション(特定の Google Cloud リージョン)はサブドメインとして指定されます。これは最新の標準であり、ロケーション エンドポイントに代わるものです。
  • ルーティング: リージョン外部ロードバランサやリージョン サービス ロード バランシングなど、完全にリージョン化されたフロントエンド スタックを使用します。DNS からサービス バックエンドまでのリクエスト パス全体が、指定されたリージョン内に留まります。
  • TLS 終端: 指定されたリージョン内のリージョン外部ロードバランサで行われます。
  • データの所在地: 転送中と使用中の両方で、データが指定されたリージョン内に留まることを保証し、厳格なコンプライアンス要件と主権要件を満たします。
  • リージョン分離: 強力。あるリージョンのフロントエンド インフラストラクチャで障害が発生しても、他のリージョンには影響しません。
  • ユースケース: 厳格なデータの所在地、高いリージョン分離、コンプライアンスが求められるアプリケーション。

すべての Google API にリージョン エンドポイントがあるわけではありません。サポートされているすべてのリージョン エンドポイントについては、こちらをご覧ください。

マルチリージョン リージョン エンドポイント(mREP)もリージョン エンドポイントです(例: storage.us.rep.googleapis.com)。

  1. ロケーション エンドポイント(LEP)
  • 形式: {location}-{service}.googleapis.com(例: us-east1-storage.googleapis.com)
  • 説明: これらのエンドポイントは、ロケーション固有のアクセスを提供する初期のアプローチでした。ロケーションはメイン ホスト名の一部です。注: ロケーション エンドポイントはリージョン エンドポイントに置き換えられています。
  • ルーティング: グローバル Google Front End に依存しています。
  • TLS 終端: 通常は GFE で行われます。これは、ホスト名で指定されたリージョンにない可能性があります。
  • データの所在地: 保証なし 。公共のインターネットからのトラフィックの場合、転送中にデータが指定されたリージョン内に留まることを保証できません。
  • リージョン分離: グローバル フロントエンド インフラストラクチャを使用するため、リージョン エンドポイントよりも弱くなります。
  • ユースケース: 一部のリージョン アクセス シナリオで以前使用されていましたが、現在では、より強力な保証のためにリージョン エンドポイントを使用することが推奨されています。

Google API 用の Private Service Connect

Private Service Connect は Google Cloud ネットワーキング機能の一つで、コンシューマーがプロデューサー サービスにアクセスできるようにします。これには、ユーザーの VPC 内でホストされているプライベート エンドポイントを介して Google API に接続する機能が含まれます。

PSC エンドポイントを使用して Google API にアクセスする方法:

PSC バックエンドを使用して Google API にアクセスする方法:

Cloud Run が VPC ネットワークにトラフィックを送信する

ダイレクト VPC 下り(外向き)では、Cloud Run のインフラストラクチャを強化し、VPC 下り(外向き)構成を簡単に行うことができます。これには次の利点があります。

  • 設定: Cloud Run のサービスとジョブは、サーバーレス VPC アクセス コネクタを管理するオーバーヘッドなしで VPC ネットワークにトラフィックを送信できます。
  • 費用: サービス自体と同様に、ゼロにスケーリングされるネットワーク トラフィックに対してのみ料金が発生します。
  • セキュリティ: サービス リビジョンでネットワーク タグを直接使用すると、よりきめ細かなネットワーク セキュリティを実現できます。
  • パフォーマンス: 低レイテンシ、高スループット。

ダイレクト VPC 下り(外向き)を使用すると、Cloud Run サービス、関数、ジョブ、ワーカープールがすべてのトラフィックを VPC ネットワークに送信できます。

2. 学習内容

  • グローバル Google API の PSC エンドポイントを作成する方法。
  • リージョン Google API の PSC エンドポイントを作成する方法。
  • Cloud Run コードで API エンドポイントを変更し、下り(外向き)のネットワーキングを構成する方法。

3. ラボの全体的なアーキテクチャ

8f5328678688f210.png

4. 準備手順

ラボで作業するために必要な IAM ロール

まず、プロジェクト レベルで必要な IAM ロールを GCP アカウントに割り当てます。

  • Compute ネットワーク管理者(roles/compute.networkAdmin): このロールでは、Compute Engine ネットワーキング リソースを完全に制御できます。
  • Logging 管理者(roles/logging.admin): このロールでは、すべてのロギング権限と依存権限にアクセスできます。
  • Service Usage 管理者(roles/serviceusage.serviceUsageAdmin): このロールでは、サービス状態の有効化、無効化、検査、オペレーションの検査、ユーザー プロジェクトの割り当てと請求の利用が可能です。
  • DNS 管理者(roles/dns.admin): このロールでは、すべての Cloud DNS リソースに対する読み取り / 書き込みアクセス権が付与されます。
  • Cloud Run 管理者(roles/run.admin): このロールでは、すべての Cloud Run リソースを完全に制御できます。
  • ストレージ管理者(roles/storage.admin): このロールでは、オブジェクトとバケットを完全に制御できます。

API を有効にする

Cloud Shell で、プロジェクトが正しく構成されていることを確認し、環境変数を設定します。

Cloud Shell で次の操作を行います。

gcloud auth login
gcloud config set project <your project id>
export project_id=<your project id>
export region=<your region>
export zone=$region-a
echo $project_id
echo $region

プロジェクトで必要なすべての Google API を有効にします。Cloud Shell で次の操作を行います。

gcloud services enable \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  run.googleapis.com \
  compute.googleapis.com \
  dns.googleapis.com \
  servicedirectory.googleapis.com \
  networkconnectivity.googleapis.com

VPC を作成

プロジェクトで、カスタム サブネット モードの VPC ネットワークを作成します。Cloud Shell で次の操作を行います。

gcloud compute networks create mynet \
    --subnet-mode=custom

サブネットを作成する

Cloud Shell で次の操作を行って、IPV4 サブネットを作成します。

gcloud compute networks subnets create mysubnet \
    --network=mynet \
    --range=10.0.0.0/24 \
    --region=$region

Cloud NAT と Cloud Router を作成する

Cloud NAT は、Cloud Run ジョブが外部ウェブサイトに接続できるようにするために使用されます。

gcloud compute routers create $region-cr \
   --network=mynet \
   --region=$region 
gcloud compute routers nats create $region-nat \
    --router=$region-cr \
    --region=$region \
    --nat-all-subnet-ip-ranges \
    --auto-allocate-nat-external-ips

5. Cloud Storage の PSC エンドポイントを作成する

Cloud Storage 用に 2 つの PSC エンドポイントを作成します。1 つはグローバル スコープ用、もう 1 つはリージョン スコープ用です。

グローバル スコープの PSC エンドポイントを作成する

Private Service Connect を使用すると、VPC ネットワーク内のグローバル内部 IP アドレスを使用して、グローバル スコープのプライベート エンドポイントを作成できます。

VPC で定義されていない一意の IP アドレスを割り当てる必要があります。この IP アドレス要件については、ドキュメントをご覧ください。

Cloud Shell で次の操作を行って、IP アドレスを作成します。割り当てた IP アドレスを使用するように、–addresses=<pscendpointip> を変更してください。

gcloud compute addresses create pscglobalip \
    --global \
    --purpose=PRIVATE_SERVICE_CONNECT \
    --addresses=<pscendpointip> \
    --network=mynet
pscendpointip=$(gcloud compute addresses list --filter=name:pscglobalip --format="value(address)")
echo $pscendpointip

エンドポイントを Google API およびサービスに接続する転送ルールを作成します。

gcloud compute forwarding-rules create pscendpoint \
    --global \
    --network=mynet \
    --address=pscglobalip \
    --target-google-apis-bundle=all-apis

Cloud DNS で p.googleapis.com を確認する

エンドポイントを作成すると、次の DNS 構成が自動的に作成されます。

  • p.googleapis.com に Service Directory のプライベート DNS ゾーンが作成されます。
  • DNS レコードは、Private Service Connect を使用して利用できる一般的な Google API とサービスのために p.googleapis.com で作成されており、末尾が googleapis.com のデフォルトの DNS 名となっています。

グローバル エンドポイントは Service Directory に登録されます。storage-[psc endpoint name].p.googleapis.com を使用して Cloud Storage にアクセスします。詳細については、プロダクト ドキュメントをご覧ください。

コマンドを実行して、p.googleaps.com ゾーンがすでに作成されているかどうかを確認します。

gcloud dns managed-zones list

デフォルトの DNS 名 storage.googleapis.com を使用する場合は、Cloud DNS にプライベート ゾーン storage.googleapis.com を作成し、グローバル スコープの IP アドレスの PSC エンドポイントを指す Apex レコードを追加します。

Cloud Storage のリージョン スコープの PSC エンドポイントを作成する

VPC サブネットから 1 つの IP が必要になります。次のコマンドを実行すると、サブネットワークの IP が PSC エンドポイントに割り当てられます。

gcloud network-connectivity regional-endpoints create psc-regional-endpoint \
    --region=$region \
    --network=projects/$project_id/global/networks/mynet \
    --subnetwork=projects/$project_id/regions/$region/subnetworks/mysubnet \
    --target-google-api=storage.us-central1.rep.googleapis.com

上記の手順で作成したエンドポイント IP アドレスを取得します。

regionalip=$(gcloud network-connectivity regional-endpoints describe psc-regional-endpoint --region=$region --format="value(address)")
echo $regionalip

storage.us-central1.rep.googleapis.com を使用して Cloud Storage にアクセスします。storage.us-central1.rep.googleapis.com のプライベート ゾーンと、Cloud DNS のリージョン エンドポイント用に作成した IP アドレスの Apex レコードを作成する必要があります。

Cloud Storage リージョン エンドポイントのプライベート ゾーンを作成する

storage.[region name].rep.googleapis.com を使用して Cloud Storage リージョン エンドポイントにアクセスします。

Cloud DNS にプライベート ゾーンを作成し、Cloud Storage リージョン エンドポイントの IP アドレスを指す Apex レコードを追加する必要があります。

次のコマンドでは、us-central1 はリージョンの例です。リージョンの名前でゾーンを作成する必要があります。

gcloud dns managed-zones create psc-regional-endpoint-zone \
  --description="" \
  --dns-name="storage.us-central1.rep.googleapis.com" \
  --visibility="private" \
  --networks="mynet"

gcloud dns record-sets create storage.us-central1.rep.googleapis.com. \
  --rrdatas=$regionalip \
  --ttl=300 \
  --type=A \
  --zone=psc-regional-endpoint-zone

6. グローバル スコープの PSC エンドポイントを使用して Cloud Run ジョブを構成する

コードを取得する

まず Node.js アプリケーションを探索し、ウェブページのスクリーンショットを撮影して Cloud Storage に保存します。その後、アプリケーションのコンテナ イメージをビルドし、Cloud Run でジョブとして実行します。

Cloud Shell で次のコマンドを実行して、こちらのリポジトリからアプリケーション コードのクローンを作成します。

git clone https://github.com/GoogleCloudPlatform/jobs-demos.git

アプリケーションが格納されているディレクトリに移動します。

cd jobs-demos/screenshot

次のようなファイル レイアウトが表示されます。

|

├── Dockerfile

├── README.md

├── screenshot.js

├── package.json

以下は、各ファイルに関する簡単な説明です。

  • screenshot.js には、アプリケーションの Node.js コードが格納されています。アプリケーションは、ウェブページのスクリーンショットを撮影して Cloud Storage に保存します。
  • package.json は、ライブラリの依存関係を定義します。
  • Dockerfile は、コンテナ イメージを定義します。

screenshot.js コードを開き、apiEndpoint を PSC グローバル エンドポイントに変更します。コードを検索し、const storage = new Storage(); を次のコードに置き換えます。

const storage = new Storage(
    {
      apiEndpoint:'https://storage-pscendpoint.p.googleapis.com.',
      useAuthWithCustomEndpoint: true
    }
  );

ジョブをデプロイする

ジョブを作成する前に、ジョブの実行に使用するサービス アカウントを作成する必要があります。

gcloud iam service-accounts create screenshot-sa --display-name="Screenshot app service account"

サービス アカウントに storage.admin ロールを付与して、バケットとオブジェクトの作成に使用できるようにします。

gcloud projects add-iam-policy-binding $project_id \
  --role roles/storage.admin \
  --member serviceAccount:screenshot-sa@$project_id.iam.gserviceaccount.com

デフォルトの Compute サービス アカウントにストレージ オブジェクト ユーザー ロール、ログ書き込みロール、Artifact Registry リポジトリ管理者ロールを付与します。

project_number=$(gcloud projects describe $project_id --format="value(projectNumber)")

gcloud projects add-iam-policy-binding $project_id \
  --role roles/storage.objectUser \
  --member serviceAccount:$project_number-compute@developer.gserviceaccount.com

gcloud projects add-iam-policy-binding $project_id \
  --role roles/logging.logWriter \
  --member serviceAccount:$project_number-compute@developer.gserviceaccount.com

gcloud projects add-iam-policy-binding $project_id \
  --role roles/artifactregistry.repoAdmin \
  --member serviceAccount:$project_number-compute@developer.gserviceaccount.com

Cloud Run ジョブでダイレクト VPC 下り(外向き)を有効にして、すべてのトラフィックを VPC ネットワークに送信します。

Cloud Shell で次の操作を行います。

gcloud run jobs deploy screenshot-1 \
  --source=. \
  --args="https://example.com" \
  --args="https://cloud.google.com" \
  --tasks=2 \
  --task-timeout=5m \
  --region=$region \
  --set-env-vars=BUCKET_NAME=screenshot-$project_id-$RANDOM \
  --service-account=screenshot-sa@$project_id.iam.gserviceaccount.com \
  --vpc-egress=all-traffic \
  --network=mynet \
  --subnet=mysubnet

ジョブを実行する

Cloud Shell で次の操作を行います。

gcloud run jobs execute screenshot-1 --region=$region

ジョブとログのステータスを確認します。Cloud Run コンソールに移動して、ジョブを探します。ジョブをクリックして、ログの履歴を確認します。次のようなジョブ実行結果が表示されます。

bae25d504ea20384.png

ジョブ実行ログの詳細については、タスクの [ログを表示] をクリックします。次のようなジョブログが表示されます。

aa0468dc463f4320.png

新しいバケットが作成されました。Cloud Storage コンソールに移動して、作成した新しいバケットを確認できます。Cloud Storage グローバル エンドポイントを使用しているため、バケットはマルチリージョン バケットになります。バケットにアップロードされた画像を確認できます。

テスト結果は、Cloud Run ジョブで変更した Cloud Run が Cloud Storage グローバル エンドポイントに非公開でアクセスしたことを示しています。

apiEndpoint:‘https://storage-pscendpoint.p.googleapis.com.'

7. リージョン スコープの PSC エンドポイントを使用して Cloud Run ジョブを構成する

コードで、apiEndpoint をリージョン スコープの PSC エンドポイントに変更します。

コードを検索し、const storage = new Storage(); を次のコードに置き換えます(us-central1 を例として使用します。リージョンに変更してください)。

const storage = new Storage(
    {
      apiEndpoint:'https://storage.us-central1.rep.googleapis.com.',
      useAuthWithCustomEndpoint: true
    }
  );

ジョブをデプロイする

アプリケーション(jobs-demos/screenshot)が格納されているディレクトリにいることを確認します。

pwd

ジョブでダイレクト VPC 下り(外向き)を有効にして、すべてのトラフィックを VPC ネットワークに送信します。

Cloud Shell で次の操作を行います。

gcloud run jobs deploy screenshot-2 \
  --source=. \
  --args="https://example.com" \
  --args="https://cloud.google.com" \
  --tasks=2 \
  --task-timeout=5m \
  --region=$region \
  --set-env-vars=BUCKET_NAME=screenshot-$PROJECT_ID-$RANDOM \
  --service-account=screenshot-sa@$project_id.iam.gserviceaccount.com \
  --vpc-egress=all-traffic \
  --network=mynet \
  --subnet=mysubnet

ジョブを実行する

Cloud Shell で次の操作を行います。

gcloud run jobs execute screenshot-2 --region=$region

ジョブとログのステータスを確認します。Cloud Run コンソールに移動して、ジョブを探します。ジョブをクリックして、ジョブの履歴を確認します。次のようなジョブ実行結果が表示されます。

1065ce25136d355e.png

ジョブ実行ログの詳細については、[ログを表示] をクリックします。次のようなジョブログが表示されます。

837afb2f95a7049b.png

新しいバケットが作成されました。Cloud Storage コンソールに移動して、作成した新しいバケットを確認できます。Cloud Storage リージョン エンドポイントを使用しているため、バケットは単一リージョン バケットになります。バケットにアップロードされた画像を確認できます。

テスト結果は、Cloud Run ジョブで変更した Cloud Run が Cloud Storage リージョン エンドポイントに非公開でアクセスしたことを示しています。

apiEndpoint:‘https://storage.us-central1.rep.googleapis.com.'

8. クリーンアップ

Cloud Run ジョブをクリーンアップする

gcloud run jobs delete screenshot-1 \
  --region=$region --quiet
gcloud run jobs delete screenshot-2 \
  --region=$region --quiet

gcloud iam service-accounts delete screenshot-sa@$project_id.iam.gserviceaccount.com --quiet

PSC エンドポイントをクリーンアップする

gcloud compute forwarding-rules delete pscendpoint \
    --global --quiet
gcloud network-connectivity regional-endpoints delete psc-regional-endpoint \
    --region=$region --quiet
gcloud compute addresses delete pscglobalip \
    --global --quiet

Cloud NAT、Cloud Router、VPC をクリーンアップする

gcloud compute routers nats delete $region-nat \
    --router=$region-cr \
    --region=$region --quiet
gcloud compute routers delete $region-cr \
    --region=$region --quiet
gcloud compute networks subnets delete mysubnet \
    --region=$region --quiet
gcloud compute networks delete mynet --quiet

9. 完了

グローバル エンドポイントとリージョン エンドポイントを使用して、Cloud Run から Cloud Storage へのプライベート アクセスをテストできました。