mirror of
https://github.com/dredx/prole.git
synced 2026-09-28 06:34:30 +00:00
Add complete GKE deployment stack: - deploy/gcp/gke/: namespace, CloudNativePG cluster (premium-rwo, 100Gi), GCS barman-cloud backup with Workload Identity SA, ArgoCD OIDC ConfigMap, GitLab OmniAuth secret template, knoe-auth Google OIDC secret template - etc/init_cnpg_gke.sh: provision GCS buckets, GCP SA, WI binding, CNPG operator - etc/init_argocd.sh: apply argocd-oidc-cm.yaml when PLATFORM_DOMAIN/FRONTDOOR_HOST set - etc/init_gitlab.sh: inject OmniAuth openid_connect block when FRONTDOOR_HOST set - prole-auth-deployment.yaml: add GOOGLE_OIDC_ENABLED env vars (all optional) - supabase/helm/prole-supabase/values-gke.yaml: GoTrue Google OAuth overlay - knoe/core/prod_config.py: add backupProvider, workloadIdentitySA, googleClientId/Secret/HostedDomain Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
139 lines
6.7 KiB
Bash
Executable File
139 lines
6.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# init_cnpg_gke.sh
|
|
# Provision CloudNativePG on GKE with GCS backup via Workload Identity.
|
|
#
|
|
# Usage:
|
|
# ./etc/init_cnpg_gke.sh [--project PROJECT_ID] [--region REGION] [--cluster CLUSTER_NAME]
|
|
#
|
|
# Env vars (override flags):
|
|
# GCP_PROJECT_ID, GCP_REGION, GKE_CLUSTER, GCS_BACKUP_BUCKET,
|
|
# CNPG_NAMESPACE, ARTIFACT_REGISTRY, CLOUDSDK_AUTH_ACCESS_TOKEN
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
GKE_MANIFEST_DIR="$REPO_ROOT/deploy/gcp/gke"
|
|
|
|
# ── Defaults ────────────────────────────────────────────────────────────────
|
|
GCP_PROJECT_ID="${GCP_PROJECT_ID:-}"
|
|
GCP_REGION="${GCP_REGION:-us-central1}"
|
|
GKE_CLUSTER="${GKE_CLUSTER:-knoe-dev-0}"
|
|
GCS_BACKUP_BUCKET="${GCS_BACKUP_BUCKET:-knoe-0-backups}"
|
|
GCS_WAL_BUCKET="${GCS_WAL_BUCKET:-knoe-0-wal}"
|
|
CNPG_NAMESPACE="${CNPG_NAMESPACE:-ecosystem-0}"
|
|
CNPG_BACKUP_SA="${CNPG_BACKUP_SA:-cnpg-backup}"
|
|
ARTIFACT_REGISTRY="${ARTIFACT_REGISTRY:-}"
|
|
|
|
# ── Argument parsing ─────────────────────────────────────────────────────────
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--project) GCP_PROJECT_ID="$2"; shift 2 ;;
|
|
--region) GCP_REGION="$2"; shift 2 ;;
|
|
--cluster) GKE_CLUSTER="$2"; shift 2 ;;
|
|
--bucket) GCS_BACKUP_BUCKET="$2"; shift 2 ;;
|
|
--namespace) CNPG_NAMESPACE="$2"; shift 2 ;;
|
|
--registry) ARTIFACT_REGISTRY="$2"; shift 2 ;;
|
|
*) echo "Unknown argument: $1" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
[[ -z "$GCP_PROJECT_ID" ]] && {
|
|
# Try to read from gcp.cfg
|
|
GCP_CFG="$REPO_ROOT/conf/prod/gcp.cfg"
|
|
if [[ -f "$GCP_CFG" ]]; then
|
|
GCP_PROJECT_ID=$(grep '^project_id' "$GCP_CFG" | sed 's/.*=\s*"\?\([^"]*\)"\?.*/\1/' | tr -d '[:space:]')
|
|
fi
|
|
}
|
|
[[ -z "$GCP_PROJECT_ID" ]] && { echo "ERROR: GCP_PROJECT_ID not set and conf/prod/gcp.cfg not found." >&2; exit 1; }
|
|
|
|
GCP_SA_EMAIL="${CNPG_BACKUP_SA}@${GCP_PROJECT_ID}.iam.gserviceaccount.com"
|
|
|
|
log() { echo "[init_cnpg_gke] $*"; }
|
|
|
|
# ── Tool checks ──────────────────────────────────────────────────────────────
|
|
for tool in gcloud kubectl gsutil; do
|
|
command -v "$tool" >/dev/null || { echo "ERROR: $tool not found in PATH." >&2; exit 1; }
|
|
done
|
|
|
|
# ── 1. Acquire kubeconfig ────────────────────────────────────────────────────
|
|
log "Fetching kubeconfig for $GKE_CLUSTER in $GCP_REGION ..."
|
|
gcloud container clusters get-credentials "$GKE_CLUSTER" \
|
|
--project "$GCP_PROJECT_ID" \
|
|
--region "$GCP_REGION"
|
|
|
|
# ── 2. Create GCS buckets ────────────────────────────────────────────────────
|
|
for bucket in "$GCS_BACKUP_BUCKET" "$GCS_WAL_BUCKET"; do
|
|
if gsutil ls -b "gs://$bucket" >/dev/null 2>&1; then
|
|
log "Bucket gs://$bucket already exists."
|
|
else
|
|
log "Creating bucket gs://$bucket ..."
|
|
gsutil mb -p "$GCP_PROJECT_ID" -l "$GCP_REGION" "gs://$bucket"
|
|
gsutil versioning set on "gs://$bucket"
|
|
gsutil lifecycle set /dev/stdin "gs://$bucket" <<EOF
|
|
{"rule":[{"action":{"type":"Delete"},"condition":{"age":30}}]}
|
|
EOF
|
|
fi
|
|
done
|
|
|
|
# ── 3. Create GCP service account ────────────────────────────────────────────
|
|
if gcloud iam service-accounts describe "$GCP_SA_EMAIL" --project "$GCP_PROJECT_ID" >/dev/null 2>&1; then
|
|
log "Service account $GCP_SA_EMAIL already exists."
|
|
else
|
|
log "Creating service account $GCP_SA_EMAIL ..."
|
|
gcloud iam service-accounts create "$CNPG_BACKUP_SA" \
|
|
--display-name="CNPG GCS Backup" \
|
|
--project="$GCP_PROJECT_ID"
|
|
fi
|
|
|
|
# ── 4. Grant storage access ───────────────────────────────────────────────────
|
|
log "Granting objectAdmin on backup buckets to $GCP_SA_EMAIL ..."
|
|
for bucket in "$GCS_BACKUP_BUCKET" "$GCS_WAL_BUCKET"; do
|
|
gsutil iam ch \
|
|
"serviceAccount:${GCP_SA_EMAIL}:objectAdmin" \
|
|
"gs://$bucket"
|
|
done
|
|
|
|
# ── 5. Bind Workload Identity ─────────────────────────────────────────────────
|
|
log "Binding Workload Identity ..."
|
|
gcloud iam service-accounts add-iam-policy-binding "$GCP_SA_EMAIL" \
|
|
--role=roles/iam.workloadIdentityUser \
|
|
--member="serviceAccount:${GCP_PROJECT_ID}.svc.id.goog[${CNPG_NAMESPACE}/cnpg-backup-sa]" \
|
|
--project="$GCP_PROJECT_ID"
|
|
|
|
# ── 6. Apply namespace ────────────────────────────────────────────────────────
|
|
log "Applying namespace $CNPG_NAMESPACE ..."
|
|
kubectl apply -f "$GKE_MANIFEST_DIR/namespace.yaml"
|
|
|
|
# ── 7. Install CNPG operator (if not present) ─────────────────────────────────
|
|
if ! kubectl get crd clusters.postgresql.cnpg.io >/dev/null 2>&1; then
|
|
log "Installing CloudNativePG operator ..."
|
|
kubectl apply --server-side -f \
|
|
https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/main/releases/cnpg-1.24.0.yaml
|
|
log "Waiting for CNPG operator to be ready ..."
|
|
kubectl rollout status deployment/cnpg-controller-manager -n cnpg-system --timeout=120s
|
|
else
|
|
log "CNPG operator already installed."
|
|
fi
|
|
|
|
# ── 8. Apply ServiceAccount + annotate with WI ───────────────────────────────
|
|
log "Applying CNPG backup ServiceAccount with Workload Identity annotation ..."
|
|
GCP_PROJECT_ID="$GCP_PROJECT_ID" envsubst < "$GKE_MANIFEST_DIR/knoe-db-backup-gcs.yaml" \
|
|
| kubectl apply -f -
|
|
|
|
kubectl annotate serviceaccount cnpg-backup-sa \
|
|
-n "$CNPG_NAMESPACE" \
|
|
"iam.gke.io/gcp-service-account=${GCP_SA_EMAIL}" \
|
|
--overwrite
|
|
|
|
# ── 9. Apply CNPG cluster ────────────────────────────────────────────────────
|
|
log "Applying knoe-db CNPG cluster ..."
|
|
ARTIFACT_REGISTRY="${ARTIFACT_REGISTRY}" envsubst < "$GKE_MANIFEST_DIR/knoe-db.yaml" \
|
|
| kubectl apply -f -
|
|
|
|
log ""
|
|
log "Done. Monitor with:"
|
|
log " kubectl -n $CNPG_NAMESPACE get cluster knoe-db"
|
|
log " kubectl -n $CNPG_NAMESPACE get pods -l cnpg.io/cluster=knoe-db"
|
|
log " kubectl -n $CNPG_NAMESPACE get scheduledbackup"
|