事の発端

管理者用プロジェクト内でCloudSQLやMemoryStoreを用いて管理者データを一括保存し、プロジェクトを跨って複数のユーザー用プロジェクトから1:Nでアクセスしたい案件がありました。

VPC peeringで各プロジェクトのVPCを繋げればいけるか?と試してみた所ダメでした。

少し調査したら、以下の様な投稿が見つかりました。

https://stackoverflow.com/questions/79496083/connect-to-cloud-sql-in-another-project-and-vpc-using-cloud-run-and-serveless-vp

要するに以下の図の様になっていると思われます。

ついつい忘れがちですが、CloudSQL、MemoryStoreなどのマネージドサービスはGoogleが管理している独自のVPCに所属しています。そこにVPC コネクターやDirect Egressを使って自分たちのVPCに繋いでいます。

また、VPC PeeringはVPC AとVPC Bを繋いでも、Bを踏み台に他の繋がっているネットワークへは移動出来ないと言う「推移性ピアリングの制限」があります。

つまりVPC AからVPC Bへ移動、その後VPC BからGoogle管理VPCのCloudSQLへ移動しようとすると推移性ピアリングの制限に引っかかる訳です。

推移性ピアリングについては理解していたのですが、マネージドサービスはGoogle管理の別VPCの部分が普段VPC Direct Egressを使っているので頭から抜けていました。

本題

ここから本題に入りますが、じゃあどうすれば良いかと言うとPSC(Private Service Connect)を使います。

https://docs.cloud.google.com/vpc/docs/private-service-connect?hl=ja

PSCはプロジェクト・VPCの内外を問わず繋げる経路であり、その末端PSCエンドポイントをアクセスしたい側のVPCにプライベートIPを付けてデプロイします。

そうする事でVPC内にあるCloudRunからそのプライベートIPに通信すれば別プロジェクトのCloudSQLやMemoryStoreにアクセス出来ます。

ただしサービス自体がPSCに対応している必要があります。

設定方法

Private Service Connect

  1. プロジェクトA(CloudRun側)のコンソール上で「Private Service Connect」と入力する。
  2. 接続ポリシー」の項目をクリックし、「Create connection policy」をクリック。
  3. 以下を設定して、接続ポリシーを2個作成する。
    1.  サービス名
      1. CloudSQL
      2. Memorystore(後述のterraformでも作成可)
    2. VPC
    3. リージョン
    4.  接続数(例:10)

CloudSQL

コンソール上で「CloudSQL」と入力し、「インスタンスを作成」をクリック。

インスタンス作成画面下部の折り畳まれた「接続」の中、「パブリックIP」の上に「PSC」の設定があるのでクリック。

新しいエンドポイント」プロジェクトAのVPCを指定します。

これでCloudSQL側からプロジェクトAに対してアクセス許可を出し、許可したプロジェクトからのみエンドポイントが作成されます。

Memorystore for Redis Cluster

(※InstanceはPSC未対応)

clusterへの接続方法としてデフォルトでPSCが採用されています。ただしデフォルトでは同プロジェクト内の指定VPCに対してのみ作成されます。

1回のデプロイで2個作成され、片方が6379ポートを使うディスカバリ接続というものです。

外部からアクセスする場合はこのディスカバリ接続のプライベートIPを指定して接続して下さい。

別プロジェクトからアクセスするためには、Clusterから別途許可を出してエンドポイントを作成する必要がありますが、恐らくコンソールでは不可能な作業だと思われます(同プロジェクトのVPCしか設定項目が存在しない)

今回はterraformを使いました。必要なリソースは以下の通り。(Google CLIでも可能かも?)

プロジェクトB(Memorystore作成側)

  • google_redis_cluster
    • psc_configsで自身のプロジェクトへエンドポイントを自動作成
  • google_network_connectivity_service_connection_policy
    • 接続ポリシー(自身のプロジェクトを許可)

プロジェクトA(CloudRun側)

  • google_network_connectivity_service_connection_policy
    • 接続ポリシー
  • google_redis_cluster_user_created_connections
    • プロジェクトBのredis内にプロジェクトAのVPCへ許可を作成する
  • google_compute_forwarding_rule ×2
  • google_compute_address ×2
    • PSCエンドポイント

 

確認方法も恐らくRedisのコンソール上には無く、以下のコマンドをcloudShell上やgcloud loginしたクライアント上で実行します。

gcloud redis clusters describe INSTANCE_ID --region=REGION_ID --project=PROJECT_ID

新しいPSC作成に成功しているとレスポンスのpscConnection項目に新たに2つのプライベートIPが追加されています。

– connections:
  – pscAutoConnection:
       address: 10.0.2.9(プロジェクトBのVPC ※自動作成)
       …
       address: 10.0.2.8(プロジェクトBのVPC ※自動作成)
  – pscConnection:
       address: 10.0.1.3(プロジェクトAのVPC ※ユーザー作成)
       …
       address: 10.0.1.4(プロジェクトAのVPC ※ユーザー作成)

疎通確認

疎通の確認方法としては、Google Cloudのコンソール上に「接続テスト」いう機能があり、それを利用しました。

開始地点をさまざまなサービスにして、ネットワーキング・セキュリティ的にそこまでの経路が繋がっているか調べる事が出来ます。

今回は始点:CloudRunと終点:PSCエンドポイント(CloudSQL、Redisのディスカバリー)になります。

ただし注意が必要なのが、Redis Clusterの疎通が確認出来るのがPSC作成から1日程度時間を開けないといけない点です。(名前解決などの伝播が遅い?)

ここで自分は設定が正しく出来てないと思ってPSCの設定と1日無駄に格闘していました・・・次の日には繋がる様になっていました。

CloudSQLのPSCエンドポイントはすぐ疎通が確認出来ました。

 

まとめ

今回はPSCを用いたプロジェクトを跨いだ経路の作成方法でした。

例としてCLoudSQLとMemoryStore Redisを出しましたが、他にも様々なサービスでプライベートIPを使って内部通信出来る様になります。

プロジェクトを跨ぐ通信で重宝しますが、同プロジェクト内でも違うVPC同士での通信やインターネットに可能な限り出ない通信にも使えるのでこれを機にPSCでのネットワーク構築に挑戦してみて下さい。