Skip to content

VPC & Networking

One custom VPC, one regional subnet, two secondary ranges. That's the entire network. Provisioned by infrastructure/gcp/vpc.tf.

Resources

Resource Value
Network gke-tomoda-vpc (custom mode, auto_create_subnetworks = false)
Subnet gke-tomoda-subnet in asia-east1
Primary CIDR (nodes) 10.0.0.0/24
Secondary range pods 10.1.0.0/16
Secondary range services 10.2.0.0/20

The GKE cluster references the two secondary ranges by name (pods, services) via its ip_allocation_policy block — see GKE.

flowchart LR
    subgraph VPC["gke-tomoda-vpc (custom mode)"]
        subgraph Subnet["gke-tomoda-subnet · asia-east1"]
            P[Primary 10.0.0.0/24<br/>node IPs]
            S1[Secondary 'pods'<br/>10.1.0.0/16]
            S2[Secondary 'services'<br/>10.2.0.0/20]
        end
    end

    Subnet -->|ip_allocation_policy| GKE[gke-tomoda cluster]

Address space sizing

  • 256 node IPs from the /24 primary range. We have 1 active node and headroom for ~250 more before the subnet itself becomes a constraint. We won't approach that with the current e2-standard-2 pool sizing.
  • 65 536 pod IPs from the /16 secondary range. GKE hands these out in /24 slices per node by default, so this caps the cluster at roughly 256 nodes worth of pods — the real bottleneck before the subnet itself.
  • 4 096 service IPs from the /20 secondary range. More than enough; we run a few dozen Services in total.

Firewall rules

vpc.tf declares no explicit google_compute_firewall resources. The VPC therefore inherits only the implicit rules that GKE itself installs when the cluster is created:

  • Allow intra-cluster traffic between nodes (master-to-node, node-to-node, node-to-pod, pod-to-pod).
  • Allow inbound from the control plane.
  • Deny everything else by default.

If you need to expose anything externally, the right pattern is never to add a firewall rule directly to this VPC — it is to route through Traefik on the cluster, which terminates TLS and forwards into the appropriate Service. The cluster's external IPs are managed entirely by GKE's LoadBalancer integration, not by anything in vpc.tf.

No default-allow-* rules

Because the VPC was created in custom mode (auto_create_subnetworks = false), it does not ship with the default-allow-internal, default-allow-ssh, default-allow-icmp rules that auto-mode VPCs get. If you ever need to SSH into a node, you'll have to add a firewall rule explicitly — and you almost certainly shouldn't.

Cloud NAT

Not configured. There is no google_compute_router or google_compute_router_nat resource anywhere in infrastructure/gcp/.

In practice this means:

  • Nodes get external IPs by default (the standard GKE behaviour for non-private clusters), and pods can reach the internet via SNAT through their node's external IP.
  • If we ever switch to a private cluster, we will need to add Cloud NAT before any pod can reach external dependencies (npm registry, GCR, Docker Hub, Slack webhooks…).

The current setup is the simplest possible thing that works for a single-zone, non-private cluster. It is also the thing that limits us most if we want network-level isolation later.

Cross-VPC connectivity

There is none. We do not peer with any other VPCs, we do not use Shared VPC, and we do not have a VPN tunnel. Anything that needs to talk to GCP from outside the cluster (developers' laptops, GitHub Actions, etc.) does so over the public internet and authenticates with IAM.