共有VPC(Shared VPC)の「正解」を掴む:大規模組織におけるネットワーク境界の設計論
クラウドエンジニアの皆さん、こんにちは。現場で「VPCを分けるべきか、それともプロジェクトを分けるべきか」という問いに頭を抱えたことはありませんか?
プロジェクトが増えれば増えるほど、各チームにバラバラのネットワークを作らせるのは悪夢の始まりです。管理が分散し、ファイアウォールルールはスパゲッティ化し、しまいには「どこから誰がアクセスしているのか分からない」というセキュリティのブラックボックスが生まれます。
そんな泥沼を避けるための銀の弾丸こそが、Google Cloudの 「共有VPC(Shared VPC)」 です。今回は、単なる用語解説ではなく、トラブルシューティングで汗をかいたエンジニアの実感とともに、この設計の要諦を紐解いていきます。
—
1. 共有VPCのアーキテクチャ:境界線を見極める
共有VPCの設計思想は極めてシンプルです。「ネットワークの管理権限(ホスト)」と「リソースの利用権限(サービス)」を明確に分離することです。
- ホストプロジェクト: ネットワークの「司令塔」。VPC、サブネット、ルート、ファイアウォールルールを一元管理します。
- サービスプロジェクト: リソースの「居住区」。Compute Engine、GKE、Cloud SQLなどが配置されます。
この分離により、ネットワークエンジニアは「ガードレール」を敷き、開発者はその中で自由にアプリケーションをデプロイするという、理想的な責務分担が可能になります。
—
2. なぜ「共有VPC」を使うのか?:実務の現場から
なぜ単一プロジェクトに押し込めず、わざわざ共有VPCという手間をかけるのか。理由は明確です。
1. IPアドレスの枯渇と枯渇防止: サブネットを一括管理することで、CIDRブロックを効率よく払い出し、CIDR重複の悲劇を防げます。
2. ファイアウォールの一元管理: 各プロジェクトで「お行儀の悪い」ルールが作られるのを防ぎます。
3. セキュリティ境界の確立: ネットワークの変更権限をネットワークチームに集中させ、開発チームはアプリケーションのデプロイに集中させることで、ガバナンスと生産性を両立できます。
—
3. 実践:共有VPCの設定フロー
共有VPCを構築する際、最も重要なのは「権限委譲」のプロセスです。これを忘れると、サービスプロジェクトからホスト側のサブネットが見えず、一日中デバッグすることになります。
手順1: ホストプロジェクトの有効化(gcloud)
まずはホストプロジェクトを定義します。
# ホストプロジェクトとして有効化する
gcloud compute shared-vpc enable [HOST_PROJECT_ID]
手順2: サービスプロジェクトをアタッチする
次に、サービスプロジェクトをホストに「招待」します。
# サービスプロジェクトをホストプロジェクトに関連付ける
gcloud compute shared-vpc associated-projects add [SERVICE_PROJECT_ID] \
--host-project [HOST_PROJECT_ID]
手順3: 権限(IAM)の付与:ここが肝!
ここが最もハマりやすいポイントです。サービスプロジェクトのGKEノードやVMがサブネットを使うには、プロジェクトのIAMロールではなく、「サブネット単位」で権限を付与する必要があります。
# サービスプロジェクトのGKEサービスアカウントにサブネット利用権限を付与
gcloud compute networks subnets add-iam-policy-binding [SUBNET_NAME] \
--project [HOST_PROJECT_ID] \
--region [REGION] \
--member "serviceAccount:[PROJECT_NUMBER]@container-engine-robot.iam.gserviceaccount.com" \
--role "roles/compute.networkUser"
—
4. Web API通信のデバッグ:パケットはどこを流れるか
共有VPC環境下で、サービスA(サービスプロジェクト1)からサービスB(サービスプロジェクト2)へのAPI呼び出しを行う際、何が起きているのでしょうか。
PythonによるAPIリクエスト例
import requests
# 共有VPC内の別サービスへの内部通信
# ホストプロジェクトで定義されたプライベートIP(例: 10.0.1.5)に対してリクエスト
url = "http://10.0.1.5:8080/v1/resource"
try:
response = requests.get(url, timeout=5)
# レスポンスの確認
print(f"Status Code: {response.status_code}")
except requests.exceptions.ConnectionError:
# 接続失敗時はファイアウォールの設定を確認すること!
print("接続不可:ホストプロジェクトのFirewallルールを見直してください")
シニアSREからのアドバイス:
もし接続エラー(ConnectionError)が発生したら、まず疑うべきは「サービスプロジェクトのプロジェクトIDではなく、ホストプロジェクトのファイアウォール設定」です。ホストプロジェクトで tag や serviceAccount を用いた ingress ルールが正しく設定されているかを確認してください。
—
5. 運用上のTips:トラブルシューティングの作法
現場で共有VPCを運用する際、以下の3点は「お守り」として持っておいてください。
- VPC Service Controlsとの併用: 共有VPCは強力ですが、データ持ち出しを防ぐには
VPC Service Controlsを重ね掛けするのが今の時代のスタンダードです。 - ファイアウォールの階層管理: ホストプロジェクトのファイアウォールルールには、「誰が、どのポートを、どのサービスに対して許可したか」を説明する
descriptionを必ず記述する文化を作りましょう。 - ログの可視化: 通信の断絶を追うには、
VPC Flow Logsを対象サブネットで有効化しておくのが鉄則です。Cloud Loggingで「どのIP間での通信がDROPされたか」が即座に分かります。
まとめ:ネットワークは「見えないインフラ」ではない
共有VPCは、単なるネットワークの共有機能ではありません。それは組織の権限構造をネットワークレイヤーに投影したものです。
最初は少し複雑に感じるかもしれませんが、大規模なプロダクトになればなるほど、この「分離」の恩恵を痛感するはずです。まずは小さなプロジェクトから、サブネットの管理権限を切り出すところから始めてみてください。
「ネットワーク設定を触るのが怖い」というフェーズを脱却し、「意図した通りにパケットを制御できている」という確信を持てるエンジニアが増えることを願っています。
何か詰まったら、まずは gcloud compute networks subnets get-iam-policy で権限を再確認すること。それがトラブル解決の最短ルートです。
コメント