- Google Cloud NATでプライベートVMから外部アクセスを実現する設計パターンを解説
- 静的IP・ポートアロケーション・ログ監視の設定をTerraformコード付きで紹介
- SES現場で活用できるネットワークセキュリティ設計とクラウドネットワークエンジニアのキャリア
「プライベートサブネットのVMから外部APIにアクセスしたいが、パブリックIPは付与したくない」——SES案件でクラウドインフラを設計するエンジニアなら、この要件に何度も直面しているはずです。セキュリティ上、VMに直接パブリックIPを割り当てるのは推奨されませんが、外部サービスとの通信は必須です。
**Google Cloud NAT(Network Address Translation)**は、プライベートIPしか持たないVMやGKE Podから外部インターネットへのアウトバウンド接続を可能にするマネージドサービスです。インバウンド接続は許可せず、外部からの不正アクセスを防ぎながら、必要な外部通信だけを制御できます。
この記事では、Cloud NATの設計から実装、運用までを実践的に解説します。
- Cloud NATの仕組みとユースケース
- プライベートサブネットからの外部アクセス設計パターン
- 静的IP割り当てとポートアロケーション設計
- GKEクラスタとの連携設定
- ログ監視とトラブルシューティング
- Terraformによるインフラ定義とベストプラクティス
Cloud NATの基礎知識
NATとは何か
NAT(Network Address Translation)は、プライベートIPアドレスをパブリックIPアドレスに変換する技術です。Cloud NATは、この変換をGoogleのマネージドサービスとして提供します。
Cloud NATの動作フロー:
プライベートVM(10.0.1.5)
↓ パケット送信
Cloud NAT(変換)
↓ 送信元IPをNAT IPに変換
インターネット(203.0.113.10 として外部に出る)
↓ レスポンス
Cloud NAT(逆変換)
↓ 宛先IPを元のプライベートIPに戻す
プライベートVM(10.0.1.5 でレスポンス受信)
※ 外部 → VM への直接アクセスは不可(インバウンドは拒否)
Cloud NATの特徴
| 特徴 | 説明 |
|---|---|
| マネージド | インフラ管理不要、自動スケーリング |
| 高可用性 | リージョン内で自動的に冗長化 |
| アウトバウンド専用 | インバウンド接続は許可しない |
| ソフトウェア定義 | VMやプロキシインスタンスは不要 |
| ログ対応 | Cloud Loggingと統合した詳細ログ |
| 静的IP対応 | 固定の外部IPアドレスを割り当て可能 |
他のアクセスパターンとの比較
| パターン | Cloud NAT | 外部IP割り当て | Cloud VPN | プロキシVM |
|---|---|---|---|---|
| セキュリティ | ◎ | △ | ◎ | ○ |
| 管理コスト | ◎ | ◎ | ○ | △ |
| スケーラビリティ | ◎ | ◎ | ○ | △ |
| 固定IP | ○ | ○ | ○ | ○ |
| インバウンド対応 | × | ○ | ○ | ○ |
| コスト | ○ | ◎ | △ | △ |
Cloud NATの基本セットアップ
Terraformによる構築
# VPCネットワーク
resource "google_compute_network" "main" {
name = "ses-base-vpc"
auto_create_subnetworks = false
}
# プライベートサブネット
resource "google_compute_subnetwork" "private" {
name = "ses-base-private"
ip_cidr_range = "10.0.1.0/24"
region = "asia-northeast1"
network = google_compute_network.main.id
# プライベートGoogle Accessを有効化
private_ip_google_access = true
# GKE用のセカンダリレンジ
secondary_ip_range {
range_name = "gke-pods"
ip_cidr_range = "10.1.0.0/16"
}
secondary_ip_range {
range_name = "gke-services"
ip_cidr_range = "10.2.0.0/20"
}
}
# Cloud Router(Cloud NATに必須)
resource "google_compute_router" "router" {
name = "ses-base-router"
region = "asia-northeast1"
network = google_compute_network.main.id
bgp {
asn = 64514
}
}
# Cloud NAT
resource "google_compute_router_nat" "nat" {
name = "ses-base-nat"
router = google_compute_router.router.name
region = google_compute_router.router.region
# NAT対象の設定
nat_ip_allocate_option = "MANUAL_ONLY"
source_subnetwork_ip_ranges_to_nat = "LIST_OF_SUBNETWORKS"
# 静的NAT IP
nat_ips = [google_compute_address.nat_ip_1.self_link]
# 対象サブネット
subnetwork {
name = google_compute_subnetwork.private.id
source_ip_ranges_to_nat = ["ALL_IP_RANGES"]
}
# ポートアロケーション設定
min_ports_per_vm = 256
max_ports_per_vm = 4096
enable_dynamic_port_allocation = true
# ログ設定
log_config {
enable = true
filter = "ERRORS_ONLY" # 本番は ERRORS_ONLY、デバッグ時は ALL
}
# タイムアウト設定
udp_idle_timeout_sec = 30
icmp_idle_timeout_sec = 30
tcp_established_idle_timeout_sec = 1200
tcp_transitory_idle_timeout_sec = 30
tcp_time_wait_timeout_sec = 120
}
# 静的NAT IPアドレス
resource "google_compute_address" "nat_ip_1" {
name = "ses-base-nat-ip-1"
region = "asia-northeast1"
}
# 必要に応じて追加のNAT IP
resource "google_compute_address" "nat_ip_2" {
name = "ses-base-nat-ip-2"
region = "asia-northeast1"
}
gcloudコマンドでの構築
# 1. VPCとサブネットの作成
gcloud compute networks create ses-base-vpc \
--subnet-mode=custom
gcloud compute networks subnets create ses-base-private \
--network=ses-base-vpc \
--region=asia-northeast1 \
--range=10.0.1.0/24 \
--enable-private-ip-google-access
# 2. 静的IPの予約
gcloud compute addresses create ses-base-nat-ip \
--region=asia-northeast1
# 3. Cloud Routerの作成
gcloud compute routers create ses-base-router \
--network=ses-base-vpc \
--region=asia-northeast1
# 4. Cloud NATの作成
gcloud compute routers nats create ses-base-nat \
--router=ses-base-router \
--region=asia-northeast1 \
--nat-external-ip-pool=ses-base-nat-ip \
--nat-custom-subnet-ip-ranges=ses-base-private \
--min-ports-per-vm=256 \
--max-ports-per-vm=4096 \
--enable-dynamic-port-allocation \
--enable-logging \
--log-filter=ERRORS_ONLY
ポートアロケーション設計
ポート枯渇の防止
Cloud NATでは、各VMに割り当てられるポート数が制限されています。大量の外部接続を行うVMでは、ポート枯渇が発生する可能性があります。
ポートアロケーションの考え方:
1つのNAT IP = 65,535ポート(使用可能: 約64,000)
VMあたりの最小ポート数: 64(デフォルト)
VMあたりの推奨ポート数: 256〜4096
例: NAT IP 1個 + VMあたり256ポート = 最大250 VM対応
NAT IP 2個 + VMあたり1024ポート = 最大125 VM対応
動的ポートアロケーション
# 動的ポートアロケーション(推奨設定)
resource "google_compute_router_nat" "nat_dynamic" {
name = "ses-base-nat-dynamic"
router = google_compute_router.router.name
region = google_compute_router.router.region
nat_ip_allocate_option = "MANUAL_ONLY"
source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
nat_ips = [
google_compute_address.nat_ip_1.self_link,
google_compute_address.nat_ip_2.self_link,
]
# 動的ポートアロケーション(負荷に応じて自動調整)
enable_dynamic_port_allocation = true
min_ports_per_vm = 256 # 最小ポート数
max_ports_per_vm = 8192 # 最大ポート数
# エンドポイント非依存マッピング
# 同じ内部IP:ポートからの接続は同じNAT IP:ポートを使用
enable_endpoint_independent_mapping = false # 大量接続時はfalse推奨
}
GKEクラスタとの連携
プライベートGKEクラスタでのCloud NAT
# プライベートGKEクラスタ
resource "google_container_cluster" "primary" {
name = "ses-base-cluster"
location = "asia-northeast1"
# プライベートクラスタ設定
private_cluster_config {
enable_private_nodes = true
enable_private_endpoint = false
master_ipv4_cidr_block = "172.16.0.0/28"
}
network = google_compute_network.main.id
subnetwork = google_compute_subnetwork.private.id
ip_allocation_policy {
cluster_secondary_range_name = "gke-pods"
services_secondary_range_name = "gke-services"
}
# ノードにパブリックIPを付与しない
node_config {
machine_type = "e2-standard-4"
# パブリックIPなし(Cloud NAT経由で外部アクセス)
network_config {
enable_private_nodes = true
}
}
}
# GKE Pod用のCloud NAT設定
resource "google_compute_router_nat" "gke_nat" {
name = "ses-base-gke-nat"
router = google_compute_router.router.name
region = google_compute_router.router.region
nat_ip_allocate_option = "MANUAL_ONLY"
source_subnetwork_ip_ranges_to_nat = "LIST_OF_SUBNETWORKS"
nat_ips = [
google_compute_address.nat_ip_1.self_link,
google_compute_address.nat_ip_2.self_link,
]
subnetwork {
name = google_compute_subnetwork.private.id
source_ip_ranges_to_nat = [
"ALL_IP_RANGES" # プライマリ + セカンダリ(Pod/Service)レンジ
]
}
# GKEノードは大量のPodを実行するため、ポート数を多めに
min_ports_per_vm = 1024
max_ports_per_vm = 16384
enable_dynamic_port_allocation = true
log_config {
enable = true
filter = "ERRORS_ONLY"
}
}
GKE Podからの外部アクセス確認
# テスト用Pod
apiVersion: v1
kind: Pod
metadata:
name: nat-test
spec:
containers:
- name: curl
image: curlimages/curl:latest
command: ["sleep", "3600"]
---
# 外部IPの確認コマンド
# kubectl exec nat-test -- curl -s https://api.ipify.org
# → Cloud NATの静的IPが表示されるはず
ログ監視とトラブルシューティング
Cloud NATログの分析
# Cloud Loggingでのフィルタクエリ
# 1. NATログの全件表示
gcloud logging read 'resource.type="nat_gateway"' \
--limit=50 \
--format=json
# 2. ポート枯渇エラーの検出
gcloud logging read '
resource.type="nat_gateway"
jsonPayload.allocation_status="DROPPED"
' --limit=20
# 3. 接続タイムアウトの検出
gcloud logging read '
resource.type="nat_gateway"
jsonPayload.connection.nat_ip!=""
jsonPayload.endpoint.timeout="true"
' --limit=20
Cloud Monitoringでのアラート設定
# ポート使用率のアラート
resource "google_monitoring_alert_policy" "nat_port_usage" {
display_name = "Cloud NAT - High Port Usage"
combiner = "OR"
conditions {
display_name = "NAT port usage > 80%"
condition_threshold {
filter = <<-EOT
resource.type = "nat_gateway"
metric.type = "router.googleapis.com/nat/allocated_ports"
EOT
duration = "300s"
comparison = "COMPARISON_GT"
threshold_value = 0.8
aggregations {
alignment_period = "60s"
per_series_aligner = "ALIGN_MEAN"
}
}
}
notification_channels = [google_monitoring_notification_channel.slack.name]
alert_strategy {
auto_close = "1800s"
}
}
# 接続エラーのアラート
resource "google_monitoring_alert_policy" "nat_errors" {
display_name = "Cloud NAT - Connection Errors"
combiner = "OR"
conditions {
display_name = "NAT dropped connections"
condition_threshold {
filter = <<-EOT
resource.type = "nat_gateway"
metric.type = "router.googleapis.com/nat/dropped_sent_packets_count"
EOT
duration = "60s"
comparison = "COMPARISON_GT"
threshold_value = 100
aggregations {
alignment_period = "60s"
per_series_aligner = "ALIGN_RATE"
}
}
}
notification_channels = [google_monitoring_notification_channel.slack.name]
}
トラブルシューティングガイド
よくある問題と対処法:
1. VMから外部に接続できない
├── Cloud NATの対象サブネットに含まれているか確認
├── ファイアウォールルールでアウトバウンドが許可されているか確認
├── VMにパブリックIPが付与されていないか確認(付与されている場合はNATを通らない)
└── Cloud NATのステータスがACTIVEか確認
2. 間欠的に接続が失敗する
├── ポート枯渇をログで確認
├── min_ports_per_vmを増やす
├── NAT IPを追加する
└── enable_dynamic_port_allocationを有効化
3. 特定の外部サービスに接続できない
├── NAT IPがサービス側のホワイトリストに登録されているか確認
├── 静的IPが正しく設定されているか確認
└── DNSの名前解決が正常か確認(Cloud DNSの設定を確認)
4. GKE Podから外部接続が遅い
├── ポートアロケーションの上限を確認
├── エンドポイント非依存マッピングの設定を確認
└── TCP タイムアウト設定を調整

