こんにちは。SREチームのシニアエンジニアです。
クラウドのインフラ設計をしていると、「マルチリージョン構成での可用性担保」や「レイテンシ削減のためのグローバル展開」という要件に必ず直面します。このとき、多くのエンジニアが最初に頭を悩ませるのが、「異なるリージョン間でどうやって安全かつシームレスにプライベートIPルーティングを通すか」という問題です。
AWSのVPCに慣れ親しんだエンジニアがGCP(Google Cloud)を触ると、最初にその「圧倒的な違い」にカルチャーショックを受けます。AWSでは基本的にVPCはリージョンリソースであり、別リージョン間のVPCを繋ぐにはVPCピアリングやTransit Gatewayの設定、さらには重複しないCIDR設計の頭の体操が必要不可欠でした。
しかし、GCPのVPCはデフォルトでグローバルリソースです。東京(asia-northeast1)とアイオワ(us-central1)のインスタンスが、まるで同じラックにいるかのように単一のプライベートIP空間(RFC 1918)で直接会話できる。この魔法のようなアーキテクチャの裏側で、Googleの巨大なバックボーンネットワークがどのように動いているのか。今回はその仕組みと、実務で絶対に知っておくべきパケットの挙動について解説します。
—
1. GCPグローバルVPCの正体:なぜリージョンを跨げるのか?
まず大前提として、GCPのVPCは「物理的な箱」ではありません。Googleのソフトウェア定義ネットワーク(SDN)である Andromeda(アンドロメダ) によって抽象化された、グローバルな論理ネットワークの概念です。
コントロールプレーンとデータプレーンの完全な分離
AWSなどの他社クラウドでは、リージョンごとにVPCのコントロールプレーンが独立しているケースが多いですが、GCPのVPCは、グローバルに分散された単一のコントロールプレーンを持ちます。
- グローバルVPCオブジェクト: サブネット(Subnet)はリージョンごとに作成しますが、VPC自体はグローバルです。
- 分散型データプレーン(Andromeda): 各ホスト(ハイパーバイザー)上に実装された仮想スイッチが、コントロールプレーンからの指示を受け取り、パケットのENCAP/DECAP(カプセル化/非カプセル化)をハードウェア(カスタムASICであるJupiterなど)の支援を受けながら超高速に処理しています。
プライベートIP空間の共有とルーティング
例えば、東京リージョンに 10.120.0.0/20、アイオワリージョンに 10.120.16.0/20 のサブネットを持つ単一のVPCを定義したとします。
このとき、東京のインスタンス(10.120.0.5)からアイオワのインスタンス(10.120.16.5)へ通信する際、パケットはパブリックインターネットに出ることはありません。Googleが世界中に張り巡らせたダークファイバー(専用バックボーン)の上を、カプセル化されたプライベートパケットが駆け抜けます。ルーティングテーブルの管理も自動で行われるため、ユーザーが明示的にルートを追加する必要すらないのです。
—
2. 通信フローの裏側:パケットはグローバルをどう旅するか?
では、実際にリージョンを跨いだHTTPリクエストが発生したとき、パケットレベルで何が起きているのでしょうか。東京のアプリケーションサーバーからアイオワのデータベースへクエリを投げるシナリオで追ってみましょう。
[Tokyo VM: 10.120.0.5]
│
▼ (プライベートIP宛てにパケット送出)
[Andromeda vSwitch (Tokyo)]
│
▼ (Google専用グローバルバックボーンへカプセル化して送出)
[Google Global Backbone Network]
│
▼ (アイオワへ到着、デカプセル化)
[Andromeda vSwitch (Iowa)]
│
▼
[Iowa DB: 10.120.16.5]
1. ソケットのオープン: 東京のアプリがアイオワのDBのプライベートIP(10.120.16.5:5432)に対してTCPハンドシェイクを開始します。
2. 仮想NICでの処理: 東京側の仮想マシン(VM)のNIC(Virtio-net等)から出たパケットは、ホスト上のAndromeda仮想スイッチにキャプチャされます。
3. グローバルカプセル化: Andromedaは、このパケットが別リージョン宛てであることを認識し、GoogleのプライベートWAN網でルーティングするための外側ヘッダを付与します。
4. ダークファイバー経由の転送: パケットは一般のインターネットとは完全に隔離されたGoogleの海底ケーブルおよび陸上バックボーンに乗せられ、最小レイテンシのパスを通ってアイオワのデータセンターへ到達します。
5. デカプセル化と配送: アイオワ側のAndromedaが外側ヘッダを剥ぎ取り、宛先のDBインスタンスの仮想NICへネイティブなIPパケットとしてインジェクションします。
この一連の処理がハードウェアアクセラレーションによって数マイクロ秒単位で完了するため、開発者は「遠くのリージョンにある」という意識を極限まで薄めてアーキテクチャを組むことができます。
—
3. 実践:TerraformによるグローバルVPCとマルチリージョンサブネットの構築
口で言うだけではなく、実際にコードでこのグローバルVPCを構築してみましょう。Terraformを使って、東京とアイオワにまたがるVPCネットワークを定義します。
# プロバイダーの設定
provider "google" {
project = "your-production-project-id"
region = "asia-northeast1"
}
# 1. グローバルVPCネットワークの定義
# auto_create_subnetworks = false にすることで、リージョンごとに手動でサブネットを制御します
resource "google_compute_network" "global_vpc" {
name = "prod-global-vpc"
auto_create_subnetworks = false
routing_mode = "GLOBAL" # ← ここがポイント!グローバルルーティングを有効化
description = "Tokyo and Iowa cross-region global VPC"
}
# 2. 東京リージョン用サブネットの作成
resource "google_compute_subnetwork" "tokyo_subnet" {
name = "prod-subnet-asia-northeast1"
ip_cidr_range = "10.120.0.0/20"
region = "asia-northeast1"
network = google_compute_network.global_vpc.id
}
# 3. アイオワリージョン用サブネットの作成
resource "google_compute_subnetwork" "iowa_subnet" {
name = "prod-subnet-us-central1"
ip_cidr_range = "10.120.16.0/20"
region = "us-central1"
network = google_compute_network.global_vpc.id
}
# 4. 異なるリージョン間でもプライベートIPで通信を許可するファイアウォールルール
resource "google_compute_firewall" "allow_internal" {
name = "allow-global-vpc-internal"
network = google_compute_network.global_vpc.name
allow {
protocol = "tcp"
ports = ["0-65535"]
}
allow {
protocol = "udp"
ports = ["0-65535"]
}
allow {
protocol = "icmp"
}
# VPC内の全プライベートIPレンジからの通信を許可
source_ranges = ["10.120.0.0/16"]
}
ここで注目してほしいのが、google_compute_network 内の routing_mode = "GLOBAL" というパラメータです。これを指定することで、Cloud Router等を用いた動的ルーティング(BGP)において、あるリージョンで学習したルートを他のすべてのリージョンへグローバルに伝播させることが可能になります。
—
4. アプリケーション層からの検証:Pythonによるリージョン間疎通確認
グローバルVPCが正しく機能しているか、実際にアプリケーションコードから確認してみましょう。東京リージョンのVM上で動くPythonスクリプトから、アイオワリージョンのVM上で立ち上げた軽量なHTTPサーバーへリクエストを投げ、正常にプライベートIP経由でレスポンスが返ってくるかをテストします。
以下のスクリプトは、東京のインスタンスからアイオワのインスタンスのプライベートIP(10.120.16.10)へHTTPリクエストを送信するサンプルです。
import urllib.request
import urllib.error
import json
import sys
# アイオワリージョンにあるバックエンドVMのプライベートIP
IOWA_SERVER_IP = "10.120.16.10"
PORT = 8080
URL = f"http://{IOWA_SERVER_IP}:{PORT}/healthz"
def check_cross_region_connectivity():
print(f"[*] Connecting to Iowa backend at {URL} via Global VPC...")
try:
# タイムアウトを3秒に設定し、プライベートネットワーク経由での応答速度を測る
req = urllib.request.Request(URL, headers={"User-Agent": "SRE-GlobalVPC-Checker/1.0"})
with urllib.request.urlopen(req, timeout=3.0) as response:
status_code = response.getcode()
body = response.read().decode("utf-8")
print(f"[SUCCESS] Status Code: {status_code}")
print(f"[SUCCESS] Response from Iowa: {json.loads(body)}")
except urllib.error.URLError as e:
print(f"[ERROR] Failed to communicate across regions: {e.reason}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"[ERROR] An unexpected error occurred: {str(e)}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
check_cross_region_connectivity()
このスクリプトを実行したとき、パブリックIPやVPNゲートウェイを一切経由せず、10.120.0.0/16 のCIDR内だけで通信が完結していれば、GCPのグローバルVPCアーキテクチャが正しく機能している証拠です。
—
5. 現場のSREが教える!実務でハマりがちな罠とトラブルシューティングTips
最後に、現場でグローバルVPCを運用する中で私たちが実際に踏み抜いた「痛い教訓」をいくつかシェアします。設計時の参考にしてください。
1. 「リージョン間通信=レイテンシゼロ」ではない
物理的な制約(光速の壁)はGoogleのバックボーンでも超えられません。東京とアイオワ間のおおよそのRTT(往復遅延)は約100ms〜110ms程度かかります。「同じVPC内だから」といって、東京のフロントエンドからアイオワのDBに対して同期的な細かいクエリ(N+1問題など)を何発も投げる設計にすると、アプリケーション全体のレスポンスタイムが致命的に悪化します。リージョンを跨ぐ通信は、バッチ処理や非同期レプリケーション、あるいはキャッシュ層を挟むなどの設計上の工夫が必要です。
2. ファイアウォールルールのスコープに注意
GCPのファイアウォールルールは、デフォルトではVPC全体に適用されます(グローバルリソース)。「特定のリージョンのサブネット間だけ通信を絞りたい」という要件がある場合は、target_tags(ターゲットタグ)や target_service_accounts を適切に組み合わせるか、あるいは階層的ファイアウォールポリシー(Hierarchical Firewall Policies)を利用して組織・フォルダ単位で制御する必要があります。
3. モニタリングには VPC Flow Logs を活用せよ
「本当にパケットが意図したリージョン間の最適パスを通っているのか?」を調査したいときは、サブネットごとに VPC Flow Logs を有効化し、BigQueryにエクスポートして解析するのが定石です。
ログ内の connection.gce_destination.project_id や bytes_sent をモニタリングすることで、予期せぬリージョン間トラフィックのバーストを検知できます。
—
まとめ
GCPのグローバルVPCは、マルチリージョンインフラの構築難易度を劇的に下げてくれる強力な武器です。しかし、その背後にある「グローバルなプライベートIP空間」と「高速なバックボーンネットワーク」の挙動を正しく理解していなければ、クラウド特有の思わぬパフォーマンス劣化やコストの罠に足元をすくわれることになります。
「なぜこの設計なのか」「パケットはどこを通っているのか」を常に頭に描きながら、堅牢でスケーラブルなクラウドインフラを構築していきましょう。皆さんの日々のSREライフの一助になれば幸いです。
コメント