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 データベースに接続する Service を 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 を生成できます。または、ご自身で試して、利用可能かどうかを確認することもできます。このステップ以降は変更できず、プロジェクトを通して同じ 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 ネットワークと基盤となる Google Cloud の VPC ネットワーク(Cloud SQL インスタンスが存在するネットワーク)との間の 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 に接続されます。静的 IP アドレスは各 VM に割り当てられ、アプリケーションの接続先 IP アドレスが Cloud SQL インスタンスの全存続期間を通して一定になるようにします。

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 イメージをコンテナ レジストリに 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. Menu サービスをデプロイします。
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. Store Menu サービスの 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 アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

プロジェクトの削除

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