Cloud Run Functions から Cloud SQL にアクセスしてみる
ある検証をしていたところ、Cloud Run functions から、パブリックIPを持たない CloudSQL に接続しようとしたら少し手こずったので方法をメモします。
今回作るもの
今回は、以下のリソースを作っていきます。
- VPC
- サーバーレス VPC アクセス コネクタ
- Cloud Run functions
- Cloud SQL インスタンス
今回のポイントは「サーバーレス VPC アクセス コネクタ」です。
サーバーレス VPC アクセス コネクタ とは
Cloud Run functions は、VPC外のリソースです。
プライベートIPしか持たない Cloud SQL インスタンスに対して Cloud Run functions がアクセスするには、VPC への入り口を作る必要があります。
Cloud Run functions のようなサーバレスサービスでは、サーバーレス VPC アクセス コネクタを使用することで VPC リソースへアクセスできるようになります。
やってみる
1. VPCネットワークの作成
まず、Cloud SQL とサーバーレス VPC アクセス コネクタが使用する VPC ネットワークを作成します。
# VPCネットワークの作成
gcloud compute networks create my-vpc-network \
--subnet-mode=custom \
--bgp-routing-mode=regional
これで、VPC が作成されました。
2. Cloud SQLインスタンスの作成
プライベートIPのみを持つ Cloud SQL インスタンスを作成します。
また、同時に Cloud SQL インスタンスへ接続するために必要なプライベートサービス接続もこのステップで作成します。
# Cloud SQL 用のプライベートIPアドレス範囲を予約
gcloud compute addresses create google-managed-services-my-vpc-network \
--global \
--purpose=VPC_PEERING \
--prefix-length=16 \
--network=my-vpc-network
# プライベートサービス接続の作成
gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=google-managed-services-my-vpc-network \
--network=my-vpc-network
# Cloud SQLインスタンスの作成(プライベートIPのみ)
gcloud sql instances create my-sql-instance \
--database-version=MYSQL_8_0 \
--tier=db-n1-standard-1 \
--region=asia-northeast1 \
--root-password=${DB_PASSWORD} \
--network=projects/$GOOGLE_CLOUD_PROJECT/global/networks/my-vpc-network \
--no-assign-ip
※ DB_PASSWORD は、適切なパスワードに変更してください。
このコマンドで、以下のリソースが作成されました。
3. サーバーレス VPC アクセス コネクタの作成
Cloud Run functions が VPC 内のリソースにアクセスするためのコネクタを作成します。
gcloud compute networks vpc-access connectors create my-connector \
--region=asia-northeast1 \
--network=my-vpc-network \
--range=10.0.0.0/28 \
--min-instances=2 \
--max-instances=10 \
--machine-type=e2-micro
IP レンジが被っている場合は、既存サブネットとの重複がないように修正してください。
ただし、サブネットマスクは28である必要がある点に注意してください。
作成されたリソースは以下です。
4. Cloud Run functionsの実装
Cloud SQL に接続する関数を実装します。
package.json
{
"name": "cloudsql-function",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@google-cloud/functions-framework": "^3.0.0",
"mysql2": "^3.0.0"
}
}
index.js
const functions = require('@google-cloud/functions-framework');
const mysql = require('mysql2/promise');
// Cloud SQL接続設定
const connectionConfig = {
host: process.env.DB_HOST, // Cloud SQLのプライベートIP
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
port: 3306
};
functions.http('connectToCloudSQL', async (req, res) => {
let connection;
try {
// データベースに接続
connection = await mysql.createConnection(connectionConfig);
// クエリの実行例
const [rows] = await connection.execute('SELECT NOW()');
res.status(200).json({
success: true,
message: 'Cloud SQLへの接続に成功しました',
data: rows[0]
});
} catch (error) {
console.error('データベース接続エラー:', error);
res.status(500).json({
success: false,
message: 'Cloud SQLへの接続に失敗しました',
error: error.message
});
} finally {
if (connection) {
await connection.end();
}
}
});
5. Cloud Run functionsのデプロイ
先ほど作成したコネクタを使用するように、関数をデプロイします。
gcloud functions deploy connect-to-cloud-sql \
--gen2 \
--runtime=nodejs20 \
--region=asia-northeast1 \
--source=. \
--entry-point=connectToCloudSQL \
--trigger-http \
--no-allow-unauthenticated \
--vpc-connector=my-connector \
--egress-settings=private-ranges-only \
--set-env-vars=DB_HOST=${CLOUD_SQL_PRIVATE_IP},DB_USER=${DB_USER},DB_PASSWORD=${DB_PASSWORD}
--vpc-connector
で、作成したVPCコネクタを指定することにより Cloud SQL インスタンスとの接続が行えるようになります。
--set-env-vars
に設定する環境変数は、変更して実行してください。
※パスワードは、実際の環境では環境変数にはセットせず Secret Manager や IAM 認証を使うことが望ましいです。今回はあくまで検証のため、この実装としています。
また、今回は検証目的として、以下のパラメータ設定を行っています。
--egress-settings
:private-ranges-only
を指定することで、プライベートIP範囲への通信のみコネクタ経由にする--no-allow-unauthenticated
: IAM認証が必要なように構成
6. 関数を呼び出して確認
Cloud Run functionsの「テスト」ボタンから、Cloud Shellでテストしてみます。
実際にアクセスが成功していることが確認できました。
まとめ
サーバーレス VPC アクセス コネクタを使用することで、Cloud Run functions から Cloud SQL へプライベート接続できることを確認しました。
筆者の場合、ちょっとしたデータベースの検証の際は環境の構築も不要な Cloud Run functions を使いたいケースが多いので、そういった方の助けになれば幸いです。