9330107fcc
Implements Option A: move Vault (3x GCE e2-small) and Gitea (Legion k8s) onto a new GKE Autopilot cluster (neuron-platform, us-central1) managed through Legion Argo CD. Terraform (servers/gcp/): - gke.tf: GKE Autopilot cluster, Workload Identity bindings for Vault (KMS) and Gitea (Cloud SQL) - cloud-sql.tf: gitea database + user on neuron-prod-pg15, gitea GCP SA, gitea-database-url and gitea-db-password Secret Manager secrets - vault-nodes.tf: PENDING DECOMMISSION comment with migration checklist k8s manifests (servers/gcp/k8s/): - vault/: namespace.yaml - gitea/: namespace, serviceaccount (Workload Identity annotation), pvc (50Gi standard-rwo), deployment (Gitea + Cloud SQL Auth Proxy sidecar), service, configmap (custom CSS carried from Legion), external-secrets (GCP SM provider) - argocd-apps/: vault-gke.yaml, vault-helm-gke.yaml (Helm chart, HA Raft 3 replicas, GCP KMS auto-unseal, topologySpread across zones, 10Gi premium-rwo), gitea-gke.yaml — all target GKE_CLUSTER_ENDPOINT placeholder Legion (servers/legion/): - apps/gke-apps.yaml: App-of-Apps entry point on Legion Argo CD that syncs the GKE Application manifests - k8s/gitea-runner/Dockerfile: add system-level git insteadOf so GKE CI runners resolve Gitea in-cluster without Cloudflare Access headers
95 lines
3.8 KiB
Terraform
95 lines
3.8 KiB
Terraform
# ── GKE Autopilot Cluster — neuron-platform ───────────────────────────────────
|
|
#
|
|
# Regional Autopilot cluster in us-central1. Autopilot manages the node pool
|
|
# automatically — no node pools to configure, no VM sizes to choose.
|
|
# Pods spread across a/b/c zones automatically by GKE.
|
|
#
|
|
# Workload Identity is required so Vault pods can access KMS (auto-unseal)
|
|
# and Gitea pods can use Cloud SQL Auth Proxy without key files.
|
|
#
|
|
# After `terraform apply`, register the cluster with Legion Argo CD:
|
|
# 1. Get the endpoint: terraform output gke_cluster_endpoint
|
|
# 2. Get credentials: gcloud container clusters get-credentials neuron-platform \
|
|
# --region us-central1 --project neuron-785695
|
|
# 3. Register with Argo CD:
|
|
# argocd cluster add <context-name> --name gke-neuron-platform
|
|
# 4. Update servers/gcp/k8s/argocd-apps/*.yaml with the actual cluster endpoint.
|
|
|
|
resource "google_container_cluster" "neuron_platform" {
|
|
provider = google-beta
|
|
|
|
name = "neuron-platform"
|
|
location = "us-central1"
|
|
project = var.project_id
|
|
|
|
# Autopilot — GKE manages node pools, scaling, and node security
|
|
enable_autopilot = true
|
|
|
|
release_channel {
|
|
channel = "REGULAR"
|
|
}
|
|
|
|
# Workload Identity — required for Vault KMS and Gitea Cloud SQL proxy
|
|
workload_identity_config {
|
|
workload_pool = "${var.project_id}.svc.id.goog"
|
|
}
|
|
|
|
# Deletion protection — prevent accidental cluster destruction
|
|
deletion_protection = true
|
|
|
|
# Cluster networking — uses default VPC (same as Vault GCE nodes)
|
|
ip_allocation_policy {}
|
|
|
|
# Disable basic auth and client cert (Workload Identity handles auth)
|
|
master_auth {
|
|
client_certificate_config {
|
|
issue_client_certificate = false
|
|
}
|
|
}
|
|
}
|
|
|
|
# ── Workload Identity bindings ────────────────────────────────────────────────
|
|
#
|
|
# Each GCP SA gets a binding that allows its corresponding k8s ServiceAccount
|
|
# (in the GKE cluster) to impersonate it via Workload Identity.
|
|
# The k8s SA must also have the annotation:
|
|
# iam.gke.io/gcp-service-account: <gcp-sa-email>
|
|
|
|
# Vault pods (namespace: vault, k8s SA: vault) → vault-unseal GCP SA
|
|
# This lets the Vault StatefulSet access KMS for auto-unseal without key files.
|
|
resource "google_service_account_iam_member" "vault_workload_identity" {
|
|
service_account_id = google_service_account.vault_unseal.name
|
|
role = "roles/iam.workloadIdentityUser"
|
|
member = "serviceAccount:${var.project_id}.svc.id.goog[vault/vault]"
|
|
|
|
depends_on = [google_container_cluster.neuron_platform]
|
|
}
|
|
|
|
# Gitea pod (namespace: gitea, k8s SA: gitea) → gitea GCP SA
|
|
# This lets the Cloud SQL Auth Proxy sidecar connect to neuron-prod-pg15.
|
|
resource "google_service_account_iam_member" "gitea_workload_identity" {
|
|
service_account_id = google_service_account.gitea.name
|
|
role = "roles/iam.workloadIdentityUser"
|
|
member = "serviceAccount:${var.project_id}.svc.id.goog[gitea/gitea]"
|
|
|
|
depends_on = [google_container_cluster.neuron_platform]
|
|
}
|
|
|
|
# ── Outputs ───────────────────────────────────────────────────────────────────
|
|
|
|
output "gke_cluster_endpoint" {
|
|
description = "GKE cluster API endpoint — use as destination.server in Argo CD Applications"
|
|
value = "https://${google_container_cluster.neuron_platform.endpoint}"
|
|
sensitive = true
|
|
}
|
|
|
|
output "gke_cluster_name" {
|
|
description = "GKE cluster name"
|
|
value = google_container_cluster.neuron_platform.name
|
|
}
|
|
|
|
output "gke_workload_pool" {
|
|
description = "Workload Identity pool — used in Workload Identity bindings"
|
|
value = "${var.project_id}.svc.id.goog"
|
|
}
|