A VM without an external IP cannot reach storage.googleapis.com by default. Two features fix that without opening the Internet.
flowchart LR VM["VM app-1<br/>internal IP only"] --> PGA["Subnet with Private Google Access"] PGA --> API["Google APIs<br/>storage, bigquery"] VM --> EP["PSC endpoint 10.10.9.10<br/>bundle all-apis"] EP --> API C["Consumer VPC"] --> PSC["PSC endpoint"] PSC --> SA["Producer service attachment<br/>internal load balancer"] %% step VM: app-1 has no external IP and no Cloud NAT. %% step PGA: With Private Google Access on its subnet, calls to Google APIs leave via the default route but stay on Google’s network. %% step API: Cloud Storage and BigQuery answer the VM without any public Internet path. %% step EP: A Private Service Connect endpoint gives Google APIs an internal IP in your VPC, reachable from on-premises too. %% step PSC: The same PSC mechanism lets a consumer reach a service published by another VPC. %% step SA: The producer exposes its internal load balancer through a service attachment; no peering, overlapping IPs are fine.
Private Google Access (PGA)
- A per-subnet setting:
--enable-private-ip-google-access. - Affects only VMs without external IPs in that subnet.
- Uses the default route to the Internet gateway, but traffic to Google APIs stays inside Google.
- Works for most Google APIs (Cloud Storage, BigQuery, Artifact Registry, Pub/Sub…).
- For on-premises hosts, use the special domains
private.googleapis.com(199.36.153.8/30) orrestricted.googleapis.com(199.36.153.4/30, for VPC Service Controls) through VPN/Interconnect.
Private Service Connect (PSC)
| Use | How |
|---|---|
| Google APIs | Create a global PSC endpoint (internal IP) for the all-apis or vpc-sc bundle; add DNS so *.googleapis.com resolves to it |
| Published services | A producer publishes an internal load balancer through a service attachment; consumers create an endpoint to it |
| Managed services | Cloud SQL, Memorystore, AlloyDB and others support PSC as their private connection |
PSC avoids peering: consumer and producer ranges may overlap, and the consumer only sees one IP.
Private services access (older pattern)
Many managed services (Cloud SQL private IP, Memorystore) can also use private services access: you allocate an IP range and create a VPC peering with Google’s service producer network. It works, but peering is not transitive, so prefer PSC where the service supports it.
Which to choose
| Need | Pick |
|---|---|
| Private VMs call Google APIs | Private Google Access (simplest) |
| Fixed internal IP for Google APIs, on-premises access, VPC-SC | PSC endpoint for Google APIs |
| Offer your service to other teams without peering | PSC service attachment |
| Private VMs call the Internet | Cloud NAT |
gcloud compute networks subnets update snet-app --region=asia-southeast1 --enable-private-ip-google-access
gcloud compute networks subnets describe snet-app --region=asia-southeast1 --format="value(privateIpGoogleAccess)"
Traps: PGA does nothing for VMs that have an external IP (they already reach APIs); PGA is not Internet access; a PSC endpoint for APIs needs DNS records, otherwise clients still use public IPs.