How private DNS zones and forwarding rules work together with PSC endpoints in GCP. This is a companion to GCP Private Service Connect & VPC Networking.

DNS Zone

A DNS Zone is a container for DNS records. It defines a domain namespace (like psc.internal) and holds all the records for that domain.

Types of DNS Zones

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           DNS ZONE TYPES                                β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚      PUBLIC ZONE            β”‚    β”‚      PRIVATE ZONE           β”‚    β”‚
β”‚  β”‚                             β”‚    β”‚                             β”‚    β”‚
β”‚  β”‚  β€’ Visible to the internet  β”‚    β”‚  β€’ Only visible to          β”‚    β”‚
β”‚  β”‚  β€’ Anyone can resolve       β”‚    β”‚    specific VPCs            β”‚    β”‚
β”‚  β”‚                             β”‚    β”‚  β€’ Internal use only        β”‚    β”‚
β”‚  β”‚  Example:                   β”‚    β”‚                             β”‚    β”‚
β”‚  β”‚  citadelapps.com            β”‚    β”‚  Example:                   β”‚    β”‚
β”‚  β”‚  m.com                β”‚    β”‚  psc.internal               β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Private DNS Zone (Terraform)

resource "google_dns_managed_zone" "psc_internal" {
  name        = "psc-internal"
  dns_name    = "psc.internal."        # The domain namespace
  visibility  = "private"              # Only visible internally
 
  private_visibility_config {
    networks {
      network_url = data.google_compute_network.shared_vpc_network_default.id
    }
  }
}
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    DNS ZONE: psc.internal                               β”‚
β”‚                                                                         β”‚
β”‚   Owner: k-github-actions-dev                                      β”‚
β”‚   Visibility: Private (dev shared VPC only)                             β”‚
β”‚                                                                         β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚  RECORDS in this zone:                                          β”‚   β”‚
β”‚   β”‚                                                                 β”‚   β”‚
β”‚   β”‚  NAME                          TYPE    VALUE                    β”‚   β”‚
β”‚   β”‚  ─────────────────────────────────────────────────────────────  β”‚   β”‚
β”‚   β”‚  octopus.lab.psc.internal      A       10.36.200.x              β”‚   β”‚
β”‚   β”‚  octopus.prod.psc.internal     A       10.36.200.y              β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                         β”‚
β”‚   WHO CAN RESOLVE THESE NAMES?                                          β”‚
β”‚   βœ“ Any VM in k-shared-vpc-host-dev network                       β”‚
β”‚   βœ— Public internet (can't see this zone)                              β”‚
β”‚   βœ— Other VPCs (unless added to visibility config)                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

DNS Record

A DNS Record maps a hostname to an IP address (or other values).

resource "google_dns_record_set" "octopus_lab_psc_internal_A" {
  managed_zone = google_dns_managed_zone.psc_internal.name
 
  name    = "octopus.lab.${google_dns_managed_zone.psc_internal.dns_name}"
  # Result: octopus.lab.psc.internal.
 
  type    = "A"           # A record = maps to IPv4 address
  ttl     = 300           # Cache for 300 seconds
 
  rrdatas = [google_compute_address.psc_octopus_server_lab.address]
  # The IP of our PSC endpoint
}
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         DNS RESOLUTION                                  β”‚
β”‚                                                                         β”‚
β”‚   ArkCI Runner asks: "What is octopus.lab.psc.internal?"               β”‚
β”‚                                                                         β”‚
β”‚         β”‚                                                               β”‚
β”‚         β–Ό                                                               β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                          β”‚
β”‚   β”‚  DNS Zone: psc.internal                 β”‚                          β”‚
β”‚   β”‚                                         β”‚                          β”‚
β”‚   β”‚  Looking up: octopus.lab.psc.internal   β”‚                          β”‚
β”‚   β”‚  Found: A record β†’ 10.36.200.x          β”‚                          β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚         β”‚                                                               β”‚
β”‚         β–Ό                                                               β”‚
β”‚   Answer: 10.36.200.x                                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Forwarding Rule (PSC Endpoint)

A Forwarding Rule in the context of PSC is NOT about DNS. It’s about network traffic routing.

It tells Google Cloud: β€œWhen traffic arrives at this IP, forward it to this destination.”

For Load Balancers (normal use)

Forwarding Rule: "Send traffic on IP 10.0.0.1:80 to my backend service"

For PSC (our use)

Forwarding Rule: "Send traffic on IP 10.36.200.x to the PSC Service Attachment"
resource "google_compute_forwarding_rule" "psc_octopus_server_lab" {
  name    = "psc-octopus-server-lab"
  region  = "asia-northeast1"
 
  # Empty = this is a PSC endpoint, not a load balancer
  load_balancing_scheme = ""
 
  # The IP address that will receive traffic
  ip_address = google_compute_address.psc_octopus_server_lab.id
 
  # Where to send the traffic (the PSC service attachment)
  target = "projects/k-octopus-lab/regions/asia-northeast1/serviceAttachments/octopus-server-psc"
 
  # Which subnet this endpoint lives in
  subnetwork = google_compute_subnetwork.k_github_actions_dev_tokyo.self_link
}
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    FORWARDING RULE (PSC Endpoint)                       β”‚
β”‚                                                                         β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚                                                                 β”‚   β”‚
β”‚   β”‚  NAME: psc-octopus-server-lab                                   β”‚   β”‚
β”‚   β”‚                                                                 β”‚   β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚   β”‚
β”‚   β”‚  β”‚  IP ADDRESS  β”‚         β”‚  TARGET                          β”‚ β”‚   β”‚
β”‚   β”‚  β”‚              β”‚  ────►  β”‚                                  β”‚ β”‚   β”‚
β”‚   β”‚  β”‚ 10.36.200.x  β”‚  routes β”‚  Service Attachment:             β”‚ β”‚   β”‚
β”‚   β”‚  β”‚              β”‚   to    β”‚  octopus-server-psc              β”‚ β”‚   β”‚
β”‚   β”‚  β”‚              β”‚         β”‚  (in k-octopus-lab)         β”‚ β”‚   β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚   β”‚
β”‚   β”‚        β–²                                                       β”‚   β”‚
β”‚   β”‚        β”‚                                                       β”‚   β”‚
β”‚   β”‚   Traffic to                                                   β”‚   β”‚
β”‚   β”‚   this IP gets                                                 β”‚   β”‚
β”‚   β”‚   forwarded                                                    β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

How They Work Together

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    COMPLETE FLOW                                        β”‚
β”‚                                                                         β”‚
β”‚   STEP 1: Application wants to connect                                  β”‚
β”‚   ─────────────────────────────────────                                 β”‚
β”‚   curl https://octopus.lab.psc.internal/api                            β”‚
β”‚                                                                         β”‚
β”‚                           β”‚                                             β”‚
β”‚                           β–Ό                                             β”‚
β”‚                                                                         β”‚
β”‚   STEP 2: DNS Resolution                                                β”‚
β”‚   ──────────────────────────                                            β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                              β”‚
β”‚   β”‚  DNS ZONE: psc.internal             β”‚                              β”‚
β”‚   β”‚                                     β”‚                              β”‚
β”‚   β”‚  Q: octopus.lab.psc.internal = ?    β”‚                              β”‚
β”‚   β”‚  A: 10.36.200.x                     β”‚                              β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                              β”‚
β”‚                                                                         β”‚
β”‚                           β”‚                                             β”‚
β”‚                           β–Ό                                             β”‚
β”‚                                                                         β”‚
β”‚   STEP 3: Network Connection                                            β”‚
β”‚   ──────────────────────────                                            β”‚
β”‚   App connects to 10.36.200.x                                          β”‚
β”‚                                                                         β”‚
β”‚                           β”‚                                             β”‚
β”‚                           β–Ό                                             β”‚
β”‚                                                                         β”‚
β”‚   STEP 4: Forwarding Rule Routes Traffic                                β”‚
β”‚   ─────────────────────────────────────                                 β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                              β”‚
β”‚   β”‚  FORWARDING RULE                    β”‚                              β”‚
β”‚   β”‚                                     β”‚                              β”‚
β”‚   β”‚  IP 10.36.200.x β†’ Service           β”‚                              β”‚
β”‚   β”‚                    Attachment       β”‚                              β”‚
β”‚   β”‚                    (octopus-lab)    β”‚                              β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                              β”‚
β”‚                                                                         β”‚
β”‚                           β”‚                                             β”‚
β”‚                           β–Ό                                             β”‚
β”‚                                                                         β”‚
β”‚   STEP 5: PSC Tunnel to Provider                                        β”‚
β”‚   ──────────────────────────────                                        β”‚
β”‚   Traffic arrives at Octopus Lab server                                β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Summary

ComponentWhat It IsWhat It Does
DNS ZoneContainer for DNS recordsDefines psc.internal namespace
DNS RecordHostname β†’ IP mappingoctopus.lab.psc.internal β†’ 10.36.200.x
Compute AddressReserved internal IPAllocates 10.36.200.x for PSC endpoint
Forwarding RuleTraffic routing ruleRoutes 10.36.200.x β†’ Octopus service attachment
Service AttachmentPSC publisherExposes Octopus for PSC consumers