migrate Vault and Gitea to GKE Autopilot cluster
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
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: gitea-gke
|
||||
namespace: argocd
|
||||
annotations:
|
||||
# Apply to the Legion Argo CD instance after registering the GKE cluster.
|
||||
# See vault-gke.yaml for the cluster registration steps.
|
||||
#
|
||||
# Migration checklist (Gitea from Legion to GKE):
|
||||
# 1. terraform apply (creates GKE cluster, Cloud SQL gitea DB, secrets)
|
||||
# 2. Register GKE cluster with Legion Argo CD (see vault-gke.yaml)
|
||||
# 3. Install ESO on GKE: helm install external-secrets external-secrets/external-secrets
|
||||
# --namespace external-secrets --create-namespace
|
||||
# 4. Apply this Application to Legion Argo CD
|
||||
# 5. Verify gitea pod is running on GKE with DB connectivity
|
||||
# 6. Take a tar of /data from the Legion Gitea pod and restore to GKE PVC
|
||||
# 7. Update Cloudflare Tunnel on Legion: remove git.neuralplatform.ai route
|
||||
# 8. Add GKE ingress / GCP LB rule for git.neuralplatform.ai
|
||||
# 9. Decommission Gitea on Legion (remove gitea*.yaml from servers/legion/apps/)
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: http://gitea.git.svc.cluster.local:3000/will/infrastructure.git
|
||||
targetRevision: main
|
||||
path: servers/gcp/k8s/gitea
|
||||
destination:
|
||||
# Replace GKE_CLUSTER_ENDPOINT after `terraform apply`:
|
||||
# terraform -chdir=servers/gcp output -raw gke_cluster_endpoint
|
||||
server: https://GKE_CLUSTER_ENDPOINT
|
||||
namespace: gitea
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
- ServerSideApply=true
|
||||
@@ -0,0 +1,33 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: vault-gke
|
||||
namespace: argocd
|
||||
annotations:
|
||||
# Syncs plain k8s manifests for Vault to the GKE cluster.
|
||||
# The Vault Helm release itself is in vault-helm-gke.yaml.
|
||||
#
|
||||
# Apply to Legion Argo CD after registering the GKE cluster:
|
||||
# 1. gcloud container clusters get-credentials neuron-platform \
|
||||
# --region us-central1 --project neuron-785695
|
||||
# 2. argocd cluster add <context-name> --name gke-neuron-platform
|
||||
# 3. Update GKE_CLUSTER_ENDPOINT in all argocd-apps/*.yaml:
|
||||
# terraform -chdir=servers/gcp output -raw gke_cluster_endpoint
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: http://gitea.git.svc.cluster.local:3000/will/infrastructure.git
|
||||
targetRevision: main
|
||||
path: servers/gcp/k8s/vault
|
||||
destination:
|
||||
# Replace GKE_CLUSTER_ENDPOINT after `terraform apply`:
|
||||
# terraform -chdir=servers/gcp output -raw gke_cluster_endpoint
|
||||
server: https://GKE_CLUSTER_ENDPOINT
|
||||
namespace: vault
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
- ServerSideApply=true
|
||||
@@ -0,0 +1,153 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: vault-helm-gke
|
||||
namespace: argocd
|
||||
annotations:
|
||||
# Deploys the Vault Helm chart to the GKE cluster via Legion Argo CD.
|
||||
# The destination.server must be updated after `terraform apply`:
|
||||
# terraform -chdir=servers/gcp output -raw gke_cluster_endpoint
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: https://helm.releases.hashicorp.com
|
||||
chart: vault
|
||||
targetRevision: "0.29.1"
|
||||
helm:
|
||||
values: |
|
||||
global:
|
||||
enabled: true
|
||||
|
||||
injector:
|
||||
enabled: false
|
||||
|
||||
ui:
|
||||
enabled: true
|
||||
|
||||
server:
|
||||
image:
|
||||
repository: hashicorp/vault
|
||||
tag: "1.19.2"
|
||||
|
||||
# Workload Identity — Vault pod k8s SA impersonates vault-unseal GCP SA
|
||||
# for KMS auto-unseal. Binding is in servers/gcp/gke.tf.
|
||||
serviceAccount:
|
||||
create: true
|
||||
name: vault
|
||||
annotations:
|
||||
iam.gke.io/gcp-service-account: vault-unseal@neuron-785695.iam.gserviceaccount.com
|
||||
|
||||
# GKE Autopilot: no privileged containers. Vault doesn't need privilege.
|
||||
# Request IPC_LOCK so Vault can lock memory (prevents secrets swap).
|
||||
securityContext:
|
||||
capabilities:
|
||||
add:
|
||||
- IPC_LOCK
|
||||
|
||||
# HA mode — 3 replicas with Raft storage
|
||||
ha:
|
||||
enabled: true
|
||||
replicas: 3
|
||||
raft:
|
||||
enabled: true
|
||||
setNodeId: true
|
||||
config: |
|
||||
ui = true
|
||||
|
||||
listener "tcp" {
|
||||
tls_disable = 1
|
||||
address = "[::]:8200"
|
||||
cluster_address = "[::]:8201"
|
||||
}
|
||||
|
||||
storage "raft" {
|
||||
path = "/vault/data"
|
||||
|
||||
retry_join {
|
||||
leader_api_addr = "http://vault-0.vault-internal:8200"
|
||||
}
|
||||
retry_join {
|
||||
leader_api_addr = "http://vault-1.vault-internal:8200"
|
||||
}
|
||||
retry_join {
|
||||
leader_api_addr = "http://vault-2.vault-internal:8200"
|
||||
}
|
||||
}
|
||||
|
||||
seal "gcpckms" {
|
||||
project = "neuron-785695"
|
||||
region = "global"
|
||||
key_ring = "vault"
|
||||
crypto_key = "vault-unseal"
|
||||
}
|
||||
|
||||
telemetry {
|
||||
prometheus_retention_time = "30s"
|
||||
disable_hostname = false
|
||||
}
|
||||
|
||||
# Spread pods across GKE zones
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: topology.kubernetes.io/zone
|
||||
whenUnsatisfiable: DoNotSchedule
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: vault
|
||||
component: server
|
||||
|
||||
# 10Gi SSD per pod — premium-rwo = pd-ssd on GKE Autopilot
|
||||
dataStorage:
|
||||
enabled: true
|
||||
size: 10Gi
|
||||
storageClass: premium-rwo
|
||||
accessMode: ReadWriteOnce
|
||||
|
||||
readinessProbe:
|
||||
enabled: true
|
||||
path: "/v1/sys/health?standbyok=true&sealedok=true&uninitcode=200"
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
failureThreshold: 3
|
||||
|
||||
livenessProbe:
|
||||
enabled: true
|
||||
path: "/v1/sys/health?standbyok=true&sealedok=true&uninitcode=200"
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
|
||||
# GKE Autopilot requires resource requests on all containers
|
||||
resources:
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 250m
|
||||
limits:
|
||||
memory: 512Mi
|
||||
cpu: 500m
|
||||
|
||||
service:
|
||||
enabled: true
|
||||
type: ClusterIP
|
||||
port: 8200
|
||||
targetPort: 8200
|
||||
|
||||
# Ingress disabled — Vault is exposed via GCP HTTPS LB.
|
||||
# After migration, update the existing LB backend (vault-nodes.tf)
|
||||
# to target a GKE NEG instead of the GCE instance groups.
|
||||
# See: https://cloud.google.com/kubernetes-engine/docs/how-to/standalone-neg
|
||||
ingress:
|
||||
enabled: false
|
||||
|
||||
destination:
|
||||
# Replace GKE_CLUSTER_ENDPOINT after `terraform apply`:
|
||||
# terraform -chdir=servers/gcp output -raw gke_cluster_endpoint
|
||||
server: https://GKE_CLUSTER_ENDPOINT
|
||||
namespace: vault
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
- ServerSideApply=true
|
||||
Reference in New Issue
Block a user