VPC Networking
Google Cloud VPC (Virtual Private Cloud) provides isolated, global networking for your resources. Unlike regional VPCs on other clouds, GCP VPCs are global — subnets are regional, but the network spans all regions. This design simplifies multi-region architectures but requires understanding how firewall rules, routing, and IP addressing work across a single global network.
VPC Architecture
VPC (global)
├── Subnet (us-central1) 10.0.1.0/24 — private Google access
├── Subnet (europe-west1) 10.0.2.0/24 — private Google access
└── Subnet (asia-east1) 10.0.3.0/24 — private Google access
Each subnet can have private Google access to reach Google APIs (Cloud Storage, BigQuery) without external IPs.
GCP VPC vs. AWS VPC
| Feature | GCP VPC | AWS VPC |
|---|---|---|
| Scope | Global (subnets are regional) | Regional |
| Subnet sizing | Fixed CIDR per subnet | Fixed CIDR per subnet |
| Firewall | Stateless at VPC level, applied per-VM | Security groups (stateful) + NACLs |
| Default deny | Implicit deny; explicit allow rules | Security group default varies |
| Load balancing | Global anycast by default | Regional (ALB/NLB) |
Create a VPC and Subnet
gcloud compute networks create learning-vpc \
--subnet-mode=custom \
--bgp-routing-mode=regional
gcloud compute networks subnets create learning-subnet-us \
--network=learning-vpc \
--region=us-central1 \
--range=10.0.1.0/24 \
--enable-private-ip-google-access
gcloud compute networks subnets create learning-subnet-eu \
--network=learning-vpc \
--region=europe-west1 \
--range=10.0.2.0/24 \
--enable-private-ip-google-access
Firewall Rules
GCP firewall rules are stateful and applied at the VM level via network tags or service accounts:
# Allow SSH from specific IP (tag-based)
gcloud compute firewall-rules create allow-ssh-admin \
--network=learning-vpc \
--allow=tcp:22 \
--source-ranges=203.0.113.50/32 \
--target-tags=ssh-access
# Allow HTTP to web servers
gcloud compute firewall-rules create allow-http \
--network=learning-vpc \
--allow=tcp:80,tcp:443 \
--source-ranges=0.0.0.0/0 \
--target-tags=http-server
# Service account-based rule (preferred for GKE)
gcloud compute firewall-rules create allow-app-to-db \
--network=learning-vpc \
--allow=tcp:5432 \
--source-service-accounts=app@learning-gcp-dev.iam.gserviceaccount.com \
--target-tags=database
Hierarchical firewall policies at the organization level provide centralized rule management across all VPCs.
Firewall Rule Priority
| Priority Range | Use |
|---|---|
| 0–999 | Emergency deny rules |
| 1000–1999 | Production allow rules |
| 2000–65534 | General rules |
| 65535 | Implied allow (default VPC only) |
Lower number = higher priority. First matching rule wins.
Cloud NAT
VMs without external IPs need Cloud NAT for outbound internet access:
gcloud compute routers create learning-router \
--network=learning-vpc \
--region=us-central1
gcloud compute routers nats create learning-nat \
--router=learning-router \
--region=us-central1 \
--auto-allocate-nat-external-ips \
--nat-all-subnet-ip-ranges \
--enable-logging
Cloud NAT provides outbound-only internet access — VMs remain unreachable from the internet.
Load Balancing
| Type | Layer | Scope | Use Case |
|---|---|---|---|
| External HTTP(S) | L7 | Global | Web applications, CDN integration |
| Internal HTTP(S) | L7 | Regional | Internal microservices |
| External TCP/UDP (Network) | L4 | Regional/Any | Non-HTTP TCP, gaming |
| Internal TCP/UDP | L4 | Regional | Internal TCP/UDP distribution |
| TCP Proxy | L4 | Global | SSL offload for non-HTTP TCP |
# Health check for backend services
gcloud compute health-checks create http http-health \
--port=80 --request-path=/health
# Backend service with MIG
gcloud compute backend-services create web-backend \
--protocol=HTTP --health-checks=http-health --global
Shared VPC
Centralize network management for multiple projects:
Host Project (networking-team)
└── Shared VPC: production-vpc
├── Service Project: myapp-prod (GKE, Cloud SQL)
├── Service Project: myapp-data (BigQuery, Dataflow)
└── Service Project: myapp-shared (DNS, logging)
gcloud compute shared-vpc enable host-project-id
gcloud compute shared-vpc associated-projects add service-project-id \
--host-project=host-project-id
VPC Flow Logs
Enable for security analysis and troubleshooting:
gcloud compute networks subnets update learning-subnet-us \
--region=us-central1 \
--enable-flow-logs \
--logging-flow-sampling=0.5 \
--logging-metadata=include-all
Export to Cloud Logging, then BigQuery for long-term analysis.
Real-World Scenario: Three-Tier Application
Internet
→ Cloud Armor (WAF)
→ External HTTP(S) LB
→ GKE Ingress (web tier, 10.0.1.0/24)
→ Internal LB (API tier, 10.0.10.0/24)
→ Cloud SQL (private IP, 10.0.20.0/24)
Firewall rules:
- Allow 443 from
0.0.0.0/0to web tier tags only - Allow 8080 from web SA to API tier tags only
- Allow 5432 from API SA to database tags only
- Deny all other traffic (implicit)
Common Mistakes
| Mistake | Impact | Fix |
|---|---|---|
| Default VPC in production | Overly permissive firewall rules | Custom VPC with explicit rules |
| Overlapping CIDR ranges | Peering/VPN failures | Plan IP ranges before deployment |
| External IPs on all VMs | Attack surface, cost | Cloud NAT for outbound only |
| No flow logs | Cannot investigate incidents | Enable on all production subnets |
| Tag-based rules without discipline | Orphaned rules, gaps | Prefer service account-based rules |
Best Practices
- Use shared VPC for centralized network management across projects
- Segment environments with separate subnets or VPCs
- Apply least-privilege firewall rules — default deny, explicit allow
- Use private IPs for databases and internal services
- Enable VPC Flow Logs for traffic analysis and security monitoring
- Use Private Service Connect for accessing Google APIs and SaaS privately
- Plan IP address ranges with room for growth (avoid /28 subnets in production)
- Document network topology in a diagram updated with every change
Troubleshooting
VM cannot reach internet:
# Check if VM has external IP or Cloud NAT is configured
gcloud compute instances describe VM_NAME --zone=ZONE \
--format="get(networkInterfaces[0].accessConfigs)"
gcloud compute routers nats list --router=learning-router --region=us-central1
Firewall rule not applying:
gcloud compute instances describe VM_NAME --zone=ZONE \
--format="get(tags.items,serviceAccounts)"
# Verify tags/SA match the firewall rule target
VPC peering not working: Peering is non-transitive. VM in VPC-A cannot reach VM in VPC-C through VPC-B. Use VPN or Cloud Interconnect for hub-and-spoke.
DNS resolution failures:
gcloud compute instances describe VM_NAME --zone=ZONE \
--format="get(metadata.items[dns-server])"
# Default: 169.254.169.254 (internal metadata DNS)
A well-designed VPC is the foundation for secure, scalable GCP architectures.
Next: Cloud Functions — serverless event-driven compute.