Cloud Run から Private Cloud SQL への接続

1. 概要

このラボでは、Cymbal Eats のメニュー サービスを作成し、メニュー項目を追加、更新、削除、一覧表示する RESTful API を公開します。Cloud Run で実行されるメニュー サービスのバックエンド データベースとして、Cloud SQL データベースを作成します。Cloud Run は Cloud SQL データベースと同じ VPC にないため、Cloud Run がプライベート IP アドレスを介して Cloud SQL と通信できるようにサーバーレス VPC アクセス コネクタを構成する必要があります。

19c7b05f35789fda.png

学習内容

このラボでは、次の方法について学びます。

  • プライベート VPC ネットワークを構成する
  • プライベート Postgres Cloud SQL データベースを作成する
  • CloudRun をプライベート VPC に接続する
  • Cloud SQL データベースに接続するサービスを Cloud Run にデプロイする

2. 設定と要件

セルフペース型の環境設定

  1. Google Cloud Console にログインして、プロジェクトを新規作成するか、既存のプロジェクトを再利用します。Gmail アカウントも Google Workspace アカウントもまだお持ちでない場合は、アカウントを作成してください。

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • プロジェクト名は、このプロジェクトの参加者に表示される名称です。Google API では使用されない文字列です。この値はいつでも更新できます。
  • プロジェクト ID は、すべての Google Cloud プロジェクトにおいて一意でなければならず、不変です(設定後は変更できません)。Cloud コンソールでは一意の文字列が自動生成されます。通常、それが何であるかは関係ありません。ほとんどの Codelab では、プロジェクト ID を参照する必要があります(通常は PROJECT_ID として識別されます)。生成された ID が気に入らない場合は、別のランダムな ID を生成できます。または、ご自身でお試しになることもできます。このステップを終えた後は変更できず、プロジェクト期間中は維持されます。
  • なお、3 つ目の値は、一部の API で使用される [プロジェクト番号] です。これら 3 つの値について詳しくは、こちらのドキュメントをご覧ください。
  1. 次に、Cloud のリソースや API を使用するために、Cloud コンソールで課金を有効にする必要があります。この Codelab の操作をすべて行って、費用が生じたとしても、少額です。このチュートリアルの終了後に課金されないようにリソースをシャットダウンするには、作成したリソースを削除するか、プロジェクト全体を削除します。Google Cloud の新規ユーザーは、300 米ドル分の無料トライアル プログラムをご利用いただけます。

環境設定

  1. プロジェクトとリソース関連の環境変数を作成する
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
export PROJECT_NAME=$(gcloud projects describe $PROJECT_ID --format='value(name)')
export REGION=us-east1
export MENU_SERVICE_NAME=menu-service

export SERVERLESS_VPC_CONNECTOR=cymbalconnector
export DB_INSTANCE_NAME=menu-catalog
export DB_INSTANCE_PASSWORD=password123
export DB_DATABASE=menu-db
export DB_USER=menu-user
export DB_PASSWORD=menupassword123
  1. リポジトリのクローンを作成し、以下のディレクトリに移動します。
git clone https://github.com/GoogleCloudPlatform/cymbal-eats.git && cd cymbal-eats/menu-service
  1. サービスを有効にする
gcloud services enable \
    sqladmin.googleapis.com \
    run.googleapis.com \
    vpcaccess.googleapis.com \
    servicenetworking.googleapis.com

3. プライベート アクセスを構成する

プライベート サービス アクセスは、VPC ネットワークと、Cloud SQL インスタンスが配置されている基盤となる Google Cloud VPC ネットワーク間の VPC ピアリング リンクとして提供されます。プライベート接続を使用すると、VPC ネットワーク内の VM インスタンスと使用するサービスで、内部 IP アドレスのみを使用して通信できます。プライベート サービス アクセスを介して利用可能なサービスにアクセスするために、VM インスタンスでインターネット接続や外部 IP アドレスは必要ありません。

  1. IP アドレス範囲を割り振る
gcloud compute addresses create google-managed-services-default \
    --global \
    --purpose=VPC_PEERING \
    --prefix-length=20 \
    --network=projects/$PROJECT_ID/global/networks/default

出力例

