Private Services Access (PSA)¶
This guide explains the design and rationale behind Private Services Access (PSA) within our Google Cloud environment.
Tip
Looking for implementation steps? See our separate how-to guide to enable private IP for Cloud SQL.
What is Private Services Access?¶
Private Services Access is a networking connection between your VPC network and a network owned by Google (the "Service Producer" network).
By default, Google-managed services like Cloud SQL, Redis (Memorystore), and Filestore are hosted in isolated VPCs. Without PSA, you would have to connect to these services via public IP addresses. PSA creates a VPC Peering bridge, allowing your resources (such as Cloud Run via a VPC connector or GCE instances) to reach these services using internal, private IP addresses.
Benefits¶
- Security: Traffic remains entirely within the Google Cloud backbone and never touches the public internet.
- Performance: Lower latency and reduced network egress costs compared to public endpoints.
- Simplicity: Services appear as if they are sitting on your own local network, making firewall management more intuitive.
Design aims in the Product Factory¶
When we integrated PSA into the gcp-product-factory, we settled on the following design aims:
- Enable by default: Most new products require a database or cache; having the plumbing ready reduces setup friction for new teams.
- Allow existing products to opt-in: Teams with existing products can choose to enable PSA when they are ready, without forcing changes on live systems. When switching to private IP on Cloud SQL, there is a downtime window while connections are migrated.
- Support legacy infrastructure: Provide a toggle (
enable_private_services_access) for older projects that may already have manual peering or overlapping IP ranges that conflict with factory defaults.
Resources created by the Factory¶
When the enable_private_services_access flag is set to true (the default), the Product Factory
automatically provisions two primary resources:
-
Global Internal IP Range (
google_compute_global_address): A named IP block (typically a/16range) reserved specifically for Google services. This range is not assigned to a subnet you can use for VMs; it is a "reservation" that Google carves up as you create database instances. -
Service Networking Connection (
google_service_networking_connection): The actual peering configuration. This creates the "handshake" between your project's VPC and theservicenetworking.googleapis.comservice producer.
Differences between PSA and standard peering¶
While PSA uses VPC Peering under the hood, there are key differences in how we manage it compared to standard project-to-project peering:
| Feature | Standard VPC Peering | Private Services Access (PSA) |
|---|---|---|
| Visibility | You see both sides of the peering in the console. | You only see your side; the producer side is hidden. |
| IP Management | You manage IPs on both ends of the link. | You reserve a range; Google manages the sub-allocation. |
| Usage | Connecting two of our VPCs together. | Connecting our VPC to Google's managed services. |
How to use PSA in your products¶
The Product Factory creates the "bridge," but individual services must be explicitly configured to use it.
Cloud SQL¶
When defining a Cloud SQL instance in Terraform, you must configure the ip_configuration to use
the VPC network provided by the factory metadata. This ensures the database is injected into the
peering bridge.
# Example snippet for a Cloud SQL resource
resource "google_sql_database_instance" "main" {
settings {
ip_configuration {
ipv4_enabled = false # Disable public IP
private_network = "default" # Use the PSA bridge
authorized_networks = []
ssl_mode = "ENCRYPTED_ONLY"
enable_private_path_for_google_cloud_services = true
}
}
}
Serverless VPC Access¶
To allow a Cloud Run service to reach a private Cloud SQL instance, you must also use a VPC Access Connector. The connector sits in your VPC and routes traffic across the PSA bridge to the database.
# Example snippet for a VPC Access Connector
module "webapp" {
source = "gitlab.developers.cam.ac.uk/uis/gcp-cloud-run-app/devops"
version = "10.6.3"
vpc_access = {
egress = "PRIVATE_RANGES_ONLY"
network_interfaces = {
network = "default"
subnetwork = "default"
}
}
}