GCP for DevOps — Cloud NAT
Cloud NAT
Cloud NAT (Network Address Translation) lets VMs without external IP addresses access the internet for outbound connections — such as downloading packages, pulling container images, or calling external APIs — without exposing them to inbound internet traffic.
How Cloud NAT Works
┌──────────────────────────────────────────────────┐
│ VPC │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ VM-1 │ │ VM-2 │ │ VM-3 │ │
│ │ (no ext │ │ (no ext │ │ (no ext │ │
│ │ IP) │ │ IP) │ │ IP) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ │ │
│ ┌───────▼───────┐ │
│ │ Cloud Router │ │
│ │ + Cloud NAT │ │
│ └───────┬───────┘ │
│ │ │
└──────────────────────┼───────────────────────────┘
│
┌─────▼─────┐
│ Internet │
│ (outbound │
│ only) │
└───────────┘
Setting Up Cloud NAT
Step 1: Create a Cloud Router
$ gcloud compute routers create nat-router \
--network=prod-vpc \
--region=us-central1
Creating router [nat-router]...done.
Step 2: Create Cloud NAT Configuration
# NAT with auto-allocated IPs (simplest)
$ gcloud compute routers nats create prod-nat \
--router=nat-router \
--region=us-central1 \
--nat-all-subnet-ip-ranges \
--auto-allocate-nat-external-ips
Creating NAT [prod-nat] in router [nat-router]...done.
# NAT with manual (static) IPs
$ gcloud compute addresses create nat-ip-1 nat-ip-2 \
--region=us-central1
$ gcloud compute routers nats create prod-nat \
--router=nat-router \
--region=us-central1 \
--nat-all-subnet-ip-ranges \
--nat-external-ip-pool=nat-ip-1,nat-ip-2
# NAT for specific subnets only
$ gcloud compute routers nats create prod-nat \
--router=nat-router \
--region=us-central1 \
--nat-custom-subnet-ip-ranges=prod-app,prod-web \
--auto-allocate-nat-external-ips
NAT Configuration Options
# View NAT configuration
$ gcloud compute routers nats describe prod-nat \
--router=nat-router \
--region=us-central1
enableEndpointIndependentMapping: false
icmpIdleTimeoutSec: 30
minPortsPerVm: 64
name: prod-nat
natIpAllocateOption: AUTO_ONLY
sourceSubnetworkIpRangesToNat: ALL_SUBNETWORKS_ALL_IP_RANGES
tcpEstablishedIdleTimeoutSec: 1200
tcpTransitoryIdleTimeoutSec: 30
udpIdleTimeoutSec: 30
# Update NAT settings — increase ports per VM for high-traffic workloads
$ gcloud compute routers nats update prod-nat \
--router=nat-router \
--region=us-central1 \
--min-ports-per-vm=256 \
--max-ports-per-vm=4096 \
--enable-dynamic-port-allocation
# Enable NAT logging
$ gcloud compute routers nats update prod-nat \
--router=nat-router \
--region=us-central1 \
--enable-logging \
--log-filter=ERRORS_ONLY
NAT Logging
# View NAT logs
$ gcloud logging read 'resource.type="nat_gateway"' \
--project=my-project --limit=10 \
--format="table(timestamp,jsonPayload.connection.src_ip,jsonPayload.connection.dest_ip,jsonPayload.allocation_status)"
Static NAT IP for Allowlisting
When external services need to allowlist your outbound IPs:
# Reserve static IPs
$ gcloud compute addresses create nat-egress-ip \
--region=us-central1
$ gcloud compute addresses describe nat-egress-ip --region=us-central1 \
--format="get(address)"
34.72.100.50
# Use the static IP in NAT
$ gcloud compute routers nats update prod-nat \
--router=nat-router \
--region=us-central1 \
--nat-external-ip-pool=nat-egress-ip
# Share this IP with the external service for allowlisting
Cloud NAT vs External IPs
| Feature | Cloud NAT | External IP on VM |
|---|---|---|
| Outbound internet | ✅ Yes | ✅ Yes |
| Inbound from internet | ❌ No | ✅ Yes (if firewall allows) |
| Security | ✅ Better — no inbound exposure | ⚠️ VM exposed to internet |
| Cost | NAT gateway charges | Only IP cost |
| Static IP for allowlisting | ✅ NAT IP pool | ✅ Reserved static IP |
| Managed | ✅ Fully managed | You manage firewall |
Common Mistakes
| Mistake | Why It’s Wrong | Fix |
|---|---|---|
| Not creating Cloud NAT | Private VMs can’t reach the internet | Always create NAT for private subnets |
Default minPortsPerVm=64 |
Not enough for high-traffic VMs | Increase to 256+ for production |
| Not enabling logging | Can’t debug connectivity | Enable with ERRORS_ONLY filter |
| Auto IPs for allowlisting | IPs can change | Use manual static IPs |
| One NAT for all subnets | No isolation | Create separate NATs per environment |
Quick Reference
| Command | Description |
|---|---|
gcloud compute routers create NAME --network=VPC --region=R |
Create Cloud Router |
gcloud compute routers nats create NAME --router=R --region=R |
Create Cloud NAT |
--nat-all-subnet-ip-ranges |
NAT all subnets |
--nat-custom-subnet-ip-ranges=S1,S2 |
NAT specific subnets |
--auto-allocate-nat-external-ips |
Auto-assign NAT IPs |
--nat-external-ip-pool=IP1,IP2 |
Use static NAT IPs |
gcloud compute routers nats describe NAME |
View NAT config |
Next → Cloud Load Balancing