Created [https://www.googleapis.com/compute/v1/projects/cymbal-eats-2-348215/global/addresses/google-managed-services-default].
  1. プライベート接続を作成します。
gcloud services vpc-peerings connect \
    --service=servicenetworking.googleapis.com \
    --ranges=google-managed-services-default \
    --network=default \
    --project=$PROJECT_ID

出力例

Operation "operations/pssn.p24-528514492617-2f2b507f-e4e5-4d53-a4de-9ddaceb4e92f" finished successfully.

4. Cloud SQL の設定

Cloud SQL は、クラウド内の PostgreSQL と MySQL のリレーショナル データベースを簡単に設定、維持、運用、管理できるようにするフルマネージド データベース サービスです。各 Cloud SQL インスタンスは、Google Cloud ホストサーバーで実行される仮想マシン(VM)を基盤としています。高可用性オプションには、プライマリ VM と同じ設定の別のゾーンにスタンバイ VM も含まれます。データベースは、永続ディスクと呼ばれるスケーラブルで耐久性の高いネットワーク ストレージ デバイスに保持され、VM に接続されます。各 VM に静的 IP アドレスを割り当てることで、Cloud SQL インスタンスのライフサイクル期間中にアプリケーションが接続する IP アドレスが一定に保たれます。

219cb722c2dd1b82.png

プライベート IP アドレスを使用して、Postgres Cloud SQL データベースを作成します。

データベースとユーザーを作成する

  1. プライベート IP を使用する Postgres Cloud SQL インスタンスを作成する
gcloud sql instances create $DB_INSTANCE_NAME \
    --project=$PROJECT_ID \
    --network=projects/$PROJECT_ID/global/networks/default \
    --no-assign-ip \
    --database-version=POSTGRES_12 \
    --cpu=2 \
    --memory=4GB \
    --region=$REGION \
    --root-password=${DB_INSTANCE_PASSWORD}

出力例

Created [https://sqladmin.googleapis.com/sql/v1beta4/projects/cymbal1/instances/menu-instance].
NAME: menu-instance
DATABASE_VERSION: POSTGRES_12
LOCATION: us-east1-a
TIER: db-custom-2-4096
PRIMARY_ADDRESS: -
PRIVATE_ADDRESS: 10.8.80.5
STATUS: RUNNABLE
  1. データベース インスタンスにデータベースを追加する
gcloud sql databases create $DB_DATABASE --instance=$DB_INSTANCE_NAME

出力例

Created database [menu-db].
instance: menu-catalog
name: menu-db
project: cymbal1
  1. SQL ユーザーを作成する
gcloud sql users create ${DB_USER} \
    --password=$DB_PASSWORD \
    --instance=$DB_INSTANCE_NAME

出力例

Created user [menu-user].
  1. データベースの IP アドレスを保存する
export DB_INSTANCE_IP=$(gcloud sql instances describe $DB_INSTANCE_NAME \
    --format=json | jq \
    --raw-output ".ipAddresses[].ipAddress")
  1. Compute Engine サービス アカウントに Cloud SQL クライアントのロールを追加する
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
--role="roles/cloudsql.client"

出力例

Updated IAM policy for project [cymbal1].
[...]

5. サーバーレス VPC

サーバーレス VPC アクセスを使用すると、Cloud Run、App Engine、Cloud Functions などのサーバーレス環境から Virtual Private Cloud ネットワークに直接接続できます。サーバーレス VPC アクセスを構成すると、サーバーレス環境で内部 DNS と内部 IP アドレス(RFC 1918 と RFC 6598 で定義)を使用して VPC ネットワークにリクエストを送信できます。これらのリクエストに対するレスポンスも内部ネットワークを使用します。

Cloud Run サービスが Cloud SQL に接続するためのサーバーレス VPC アクセス コネクタを作成します。

19c7b05f35789fda.png

  1. Cloud SQL インスタンスと同じ VPC ネットワークにサーバーレス VPC アクセス コネクタを作成します。
gcloud compute networks vpc-access connectors create ${SERVERLESS_VPC_CONNECTOR} \
    --region=${REGION} \
    --range=10.8.0.0/28

出力例

Created connector [cymbalconnector].

6. Cloud Run へのデプロイ

Docker イメージをビルドして Cloud Run にデプロイし、Cloud Run をサーバーレス VPC コネクタに接続して Cloud SQL データベースにアクセスします。

  1. Maven を使用してアプリケーションをコンパイルする
./mvnw package -DskipTests

出力例

[...]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  42.864 s
[INFO] Finished at: 2022-04-28T16:15:33Z
[INFO] ------------------------------------------------------------------------
  1. Docker イメージをビルドします。
docker build -f src/main/docker/Dockerfile.jvm \
    --tag gcr.io/$PROJECT_NAME/menu-service .

出力例

[...]
Successfully built 4ef5d7a3befc
Successfully tagged gcr.io/cymbal1/menu-service:latest
  1. Docker イメージを Container Registry に push します。
docker push gcr.io/$PROJECT_NAME/menu-service

出力例

Using default tag: latest
The push refers to repository [gcr.io/cymbalsql/menu-service]
17b374963800: Pushed
d9a51c06430d: Pushed
fff5d2a2cfc9: Pushed
f21fceb558c6: Pushed
5ffbbbf218dd: Pushed
60609ec85f86: Layer already exists
f2c4302f03b8: Layer already exists
latest: digest: sha256:f64cb7c288dbf4ad9b12bd210c23c5aec1048dee040450ff2d9dbdf96e83a426 size: 1789
  1. メニュー サービスのデプロイ:
gcloud run deploy $MENU_SERVICE_NAME \
    --image=gcr.io/$PROJECT_NAME/menu-service:latest \
    --region $REGION \
    --allow-unauthenticated \
    --set-env-vars DB_USER=$DB_USER \
    --set-env-vars DB_PASS=$DB_PASSWORD \
    --set-env-vars DB_DATABASE=$DB_DATABASE \
    --set-env-vars DB_HOST=$DB_INSTANCE_IP \
    --vpc-connector $SERVERLESS_VPC_CONNECTOR \
    --project=$PROJECT_ID \
    --quiet

出力例

[...]
Done.
Service [menu-service] revision [menu-service-00002-xox] has been deployed and is serving 100 percent of traffic.
Service URL: https://menu-service-g2mfphytdq-uk.a.run.app

SQL 認証情報などの機密情報の保存には、Secret Manager を使用することをおすすめします。Cloud Run では、シークレットを環境変数として渡すか、ボリュームとしてマウントできます。

  1. 店舗メニューのサービス URL:
MENU_SERVICE_URL=$(gcloud run services describe menu-service \
  --platform managed \
  --region $REGION \
  --format=json | jq \
  --raw-output ".status.url")
  1. メニュー サービスの URL を確認する
echo $MENU_SERVICE_URL

出力例

https://menu-service-g2mfphytdq-uk.a.run.app

7. サービスをテストする

  1. POST リクエストを送信して新しいメニュー項目を作成します。
curl -X POST "${MENU_SERVICE_URL}/menu" \
  -H 'Content-Type: application/json' \
  -d '{
       "itemImageURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
       "itemName": "Curry Plate",
       "itemPrice": 12.5,
       "itemThumbnailURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
       "spiceLevel": 3,
       "status": "Ready",
       "tagLine": "Spicy touch for your taste buds!!"
   }'

出力例

{
    "id": 16,
    "createDateTime": "2022-04-28T18:14:04.17225",
    "itemImageURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
    "itemName": "Curry Plate",
    "itemPrice": 12.5,
    "itemThumbnailURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
    "spiceLevel": 3,
    "status": "Processing",
    "tagLine": "Spicy touch for your taste buds!!",
    "updateDateTime": "2022-04-28T18:14:04.172298"
}
  1. PUT リクエストを送信してメニュー項目のステータスを変更します。
curl -X PUT "${MENU_SERVICE_URL}/menu/1" \
  -H 'Content-Type: application/json' \
  -d '{"status": "Ready"}'

出力例

{
    "id": 1,
    "createDateTime": "2022-04-28T17:21:02.369093",
    "itemImageURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
    "itemName": "Curry Plate",
    "itemPrice": 12.50,
    "itemThumbnailURL": "https://images.unsplash.com/photo-1631452180519-c014fe946bc7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1587&q=80",
    "spiceLevel": 0,
    "status": "Ready",
    "tagLine": "Spicy touch for your taste buds!!",
    "updateDateTime": "2022-04-28T17:21:02.657636"
}

8. 完了

お疲れさまでした。これでこの Codelab は終了です。

次のステップ:

Cymbal Eats の他の Codelab を確認する:

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

プロジェクトの削除

課金を停止する最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。