deploy gitea CI runner to GKE as k8s pod

Replaces the GCE VM runner with a k8s Deployment in the ci namespace on
neuron-platform GKE. Uses Docker-in-Docker for build isolation since
Autopilot doesn't expose the node socket. Runner token pulled from Secret
Manager via ESO + Workload Identity.

- servers/gcp/k8s/gitea-runner/: namespace, serviceaccount, external-secrets,
  deployment manifests (ci namespace, dind sidecar, idempotent registration)
- servers/gcp/k8s/argocd-apps/gitea-runner-gke.yaml: Argo CD Application
- servers/gcp/gitea-runner.tf: gitea-runner-gke GCP SA with secretAccessor
  on gitea-runner-token, Workload Identity binding for ci/gitea-runner,
  artifactregistry.reader for pulling ci-base image
This commit is contained in:
Will Anderson
2026-05-05 10:16:49 -05:00
parent 4dc687f2ae
commit c31edc8b83
6 changed files with 245 additions and 0 deletions
+40
View File
@@ -254,6 +254,46 @@ resource "google_service_account_iam_member" "ci_pusher_wif_neuron_web" {
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.gitea.name}/attribute.repository/neuron-technologies/neuron-web"
}
# ── Gitea Actions runner on GKE ───────────────────────────────────────────────
# A k8s Deployment in the `ci` namespace on GKE runs act_runner with a DinD
# sidecar. The pod uses this GCP SA via Workload Identity to pull the runner
# registration token from Secret Manager at startup.
#
# See servers/gcp/k8s/gitea-runner/ for the k8s manifests.
resource "google_service_account" "gitea_runner_gke" {
account_id = "gitea-runner-gke"
display_name = "Gitea Actions runner (GKE identity)"
description = "Workload Identity SA for the GKE-hosted Gitea Actions runner. Read-only access to the registration token."
project = var.project_id
}
# Allow the GKE SA to read the runner registration token from Secret Manager.
resource "google_secret_manager_secret_iam_member" "runner_gke_token_access" {
project = var.project_id
secret_id = "gitea-runner-token"
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.gitea_runner_gke.email}"
}
# Workload Identity binding — the k8s SA `gitea-runner` in the `ci` namespace
# can impersonate this GCP SA without a JSON key file.
resource "google_service_account_iam_member" "gitea_runner_gke_workload_identity" {
service_account_id = google_service_account.gitea_runner_gke.name
role = "roles/iam.workloadIdentityUser"
member = "serviceAccount:${var.project_id}.svc.id.goog[ci/gitea-runner]"
depends_on = [google_container_cluster.neuron_platform]
}
# Allow the runner to pull images from Artifact Registry (needed for build jobs
# that pull from neuron-* repos, and for the runner's own ci-base image).
resource "google_project_iam_member" "gitea_runner_gke_ar_reader" {
project = var.project_id
role = "roles/artifactregistry.reader"
member = "serviceAccount:${google_service_account.gitea_runner_gke.email}"
}
# ── Outputs ───────────────────────────────────────────────────────────────────
output "gitea_runner_vm_name" {