【実務・中級編】 GCP共有VPC(Shared VPC)のホストプロジェクトとサービスプロジェクトのアーキテクチャ – クラウドインフラと仮想化ネットワーク実践ガイド

GCP共有VPC(Shared VPC)のアーキテクチャ:迷えるSREのためのネットワーク統治とIAM設計の極意

こんにちは。数々の修羅場――深夜のパケットロス調査や、本番環境でのファイアウォール設定ミスによる孤立劇――を潜り抜けてきたシニアSREの私だ。

クラウドの利用規模が拡大するにつれて、開発チームごとにGCPプロジェクトを切る「マルチプロジェクト戦略」をとる組織は多い。しかし、ここで必ずぶ Walls(壁)がある。「プロジェクトごとにVPCを作ったら、VPCピアリングのメッシュ地獄になって管理しきれなくなった」「オンプレミスや他リージョンとの閉域接続(Interconnect/VPN)をプロジェクトごとに構築・維持するのは予算的にも運用負荷的にも無理だ」という悲鳴だ。

このインフラ管理者の頭痛を一発で解消するのが、今回解説する GCP共有VPC(Shared VPC) である。

今回は、教科書的な仕様のなぞり書きではない。パケットがホストとサービスの間をどう駆け抜け、IAMの罠にどうハマり、いかにしてそれを回避するか。実務の現場で即座に使える知見を叩き込んでいこう。

—

1. 共有VPCの全体像:ホストとサービスという「主従」の概念

共有VPCの核心は極めてシンプルだ。「ネットワークの管理権限を持つ『ホストプロジェクト』」と、「そこで定義されたVPCやサブネットを間借りしてリソースをデプロイする『サービスプロジェクト』」を切り離すことにある。

+-------------------------------------------------------------+
| 【ホストプロジェクト】 (Network Adminが管理)                  |
|  - VPCネットワーク (shared-vpc)                             |
|    - サブネットA (10.128.0.0/20)                            |
|    - サブネットB (10.130.0.0/20)                            |
|  - 共有ファイアウォールルール                               |
+------------------------------+------------------------------+
                               | 共有 (Attach)
        +----------------------+----------------------+
        |                                             |
        v                                             v
+-------------------------------+             +-------------------------------+
| 【サービスプロジェクト A】       |             | 【サービスプロジェクト B】       |
|  - GKEクラスター A              |             |  - Cloud Run / Compute Engine |
|  - サブネットAを利用            |             |  - サブネットBを利用            |
+-------------------------------+             +-------------------------------+

このアーキテクチャの最大のメリットは、ネットワークの権限(Network Admin)と、アプリケーションのデプロイ権限(Developer)を完全に分離できる点にある。開発者は「勝手にサブネットのCIDRを切ってルーティングを壊す」という自由を奪われる代わりに、「安全に管理された基盤の上で、セキュアなマイクロサービスを爆速でデプロイする」という自由を手に入れるのだ。

—

2. 通信の裏側:パケットはどこを通り、どうルーティングされるのか?

「サービスプロジェクトのインスタンスから出たパケットは、どうやってホストプロジェクトのVPCを通るのか?」これは実務で必ず聞かれる質問だ。

結論から言えば、GCPの仮想ネットワークファブリック上では、ホストとサービスの境界線は完全に透過的である。

1. インターフェイスの生成: サービスプロジェクト側でGKEノードやCompute Engine(GCE)インスタンスを起動する際、アタッチするサブネットとしてホストプロジェクト内のリソース(例: projects/my-host-project/regions/asia-northeast1/subnetworks/app-subnet)を指定する。
2. IPアドレスの割当: IPアドレスはホストプロジェクトのサブネットのIPAMプールから払い出される。
3. ルーティングとファイアウォール: パケットが送信されると、GCPの分散仮想ルーターがホストプロジェクト側で定義されたルートテーブルとファイアウォールルール(VPCファイアウォール)を即座に適用する。サービスプロジェクト側で独自のファイアウォールを作る必要はない。むしろ作れない(権限がない)。

—

3. 構築のステップと実務で役立つTerraformコード例

口頭で説明してもピンと来ない若手のために、実際にインフラをコードでプロビジョニングする例を示そう。Terraformを使うのが現代のSREの標準だ。

