Cloud NAT is the primary way to give private GCP instances internet access without assigning them public IP addresses.

Let’s see it in action. Imagine a simple network:

VPC Network: my-vpc
  Subnet: private-subnet (10.0.1.0/24)
    VM Instance: vm-private (IP: 10.0.1.10)

Without Cloud NAT, vm-private can’t initiate connections to the internet. If you try to curl google.com from vm-private, it will hang.

To fix this, we’ll set up Cloud NAT for the private-subnet.

First, you need a Cloud Router. This is a global resource, but it’s associated with a specific region for NAT.

gcloud compute routers create my-router \
    --network my-vpc \
    --region us-central1

This command creates a router named my-router within the us-central1 region, linked to the my-vpc network. Cloud NAT configuration is attached to this router.

Next, configure the NAT gateway itself.

gcloud compute routers nats create my-nat-gateway \
    --router my-router \
    --region us-central1 \
    --auto-allocate-nat-external-ips \
    --nat-custom-subnet-ip-ranges private-subnet

Here’s what’s happening:

  • my-nat-gateway: The name of our NAT gateway.
  • --router my-router: Associates this NAT gateway with the previously created Cloud Router.
  • --region us-central1: Specifies the region for the NAT gateway. This must match the router’s region.
  • --auto-allocate-nat-external-ips: Cloud NAT needs external IP addresses to translate private IPs to. This option tells GCP to automatically assign and manage them. You could also specify static IPs with --nat-external-ip-pool.
  • --nat-custom-subnet-ip-ranges private-subnet: This is the crucial part. It tells Cloud NAT to apply to traffic originating from instances in the private-subnet. You can also specify specific IP ranges within a subnet using --nat-custom-subnet-ip-ranges=subnet-name:range-name.

Once this is applied, traffic from vm-private (10.0.1.10) destined for the internet will be:

  1. Intercepted by the Cloud NAT gateway.
  2. Its source IP address (10.0.1.10) will be translated to one of the automatically allocated external IP addresses.
  3. The translated packet will be sent to the internet.
  4. Responses from the internet, arriving at the external IP, will be translated back to the private IP (10.0.1.10) and routed to vm-private.

You can verify the NAT gateway status:

gcloud compute routers nats describe my-nat-gateway \
    --router my-router \
    --region us-central1

Look for state: RUNNING and check the natIpAllocateOption and natRanges to confirm your configuration.

The default configuration for Cloud NAT is to use UDP and TCP ports dynamically. If you have specific port requirements, you can configure the minimum and maximum ports per VM instance or per IP address. For example, to set a minimum of 1024 ports per VM:

gcloud compute routers nats update my-nat-gateway \
    --router my-router \
    --region us-central1 \
    --min-ports-per-vm 1024

This command adjusts the NAT gateway to ensure each VM has at least 1024 ephemeral ports available for its outbound connections. This can be important for applications that open many simultaneous connections.

A common pitfall is forgetting to associate the NAT gateway with the correct subnet or IP range. If you only have one subnet in a region and don’t specify --nat-custom-subnet-ip-ranges, it might not pick it up automatically. Always explicitly declare the ranges.

Another important aspect is the choice between automatic and manual IP allocation. Auto-allocation is convenient for most use cases, but if you need predictable external IPs for firewall rules on the internet side, you’ll use --nat-external-ip-pool with specific static IP addresses reserved in GCP.

The most surprising thing is that Cloud NAT operates at the router level, not directly on the VM’s network interface. The Cloud Router acts as the central point for NAT in a region, managing the translations for all associated subnets. This means a single Cloud NAT gateway attached to a router can serve multiple subnets within that region, simplifying management.

The next thing you’ll likely encounter is managing the number of ephemeral ports available for NAT. If your instances are making a very large number of concurrent outbound connections, you might run out of ports, leading to connection failures. Cloud NAT has a default limit per VM, but it can be increased.

Want structured learning?

Take the full Gcp course →