prole/infrastructure/inventory/host_vars/merlin.prole.org.yml
chrisfu 5529fdea77 feat: full GKE/prod deployment pipeline from UI to Artifact Registry
## GCP / Cluster Environment Screen
- Auto-populate Cloud tab from conf/prod/gcp.cfg on screen open (org_id,
  billing_account, billing_project, project_id)
- gcloud auth validity checked on screen startup; friendly modal dialog
  streams gcloud auth login output live so user never leaves the app
- Live GKE cluster browser: fetches clusters via gcloud container clusters
  list, displays with checkmark selector, auto-selects saved cluster
- Selecting a cluster runs get-credentials, sets KUBECONFIG/KUBECONTEXT,
  and syncs the region dropdown to the selected cluster's location
- Region dropdown populated live from gcloud compute regions list with
  checkmark on currently selected region; graceful fallback when offline
- New 'GCP Storage' tab with workload->StorageClass mapping (CNPG->premium-rwo,
  Redis/Monitoring->standard-rwo, Garage->garage-hdd) and Fetch from Cluster
- Provider readonly field styled correctly (no solid-black on macOS)
- Stale prole.cfg/conf/prole.cfg symlinks removed; all config I/O now
  resolves env-specific paths via prole_conf.entrypoint_path()

## GKE Autopilot Compatibility (Common Services)
- Synology iSCSI StorageClass and static PVs guarded behind PROLE_MODE!=k8s
  in init_openbao.sh (GKE Autopilot forbids hostPath/iSCSI volumes)
- In-cluster Docker registry (hostPath) skipped in k8s mode; GCP Artifact
  Registry used instead
- Kong renamed knoe-svc-kong in k8s mode; all health-check kubectl calls in
  init_common_services.sh and status_common_services.sh updated accordingly
- DNS endpoints switched from *.prole.org to *.knoe.dev in k8s mode
  (api.knoe.dev, git.knoe.dev, svc.knoe.dev); ingress uses gce class
- New GKE-clean Kong manifests under deploy/opentofu/k8s/manifests/prole/:
  no k3s node affinity, explicit Autopilot resource requests/limits

## Garage S3 Store (GKE)
- New garage-statefulset-gcp.yaml targeting garage-hdd StorageClass
  (pd-standard, avoids SSD_TOTAL_GB quota exhaustion in us-west3)
- New storageclass-gcp-hdd.yaml (pd-standard, Retain, WaitForFirstConsumer)
- GCP StorageClass manifests skipped on re-runs (Autopilot built-ins are
  immutable; skip-if-exists guard added)
- PVC deletion guard extended to cover any storageClass (not just synology)
  so stale claims are cleaned before StatefulSet recreation

## Topology (GKE Autopilot)
- DaemonSet collector skipped in prod mode (forbidden in kube-system by
  GKE Warden); Kubernetes-only node facts path used instead
- All ready GKE nodes assumed cnpg-eligible and monitoring-eligible without
  taint/synology-mount checks (skip_collector + assume_nodes_eligible flags)

## KUBECONFIG / kubectl (k8s mode)
- actions.py: new elif mode==k8s branch sets KUBECONFIG=~/.kube/config
  and injects KUBECONTEXT from prole_cfg_data into script env
- _build_kubectl_cmd falls back to Global.KUBECONTEXT when
  init_cluster.selected_kubectx is empty
- _activate_selected_gke_cluster persists KUBECONFIG/KUBECONTEXT to
  prole_cfg_data and saves prole.cfg immediately after get-credentials

## Database Build Screen (GKE)
- Registry display shows correct Artifact Registry URL
  (<region>-docker.pkg.dev/<project>/<namespace>/knoe-db) in green
- Build+push: gcloud auth configure-docker, auto-creates AR repository
  named after SERVICE_NAMESPACE (e.g. knoe-system) if missing, then
  docker tag + push; falls back to gcr.io if region unavailable
- GCP config loaded from conf/prod/gcp.cfg on every screen entry;
  keys normalised to lowercase so project_id lookup is always consistent

## Config / Namespace persistence
- prole_conf.py activate_environment: symlink creation removed; sets
  CLUSTER_ENV env-var so all subsequent calls resolve correct env directory
