Private Service Connect(PSC)を使って別プロジェクト間でDatastreamをつなげる

Google Cloud

2025.9.22

Topics

はじめに

Google Cloud 上でデータ分析基盤を構築する際、Cloud SQL から BigQuery へのデータ連携はよく想定されるユースケースかと思います。
それぞれのリソースが別のプロジェクトに存在する場合、ネットワーク構成などハマりやすいポイントがあります。

本構成を実現するうえで、実際に私がハマったポイントをご紹介します。

Datastream の設定としてプライベート接続構成を作成していたため、MySQL プロファイルの作成の際に Cloud SQL に割り振られたプライベートIPに向けて接続テストを実施したところ、接続がタイムアウトしテストに失敗するという状態でした。

こちらについては、以下の記事に注意書きとして Proxy(NAT VM)が必要という記載がありました。

フルマネージド データベース(Cloud SQL など)を使用しているか、ソースが存在するリージョンで Datastream が実行されていない場合は、NAT VM が必要です。
参考: 接続プロファイルの作成

そのため、Compute Engine を用いて Cloud SQL Auth Proxy を作成し、その IP を指定することで問題なく接続することができました。

構成イメージ

本記事では、

  • アカウントA: Cloud SQL
  • アカウントB: Datastream / BigQuery / Cloud SQL Auth Proxy

という前提で、Private Service Connect(PSC)を活用した Datastream 連携の構築手順をまとめます。
gcloudコマンドを利用する想定ですので、CloudShell上やローカル環境にgcloudコマンドのインストールを行い実行してください。

実行コマンド

変数定義

以下の変数は必要に応じて修正ください。

export REGION="asia-northeast1"

# アカウントA向け (Cloud SQL 側)
export A_PROJECT="accounta-123456"
export CLOUDSQL_INSTANCE="accounta-mysql"
export CLOUDSQL_USER="root"
export CLOUDSQL_PASSWORD="password"

# アカウントB向け (Datastream / Proxy VM など)
export B_PROJECT="accountb-123456"
export B_VPC="datastream-vpc"
export B_SUBNET="datastream-subnet"
export B_SUBNET_CIDR="10.0.0.0/24"
export DB_PORT=3306
export DS_PC_NAME="ds-to-vpc-datastream"
export DS_PEERING_CIDR="172.20.255.248/29"
export BQ_DATASET="accounta-mysql-dataset"
export PROXY_VM_NAME="ds-csql-proxy"
export PROXY_SA_NAME="proxy-vm-sa"
export PSC_ADDR_NAME="psc-csql-endpoint-ip"

export PROXY_SA_EMAIL="${PROXY_SA_NAME}@${B_PROJECT}.iam.gserviceaccount.com"
export ZONE="${REGION}-b"
export CLOUDSQL_CONN="${A_PROJECT}:${REGION}:${CLOUDSQL_INSTANCE}"

1) アカウントA/B向け API を有効化

# A: Cloud SQL 側
gcloud services enable compute.googleapis.com servicenetworking.googleapis.com sqladmin.googleapis.com \
  --project="${A_PROJECT}"

# B: Datastream / BigQuery 側
gcloud services enable compute.googleapis.com datastream.googleapis.com bigquery.googleapis.com \
  --project="${B_PROJECT}"

2) アカウントB向け VPC / サブネットを作成

gcloud compute networks create "${B_VPC}" \
  --project="${B_PROJECT}" \
  --subnet-mode=custom

gcloud compute networks subnets create "${B_SUBNET}" \
  --project="${B_PROJECT}" \
  --region="${REGION}" \
  --network="${B_VPC}" \
  --range="${B_SUBNET_CIDR}" \
  --enable-private-ip-google-access

3) アカウントA向け Cloud SQL の PSC 有効化と設定確認

# PSC を有効化し、B プロジェクトを許可
gcloud sql instances patch "${CLOUDSQL_INSTANCE}" \
  --project="${A_PROJECT}" \
  --enable-private-service-connect \
  --allowed-psc-projects="${B_PROJECT}"

既存インスタンスの PSC の有効化については、ダウンタイムが約45秒発生しますので注意が必要です。
参考 : インスタンスで Private Service Connect を有効にする

# Public IP が付与されていないことを確認
gcloud sql instances describe "${CLOUDSQL_INSTANCE}" \
  --project="${A_PROJECT}" \
  --format='value(settings.ipConfiguration.ipv4Enabled)'
# 想定: False

# PSC が有効化され、B プロジェクトが許可されていることを確認
gcloud sql instances describe "${CLOUDSQL_INSTANCE}" \
  --project="${A_PROJECT}" \
  --format='value(settings.ipConfiguration.pscConfig.pscEnabled,settings.ipConfiguration.pscConfig.allowedConsumerProjects[0])'
# 想定: True  ${B_PROJECT}

# サービスアタッチメント URI を取得(B 側で使用)
export SVC_ATTACH_URI="$(gcloud sql instances describe "${CLOUDSQL_INSTANCE}" \
  --project="${A_PROJECT}" \
  --format='value(pscServiceAttachmentLink)')"

4) アカウントB向け PSC エンドポイントを作成

