Skip to main content

Network Component

The Network component creates the VPC foundation for all other infrastructure, including subnets, firewall rules, Cloud Router, and NAT gateway.

Architecture

Resources Created

ResourceNamePurpose
VPC Networkserko-northsky-vpcMain network
GKE Subnetserko-northsky-gke-subnetGKE nodes and pods
Private Subnetserko-northsky-private-subnetDatabases and caches
Private IP Rangeserko-northsky-private-ip-rangePrivate service access
VPC Peeringserko-northsky-private-vpc-connectionConnect to managed services
Cloud Routerserko-northsky-routerRegional routing
Cloud NATserko-northsky-natOutbound internet for private nodes
Static IPserko-northsky-{env}-k8s-ipGKE Ingress load balancer IP
SSL Certificateserko-northsky-{env}-ssl-cert-v2Google-managed SSL certificate

Firewall Rules

RuleDirectionPortsPurpose
allow-internalIngressAllInternal VPC communication
allow-iap-sshIngress22SSH via IAP
allow-health-checksIngressAllGCP health check ranges
allow-gke-masterIngress443, 10250GKE control plane access

Configuration

# Pulumi.dev.yaml
config:
serko-northsky:gkeSubnetCidr: "10.0.1.0/24"
serko-northsky:privateSubnetCidr: "10.0.2.0/24"
serko-northsky:podCidr: "10.1.0.0/16"
serko-northsky:serviceCidr: "10.2.0.0/16"

IP Address Planning

CIDR BlockPurposeUsable IPs
10.0.1.0/24GKE nodes254
10.0.2.0/24Private services254
10.1.0.0/16Kubernetes pods65,534
10.2.0.0/16Kubernetes services65,534

Outputs

interface NetworkOutputs {
vpcId: string;
vpcName: string;
gkeSubnetId: string;
gkeSubnetName: string;
privateSubnetId: string;
privateSubnetName: string;
k8sIngressIpAddress: string;
sslCertificateName: string;
}

Usage in Other Components

The network is passed to dependent components:

const network = new Network('network', {
projectId,
region,
gkeSubnetCidr: '10.0.1.0/24',
privateSubnetCidr: '10.0.2.0/24',
podCidr: '10.1.0.0/16',
serviceCidr: '10.2.0.0/16',
});

// GKE uses the network
const gke = new GkeCluster('gke', {
network: network.vpc,
subnet: network.gkeSubnet,
// ...
});

// Cloud SQL uses the private VPC connection
const mainDb = new MainDB('main-db', {
vpcSelfLink: network.vpc.selfLink,
privateVpcConnection: network.privateVpcConnection,
// ...
}, { dependsOn: [network] });

Private Service Access

The network configures Private Service Access for managed services like Cloud SQL:

  1. IP Range Allocation: Reserves /16 range for Google services
  2. VPC Peering: Creates peering to servicenetworking.googleapis.com
  3. Private Connectivity: Databases accessible only within VPC

Static IP for Ingress

A global static IP address is reserved for the GKE Ingress load balancer:

this.k8sIngressIp = new gcp.compute.GlobalAddress(
`${name}-k8s-ingress-ip`,
{
name: `serko-northsky-${config.environment}-k8s-ip`,
project: config.projectId,
addressType: "EXTERNAL",
description: "Static IP for Kubernetes Ingress load balancer",
}
);

DNS Configuration

Point your DNS records to the static IP:

DomainRecord TypeValue
app.{env}.serko-northsky.comAStatic IP from Pulumi output
langfuse.{env}.serko-northsky.comAStatic IP from Pulumi output
tools.{env}.serko-northsky.comAStatic IP from Pulumi output
docs.{env}.serko-northsky.comAStatic IP from Pulumi output

Get the static IP:

pulumi stack output k8sIngressIpAddress

SSL/TLS Certificate

A Google-managed SSL certificate is provisioned for HTTPS:

this.sslCertificate = new gcp.compute.ManagedSslCertificate(
`${name}-ssl-cert`,
{
name: `serko-northsky-${config.environment}-ssl-cert-v2`,
project: config.projectId,
managed: {
domains: [
`app.${config.environment}.serko-northsky.com`,
`langfuse.${config.environment}.serko-northsky.com`,
`tools.${config.environment}.serko-northsky.com`,
`docs.${config.environment}.serko-northsky.com`,
],
},
}
);

Certificate Provisioning

The certificate goes through these stages:

  1. PROVISIONING: Initial state, waiting for DNS validation
  2. ACTIVE: Certificate is valid and serving traffic

Check certificate status:

gcloud compute ssl-certificates list --project=PROJECT_ID
gcloud compute ssl-certificates describe serko-northsky-{env}-ssl-cert-v2 --project=PROJECT_ID
note

DNS records must be configured and propagated before the certificate becomes ACTIVE. This can take up to 24 hours.