セキュリティ設計のベストプラクティス
ファイアウォールルールとの組み合わせ
# アウトバウンドを特定のポート/プロトコルに制限
resource "google_compute_firewall" "allow_outbound_https" {
name = "allow-outbound-https"
network = google_compute_network.main.id
direction = "EGRESS"
priority = 1000
allow {
protocol = "tcp"
ports = ["443"]
}
destination_ranges = ["0.0.0.0/0"]
target_tags = ["web-server"]
}
# 不要なアウトバウンドをブロック
resource "google_compute_firewall" "deny_outbound_default" {
name = "deny-outbound-default"
network = google_compute_network.main.id
direction = "EGRESS"
priority = 65534
deny {
protocol = "all"
}
destination_ranges = ["0.0.0.0/0"]
}
# 内部通信の許可
resource "google_compute_firewall" "allow_internal" {
name = "allow-internal"
network = google_compute_network.main.id
direction = "INGRESS"
priority = 1000
allow {
protocol = "tcp"
}
allow {
protocol = "udp"
}
allow {
protocol = "icmp"
}
source_ranges = ["10.0.0.0/8"]
}
VPC Service Controlsとの連携
# VPC Service Controlsでデータ流出を防止
resource "google_access_context_manager_service_perimeter" "ses_perimeter" {
parent = "accessPolicies/${var.access_policy_id}"
name = "accessPolicies/${var.access_policy_id}/servicePerimeters/ses_base"
title = "SES BASE Service Perimeter"
status {
resources = [
"projects/${var.project_number}"
]
restricted_services = [
"storage.googleapis.com",
"bigquery.googleapis.com",
]
vpc_accessible_services {
enable_restriction = true
allowed_services = [
"storage.googleapis.com",
"logging.googleapis.com",
"monitoring.googleapis.com",
]
}
}
}
SES現場でのCloud NATスキルの市場価値
クラウドネットワークエンジニアの需要と単価
| スキルレベル | 対応可能範囲 | 月単価目安 |
|---|---|---|
| 基本レベル | VPC・サブネット・ファイアウォール設定 | 60〜75万円 |
| 中級レベル | Cloud NAT・VPN・ロードバランサ設計 | 75〜90万円 |
| 上級レベル | マルチリージョン設計・ハイブリッドクラウド | 90〜110万円 |
| エキスパート | ゼロトラスト設計・ネットワークアーキテクト | 110〜130万円 |
学習ロードマップ
STEP 1: GCPネットワーキングの基礎(1-2週間)
├── VPC・サブネット・ファイアウォール
├── Cloud Router・Cloud NAT
└── gcloudコマンドでの構築
STEP 2: セキュアなネットワーク設計(2-3週間)
├── プライベートGKEクラスタ
├── Cloud NATの最適化
└── ログ監視とアラート設定
STEP 3: Terraform IaC化(3-4週間)
├── ネットワーク全体のTerraform定義
├── モジュール設計
└── CI/CDパイプラインとの統合
STEP 4: エンタープライズネットワーク(継続的)
├── マルチリージョン・マルチVPC設計
├── Shared VPC・VPC Service Controls
└── ハイブリッドクラウド接続
まとめ|Cloud NATでセキュアなネットワークを構築する
Google Cloud NATを活用することで、プライベートインフラから安全に外部通信を行う環境を構築できます。
この記事で紹介した主なポイント:
- Cloud NAT基礎: マネージドNATの仕組みとアウトバウンド専用設計
- Terraform構築: VPC・サブネット・Cloud NAT一式のIaC定義
- ポートアロケーション: 動的割り当てによるポート枯渇の防止
- GKE連携: プライベートクラスタでのPod外部アクセス設定
- 監視・運用: Cloud Logging/Monitoringとの統合とトラブルシューティング
- セキュリティ: ファイアウォール・VPC Service Controlsとの組み合わせ
ネットワークセキュリティ設計は、2026年のSES市場でクラウドインフラエンジニアとしての基盤スキルです。Cloud NATを起点にGCPネットワーキングの専門性を磨いていきましょう。
GCPネットワーク設計・クラウドインフラのスキルを活かせるSES案件をお探しなら、SES BASEで最新案件をチェックしましょう。