# 内部 IP 予約
gcloud compute addresses create "${PSC_ADDR_NAME}" \
  --project="${B_PROJECT}" \
  --region="${REGION}" \
  --subnet="${B_SUBNET}"

# PSC エンドポイント作成
gcloud compute forwarding-rules create psc-to-cloudsql \
  --project="${B_PROJECT}" \
  --region="${REGION}" \
  --network="${B_VPC}" \
  --subnet="${B_SUBNET}" \
  --address="${PSC_ADDR_NAME}" \
  --target-service-attachment="${SVC_ATTACH_URI}" \
  --allow-psc-global-access

5) アカウントB向け Proxy VM 用サービスアカウント作成と権限付与

gcloud iam service-accounts create "${PROXY_SA_NAME}" \
  --project="${B_PROJECT}" \
  --display-name="Datastream Proxy VM SA"

# A 側に cloudsql.client を付与
gcloud projects add-iam-policy-binding "${A_PROJECT}" \
  --member="serviceAccount:${PROXY_SA_EMAIL}" \
  --role="roles/cloudsql.client"

6) アカウントB向け Cloud SQL Auth Proxy を作成

gcloud compute instances create "${PROXY_VM_NAME}" \
  --project="${B_PROJECT}" \
  --zone="${ZONE}" \
  --machine-type=e2-micro \
  --network-interface=subnet="${B_SUBNET}",no-address \
  --tags=allow-datastream \
  --service-account="${PROXY_SA_EMAIL}" \
  --scopes=cloud-platform \
  --metadata=cloudsql-conn="${CLOUDSQL_CONN}",db-port="${DB_PORT}",psc-ip="${PSC_IP}",cloudsql-dns="${DNS_NAME}",startup-script='#!/bin/bash
set -eux

# 1) パッケージインストール
apt-get update
apt-get install -y wget
install -d /usr/local/bin
wget -q https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.11.4/cloud-sql-proxy.linux.amd64 -O /usr/local/bin/cloud-sql-proxy
chmod +x /usr/local/bin/cloud-sql-proxy

# 2) パラメータ取得(インスタンスメタデータ)
get_md () { curl -fsH "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/$1"; }
CONN="$(get_md cloudsql-conn)"
PORT="$(get_md db-port || echo 3306)"
PSC_IP="$(get_md psc-ip)"
CLOUDSQL_DNS="$(get_md cloudsql-dns)"

# 3) /etc/hostsにPSCエンドポイントのDNS解決を追加
echo "${PSC_IP} ${CLOUDSQL_DNS}" >> /etc/hosts

# 4) systemd ユニット作成
cat >/etc/systemd/system/cloud-sql-proxy.service <<EOF
[Unit]
Description=Cloud SQL Auth Proxy (PSC)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/cloud-sql-proxy --psc --address=0.0.0.0 --port=${PORT} ${CONN}
Restart=always
RestartSec=3
AmbientCapabilities=CAP_NET_BIND_SERVICE
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target
EOF

# 5) 起動 & 自動起動
systemctl daemon-reload
systemctl enable --now cloud-sql-proxy
'

7) アカウントA向け Cloud SQL の CDC 有効化とユーザー作成

gcloud sql instances patch "${CLOUDSQL_INSTANCE}" \
  --project="${A_PROJECT}" \
  --enable-bin-log

gcloud sql users create "${CLOUDSQL_USER}" \
  --instance="${CLOUDSQL_INSTANCE}" \
  --project="${A_PROJECT}" \
  --password="${CLOUDSQL_PASSWORD}"

8) アカウントB向け Datastream を設定(Private Connection / 接続プロファイル / ストリーム)

cat > mysql_source_config.json <<'JSON'
{
  "includeObjects": { "mysqlDatabases": [ { "database": "%" } ] }
}
JSON

cat > bq_dest_config.json <<JSON
{
  "singleTargetDataset": { "datasetId": "${B_PROJECT}:${BQ_DATASET}" },
  "dataFreshness": "900s"
}
JSON

gcloud datastream streams create cloudsql-to-bq \
  --project="${B_PROJECT}" \
  --location="${REGION}" \
  --display-name="Cloud SQL to BigQuery via Private Service Connect" \
  --source="projects/${B_PROJECT}/locations/${REGION}/connectionProfiles/cloudsql-mysql-source" \
  --destination="projects/${B_PROJECT}/locations/${REGION}/connectionProfiles/cloudsql-bigquery" \
  --mysql-source-config=mysql_source_config.json \
  --bigquery-destination-config=bq_dest_config.json \
  --backfill-all

作成したストリームの対象テーブルを変更する

作成したストリームを選択 -> 編集 -> ソース構成を変数 から、対象とするテーブル等の設定を作成後に編集することも可能です。

おわりに

本記事では、異なるプロジェクト間で Cloud SQL から BigQuery へのデータ連携を実現するために、Private Service Connect(PSC)を活用した Datastream 構成の構築手順をご紹介しました。
同じ課題に直面している方の参考になれば幸いです。

NHN テコラスの採用情報はこちら

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

waka

2022年に中途入社した人です。好きなAWSサービスはLambdaです。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら