Google’s Private Google Access allows your GCP resources without public IPs to reach Google APIs and services.

Imagine you have a Compute Engine VM in a private subnet, no external IP address. You need it to talk to Cloud Storage to fetch some data. How does that happen?

{
  "kind": "compute#instance",
  "name": "my-private-vm",
  "networkInterfaces": [
    {
      "network": "projects/my-project/global/networks/my-vpc",
      "subnetwork": "projects/my-project/regions/us-central1/subnetworks/my-private-subnet",
      "accessConfigs": [] // No public IP here
    }
  ],
  "serviceAccounts": [
    {
      "email": "123456789012-compute@developer.gserviceaccount.com",
      "scopes": [
        "https://www.googleapis.com/auth/cloud-platform"
      ]
    }
  ]
}

This VM, my-private-vm, lives in my-private-subnet within my-vpc. It has no accessConfigs, meaning no public IP. Its service account has broad access to cloud-platform. When it tries to access storage.googleapis.com, it needs a route.

Here’s how it works:

  1. DNS Resolution: The VM tries to resolve storage.googleapis.com. If you’re using Google’s default DNS, it resolves to public IP addresses.
  2. Routing: Normally, traffic destined for public IPs would go out to the internet. But with Private Google Access, GCP intercepts this.
  3. Internal Routing: GCP rewrites the destination IP. Instead of going to the public internet, it directs the traffic to Google’s internal network infrastructure.
  4. Authentication: Your VM’s service account credentials are included in the request, allowing Google’s services to authenticate and authorize the access.

The magic happens at the subnet level. You enable Private Google Access on the subnet where your private resources reside.

gcloud compute networks subnets update my-private-subnet \
  --region=us-central1 \
  --enable-private-ip-google-access

This configuration tells GCP that any traffic originating from instances in my-private-subnet that is destined for *.googleapis.com (or other specific Google API domains) should be routed internally, not externally.

Why is this useful?

  • Security: Your instances remain entirely within your private VPC, never exposed to the public internet. This significantly reduces your attack surface.
  • Cost: You avoid the cost of assigning public IP addresses to every instance that needs to access Google APIs.
  • Performance: Traffic stays within Google’s network, often resulting in lower latency compared to going over the public internet.

How to verify it’s working:

From your private VM, try to curl a Google API endpoint. For example, to list buckets in Cloud Storage:

curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  https://storage.googleapis.com/storage/v1/b

If Private Google Access is enabled and configured correctly, this command will return a JSON list of your Cloud Storage buckets. If it fails with a timeout or "network unreachable" error, Private Google Access is likely not configured or the DNS resolution is pointing to public IPs.

The "Private Google Access" setting on a subnet is a boolean flag. When true, the subnet’s egress traffic to *.googleapis.com is rerouted internally.

When you enable Private Google Access for a subnet, you are essentially telling GCP: "For any IP address in the 199.36.153.4/30 range (which is 199.36.153.4, 199.36.153.5, 199.36.153.6, 199.36.153.7), route this traffic through Google’s internal network instead of the public internet." These IPs are reserved for Private Google Access. Any request to *.googleapis.com will resolve to these internal IPs when viewed from a private subnet with the feature enabled.

You can also use a specific IP address for Private Google Access: 199.36.153.8/30. This range (199.36.153.8 to 199.36.153.11) is for restricted.googleapis.com. Traffic sent to restricted.googleapis.com resolves to these IPs and is routed internally. This is more secure as it only allows access to services explicitly listed in your DNS configuration for restricted.googleapis.com.

The most common mistake is forgetting to enable it on the correct subnet. If your VM is in subnet-A and you enable Private Google Access on subnet-B, traffic from subnet-A will still try to go to the public internet.

A common pitfall is relying on custom DNS servers that don’t resolve *.googleapis.com to the correct internal IPs. If your VM uses a custom DNS server, ensure it correctly resolves *.googleapis.com to 199.36.153.4 (or the appropriate range for restricted.googleapis.com). If you’re using the default Google Cloud DNS, this is handled automatically when Private Google Access is enabled.

If you’re using Cloud NAT for your private instances, Private Google Access will not be used. Cloud NAT is for routing traffic to the public internet. Private Google Access is an alternative for accessing Google APIs without public IPs or Cloud NAT.

The next challenge you’ll face is controlling which Google APIs your private instances can access.

Want structured learning?

Take the full Gcp course →