# ─── Required APIs ──────────────────────────────────────────────────── resource "google_project_service" "compute" { project = var.project_id service = "compute.googleapis.com" disable_on_destroy = false } resource "google_project_service" "container" { project = var.project_id service = "container.googleapis.com" disable_on_destroy = false } # ─── Networking ─────────────────────────────────────────────────────── resource "google_compute_network" "main" { project = var.project_id name = "${var.prefix}-vpc" auto_create_subnetworks = false depends_on = [google_project_service.compute] } resource "google_compute_subnetwork" "main" { project = var.project_id name = "${var.prefix}-subnet" ip_cidr_range = "10.100.0.0/22" region = var.region network = google_compute_network.main.id # Secondary ranges required for GKE VPC-native cluster secondary_ip_range { range_name = "pods" ip_cidr_range = "10.200.0.0/14" # /14 = ~262k pod IPs } secondary_ip_range { range_name = "services" ip_cidr_range = "10.204.0.0/20" # /20 = ~4k service IPs } } # ─── GKE Cluster ────────────────────────────────────────────────────── # # Regional cluster (3 control-plane replicas) for HA. # Workload Identity enabled — allows K8s service accounts to impersonate # Google Service Accounts for keyless access to GCP services. resource "google_container_cluster" "main" { project = var.project_id name = "${var.prefix}-gke" location = var.region # regional cluster network = google_compute_network.main.id subnetwork = google_compute_subnetwork.main.id # VPC-native cluster with alias IP ranges ip_allocation_policy { cluster_secondary_range_name = "pods" services_secondary_range_name = "services" } # Workload Identity pool — enables OIDC token projection for pods workload_identity_config { workload_pool = "${var.project_id}.svc.id.goog" } # Remove default node pool — we manage our own below remove_default_node_pool = true initial_node_count = 1 deletion_protection = var.deletion_protection dynamic "release_channel" { for_each = var.kubernetes_version == null ? [1] : [] content { channel = "STABLE" } } resource_labels = var.labels depends_on = [google_project_service.container] } resource "google_container_node_pool" "main" { project = var.project_id name = "${var.prefix}-nodes" location = var.region cluster = google_container_cluster.main.name node_count = var.node_count node_config { machine_type = var.node_machine_type # GKE_METADATA mode is required for Workload Identity workload_metadata_config { mode = "GKE_METADATA" } oauth_scopes = [ "https://www.googleapis.com/auth/cloud-platform", ] labels = merge(var.labels, { role = "worker" }) } management { auto_repair = true auto_upgrade = true } }