ここでは、ホストプロジェクトに対してサービスプロジェクトをアタッチし、IAMを設定するまでのモダンな構成を記述する。

# ==========================================
# 1. ホストプロジェクトの有効化
# ==========================================
resource "google_compute_shared_vpc_host_project" "host" {
  project = "my-host-project-id"
}

# ==========================================
# 2. サービスプロジェクトの紐付け (アタッチ)
# ==========================================
resource "google_compute_shared_vpc_service_project" "service1" {
  host_project    = google_compute_shared_vpc_host_project.host.project
  service_project = "my-service-project-id"

  # ホストプロジェクトの有効化が完了してからアタッチを実行する依存関係
  depends_on = [google_compute_shared_vpc_host_project.host]
}

# ==========================================
# 3. サービスプロジェクトのプリンシパルに対するIAM付与
# (例: サービスプロジェクトのGKEサービスエージェントにネットワーク利用権限を付与)
# ==========================================
resource "google_project_iam_member" "service_agent_network_user" {
  project = google_compute_shared_vpc_host_project.host.project
  role    = "roles/compute.networkUser"
  
  # サービスプロジェクト側のKubernetes Engineサービスエージェントを指定
  member  = "serviceAccount:service-SVC_PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com"
}

実務の現場における最大の罠:IAM権限(roles/compute.networkUser)

共有VPCで最も多くのエンジニアが踏み抜く地雷が、このIAM権限の設計だ。

「サービスプロジェクトなんだから、サービスプロジェクト内だけでIAMを完結させたい」と思うのは人情だが、共有VPCでは「ホストプロジェクト側」のサブネットやVPCに対して、サービスプロジェクト側のリソース(特にGKEやCloud SQL、ロードバランサーなど)がアクセスするための許可を与える必要がある。

特にGKEを動かす場合、以下の両方が必要になる。

  • ホストプロジェクトの特定サブネットに対する roles/compute.networkUser
  • ホストプロジェクト自体に対する roles/container.hostServiceAgentUser (GKEがホスト側でネットワークリソースをプロビジョニングするため)

これを忘れると、クラスタ作成時に VPC network not found や Permission denied という、夜間対応を余儀なくされる美しくないエラーログに直面することになる。

—

4. 運用・トラブルシューティングの現場の知見

最後に、現場で実際に起きた障害から得た、生きたTipsを共有しよう。

トラブルシューティング:パケットが落ちるときの確認手順

もしサービスプロジェクト内のインスタンスから、外部または別サブネットへの通信が失敗した場合、以下のコマンドと手順でデバッグを試みてほしい。

1. IAMの確認
ホストプロジェクトのサブネット単位で、対象のサービスアカウント(GCEのデフォルトサービスアカウントやGKEのロボットアカウント)に roles/compute.networkUser が正しくバインドされているか、以下のgcloudコマンドで即座に確認する。

# サブネット単位でのIAMポリシー確認
   gcloud compute networks subnets get-iam-policy app-subnet \
       --region=asia-northeast1 \
       --project=my-host-project-id

2. ファイアウォールルールの評価順序
共有VPCでは、ホストプロジェクトに設定されたファイアウォールルールが全サービスプロジェクトに強制適用される。ログベースのファイアウォールロギングを有効化し、どのルール(プライオリティ)でドロップされているかを gcloud logging で追跡するのが鉄則だ。

3. 削除の順序ミスに注意(アンチパターン)
共有VPCを解体する際、ホストプロジェクト側を先に削除しようとすると、サービスプロジェクトがアタッチされたままのためエラーになる。必ず 「サービスプロジェクトのデタッチ $\to$ ホストプロジェクトの無効化」 の順序を守ること。

—

まとめ

GCP共有VPCは、単なるネットワークのコスト削減やIPアドレス節約のツールではない。「組織の権限委譲と、インフラのガバナンスを両立させるための最強のアーキテクチャパターン」である。

ホストとサービスの責務を明確に分け、適切なIAM(特に compute.networkUser と各種サービスエージェントの権限)を理解して実装すれば、あなたのクラウドインフラは泥臭いネットワーク管理から解放され、より本質的なプロダクト開発へとエンジニアのリソースを集中させることができるはずだ。

さあ、明日からの設計書には、迷うことなく共有VPCのアーキテクチャを組み込んでいこう。

コメント

タイトルとURLをコピーしました