- knoe/ui/screens/__init__.py: startup config load uses entrypoint_path()
  instead of hardcoded conf/prole.cfg; seeds SERVICE_NAMESPACE=knoe-system
  for managed envs so Common Services never defaults to 'default'
- cfg.py _save_prole_cfg: saves to env-specific path via entrypoint_path()
- etc/prole_cfg.sh: removed all ln -snf symlink creation

Co-authored-by: Junie <junie@jetbrains.com>
2026-04-04 12:38:29 -07:00

86 lines
2.9 KiB
YAML

---
ansible_host: 10.0.0.6
netplan_static_enabled: true
netplan_static_iface: eth0
netplan_static_address: 10.0.0.6/24
netplan_static_gateway4: 10.0.0.1
netplan_static_nameservers:
- 10.0.0.1
# MariaDB primary (USB-backed)
# Permanent portable USB disk for MariaDB (merlin)
# - Disk: UUID=3669ddf4-5884-43ae-84b2-150ec117a2b1 (ext4, ~1.82T)
# - Mount: /external (by UUID; device name varies after USB re-enumeration)
# - MariaDB datadir is expected at /srv/mariadb/mariadb, but is bind-mounted to /external/mariadb
# - Replaced borrowed WD My Book (exFAT) after disk-full kine deadlock incident (2026-04-03)
mariadb_external_enabled: true
mariadb_external_device: /dev/disk/by-uuid/3669ddf4-5884-43ae-84b2-150ec117a2b1
mariadb_external_mountpoint: /external
mariadb_external_fstype: ext4
# ext4 supports POSIX ownership; chown -R mysql:mysql was applied during migration from sda1.
mariadb_external_mount_opts: "defaults,nofail,x-systemd.device-timeout=10"
mariadb_external_src_datadir: /srv/mariadb/mariadb
mariadb_external_dst_datadir: /external/mariadb
mariadb_external_backup_datadir: /srv/mariadb/mariadb.pre-external
mariadb_external_migration_marker: /external/mariadb/.prole-mariadb-external-migrated
# k3s worker (stateless workloads)
k3s_enabled: true
k3s_role: agent
k3s_cluster_init: false
k3s_server_url: "https://myrddin.prole.org:6443"
# k3s datastore now lives on merlin.
# NOTE: Use IP to avoid DNS drift during migration/cutover.
k3s_datastore_mariadb_host: 10.0.0.6
k3s_datastore_mariadb_port: 3306
k3s_datastore_mariadb_db: k3s
k3s_datastore_mariadb_user: prole_k3s
k3s_datastore_endpoint: "mysql://{{ k3s_datastore_mariadb_user }}:{{ k3s_datastore_mariadb_password | urlencode }}@tcp({{ k3s_datastore_mariadb_host }}:{{ k3s_datastore_mariadb_port }})/{{ k3s_datastore_mariadb_db }}"
k3s_tls_sans:
- merlin.prole.org
k3s_service_node_labels:
- "prole.org/node-role=general"
k3s_node_taints: []
k3s_required_mounts:
- /synology/d002
- /synology/d004
# iSCSI
# `/var/lib/rancher` is local host storage (do not manage it via iSCSI).
iscsi_portal: 10.0.0.203:3260
iscsi_targets:
# PROLE-DATA-2
- iqn: "iqn.2000-01.com.synology:synology.Target-12.292d45194a1"
chap_user: "prole"
chap_password: "{{ vault_iscsi_prole_password }}"
mounts:
- name: d002
path: /synology/d002
fstype: xfs
opts: "_netdev,noatime"
src: "UUID=fe087fb0-a321-4767-b838-b4385e81693e"
# PROLE-DATA-4
# Repurposed from myrddin's former `/var/lib/rancher` Synology LUN.
# Repartitioned 2026-04-03: raw XFS on /dev/sdb → GPT + /dev/sdb1 (XFS).
- iqn: "iqn.2000-01.com.synology:synology.Target-15.292d45194a1"
chap_user: "prole"
chap_password: "{{ vault_iscsi_prole_password }}"
mounts:
- name: d004
path: /synology/d004
fstype: xfs
opts: "_netdev,noatime"
src: "UUID=45143352-142d-4e47-8508-9eb84c4c1f29"
iscsi_absent_mounts: []