GCP for DevOps — Subnets & Firewall

3 minute read

Subnets & Firewall

Subnets define IP ranges within a region, and firewall rules control traffic flow. Together they form the network security foundation for your GCP infrastructure.

Subnet IP Planning

Production VPC: prod-vpc
│
├── us-central1
│   ├── prod-web:    10.1.1.0/24  (254 hosts)
│   ├── prod-app:    10.1.2.0/24  (254 hosts)
│   ├── prod-db:     10.1.3.0/24  (254 hosts)
│   └── gke-nodes:   10.1.10.0/24 (254 hosts)
│       ├── pods:    10.100.0.0/16 (65,534 pods)
│       └── services: 10.200.0.0/20 (4,094 services)
│
├── us-east1
│   ├── dr-web:     10.2.1.0/24
│   └── dr-app:     10.2.2.0/24
│
└── europe-west1
    └── eu-app:     10.3.1.0/24

Expanding Subnets

Unlike many cloud providers, GCP subnets can be expanded (but not shrunk).

# Expand a subnet range
$ gcloud compute networks subnets expand-ip-range prod-web \
    --region=us-central1 \
    --prefix-length=22

Updated [prod-web].
# Range changed from 10.1.1.0/24 (254 IPs) to 10.1.0.0/22 (1,022 IPs)

Firewall Rule Architecture

┌─────────────────────────────────────────────────────┐
│                  VPC: prod-vpc                       │
│                                                     │
│  Firewall Rules (evaluated by priority):            │
│                                                     │
│  ┌────────────────────────────────────────────┐     │
│  │ P:100  DENY  all → 198.51.100.0/24        │     │
│  │ P:1000 ALLOW tcp:80,443 → tag:web         │     │
│  │ P:1000 ALLOW tcp:22 from 35.235.240.0/20  │     │
│  │ P:1000 ALLOW tcp:8080 tag:app → tag:app   │     │
│  │ P:1100 ALLOW tcp:5432 SA:app → SA:db      │     │
│  │ P:65534 ALLOW all from 10.0.0.0/8 (int)   │     │
│  │ P:65535 DENY  all ingress (implied)        │     │
│  │ P:65535 ALLOW all egress (implied)         │     │
│  └────────────────────────────────────────────┘     │
│                                                     │
│  Traffic matching: First match wins (lowest P#)     │
└─────────────────────────────────────────────────────┘

Three-Tier Firewall Example

# Web tier: allow HTTP/HTTPS from internet
$ gcloud compute firewall-rules create prod-allow-web \
    --network=prod-vpc \
    --direction=INGRESS \
    --action=ALLOW \
    --rules=tcp:80,tcp:443 \
    --source-ranges=0.0.0.0/0 \
    --target-tags=web-tier \
    --priority=1000

# App tier: allow from web tier only
$ gcloud compute firewall-rules create prod-allow-web-to-app \
    --network=prod-vpc \
    --direction=INGRESS \
    --action=ALLOW \
    --rules=tcp:8080 \
    --source-tags=web-tier \
    --target-tags=app-tier \
    --priority=1000

# DB tier: allow from app tier only (service account based)
$ gcloud compute firewall-rules create prod-allow-app-to-db \
    --network=prod-vpc \
    --direction=INGRESS \
    --action=ALLOW \
    --rules=tcp:5432 \
    --source-service-accounts=app-sa@my-project.iam.gserviceaccount.com \
    --target-service-accounts=db-sa@my-project.iam.gserviceaccount.com \
    --priority=1000

# SSH via IAP only
$ gcloud compute firewall-rules create prod-allow-iap \
    --network=prod-vpc \
    --direction=INGRESS \
    --action=ALLOW \
    --rules=tcp:22 \
    --source-ranges=35.235.240.0/20 \
    --priority=1000

# Health checks from Google's health check ranges
$ gcloud compute firewall-rules create prod-allow-health-check \
    --network=prod-vpc \
    --direction=INGRESS \
    --action=ALLOW \
    --rules=tcp:80,tcp:8080 \
    --source-ranges=130.211.0.0/22,35.191.0.0/16 \
    --target-tags=health-check \
    --priority=1000

# Deny all other ingress (explicit, for clarity)
$ gcloud compute firewall-rules create prod-deny-all \
    --network=prod-vpc \
    --direction=INGRESS \
    --action=DENY \
    --rules=all \
    --source-ranges=0.0.0.0/0 \
    --priority=65000

Hierarchical Firewall Policies

Organization-wide firewall policies that apply across all VPCs.

# Create an organization-level firewall policy
$ gcloud compute firewall-policies create \
    --organization=123456789 \
    --short-name=org-security-policy \
    --description="Organization security policy"

# Add a rule to block known malicious IPs
$ gcloud compute firewall-policies rules create 100 \
    --firewall-policy=org-security-policy \
    --organization=123456789 \
    --direction=INGRESS \
    --action=deny \
    --src-ip-ranges=198.51.100.0/24 \
    --layer4-configs=all

# Associate with the organization
$ gcloud compute firewall-policies associations create \
    --firewall-policy=org-security-policy \
    --organization=123456789

Tags vs Service Accounts for Targeting

Method Security Ease of Use Recommendation
Network tags ⚠️ Any user with setTags can add Easy Dev/test only
Service accounts ✅ Tied to IAM identity More setup Production

Firewall Insights

# View firewall insights (overly permissive rules)
$ gcloud recommender insights list \
    --project=my-project \
    --insight-type=google.compute.firewall.Insight \
    --location=global \
    --format="table(content.overview.firewallRuleName,content.overview.insight)"

Common Mistakes

Mistake Why It’s Wrong Fix
Using 0.0.0.0/0 for SSH Exposes to the internet Use IAP range 35.235.240.0/20
Not planning IP ranges Overlapping ranges block peering Plan before creating subnets
Forgetting health check ranges Load balancer health checks fail Allow 130.211.0.0/22,35.191.0.0/16
One large subnet for everything No network segmentation Use separate subnets per tier
Not using firewall logging Can’t debug connectivity Enable logging on key rules

Quick Reference

Command Description
gcloud compute networks subnets create NAME Create a subnet
gcloud compute networks subnets expand-ip-range NAME Expand subnet
gcloud compute firewall-rules create NAME Create firewall rule
--source-ranges=CIDR Source IP range (ingress)
--source-tags=TAG Source tag (ingress)
--target-tags=TAG Target VMs by tag
--source-service-accounts=SA Source by SA
--target-service-accounts=SA Target by SA

Next → Cloud NAT

Updated: