From ab658982343daa63c73517270aa96c3f45711a6d Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Sat, 25 Jul 2026 10:45:46 +0200 Subject: [PATCH] refactor(immich): fold seed-immich into the immich KS (stage 2) Completes the immich seed->apps move (same single-transfer pattern as paperless #400). Restore-test passed first (im-pg backup restorable: 33316 rows in asset). - git mv seed/immich/{cluster,objectstore,scheduled-backup,barman-creds- externalsecret,hetzner-creds-externalsecret,pvcs}.yaml -> apps/immich/, add to apps/immich/kustomization.yaml. - immich KS: drop 'dependsOn: seed-immich', add 'dependsOn: infrastructure-cnpg-barman', add the CNPG Cluster healthCheckExprs. - Delete clusters/homelab/seed-immich.yaml and the now-empty seed/immich/. - e2e-test.sh: drop seed-immich, add immich to the app-KS readiness checks (immich was previously only covered via seed-immich). - Fix the last stale seed/immich comment path in infrastructure/openbao/snapshot-pvc.yaml (seed/immich -> apps/immich). Safe ownership transfer (nothing pruned): all 7 seed/immich objects carry prune: disabled (5 CNPG from stage 1 #401, 2 PVCs pre-existing), so deleting seed-immich skips them in GC and the immich KS adopts them in place. No CNPG restart, no app restart. Verified: kubectl kustomize apps/immich builds 17 objects incl. Cluster/im-pg, exactly 7 prune-protected; bash -n e2e-test.sh OK; seed/immich fully removed. Left intentionally: the hetzner-creds ExternalSecret still reads OpenBao key seed/immich/... (vault path, not a repo path). Co-Authored-By: Claude Bot Co-Authored-By: Claude Opus 4.8 (1M context) --- .../immich/barman-creds-externalsecret.yaml | 0 kubernetes/{seed => apps}/immich/cluster.yaml | 0 .../immich/hetzner-creds-externalsecret.yaml | 0 kubernetes/apps/immich/kustomization.yaml | 10 ++++++ .../{seed => apps}/immich/objectstore.yaml | 0 kubernetes/{seed => apps}/immich/pvcs.yaml | 0 .../immich/scheduled-backup.yaml | 0 kubernetes/clusters/homelab/immich.yaml | 13 +++++-- kubernetes/clusters/homelab/seed-immich.yaml | 35 ------------------- kubernetes/e2e-test.sh | 4 +-- .../infrastructure/openbao/snapshot-pvc.yaml | 2 +- kubernetes/seed/immich/kustomization.yaml | 9 ----- 12 files changed, 23 insertions(+), 50 deletions(-) rename kubernetes/{seed => apps}/immich/barman-creds-externalsecret.yaml (100%) rename kubernetes/{seed => apps}/immich/cluster.yaml (100%) rename kubernetes/{seed => apps}/immich/hetzner-creds-externalsecret.yaml (100%) rename kubernetes/{seed => apps}/immich/objectstore.yaml (100%) rename kubernetes/{seed => apps}/immich/pvcs.yaml (100%) rename kubernetes/{seed => apps}/immich/scheduled-backup.yaml (100%) delete mode 100644 kubernetes/clusters/homelab/seed-immich.yaml delete mode 100644 kubernetes/seed/immich/kustomization.yaml diff --git a/kubernetes/seed/immich/barman-creds-externalsecret.yaml b/kubernetes/apps/immich/barman-creds-externalsecret.yaml similarity index 100% rename from kubernetes/seed/immich/barman-creds-externalsecret.yaml rename to kubernetes/apps/immich/barman-creds-externalsecret.yaml diff --git a/kubernetes/seed/immich/cluster.yaml b/kubernetes/apps/immich/cluster.yaml similarity index 100% rename from kubernetes/seed/immich/cluster.yaml rename to kubernetes/apps/immich/cluster.yaml diff --git a/kubernetes/seed/immich/hetzner-creds-externalsecret.yaml b/kubernetes/apps/immich/hetzner-creds-externalsecret.yaml similarity index 100% rename from kubernetes/seed/immich/hetzner-creds-externalsecret.yaml rename to kubernetes/apps/immich/hetzner-creds-externalsecret.yaml diff --git a/kubernetes/apps/immich/kustomization.yaml b/kubernetes/apps/immich/kustomization.yaml index 3a2640eb..ad1b5458 100644 --- a/kubernetes/apps/immich/kustomization.yaml +++ b/kubernetes/apps/immich/kustomization.yaml @@ -6,3 +6,13 @@ resources: - machine-learning.yaml - server.yaml - ingress.yaml + # im-pg CNPG Postgres + library/ml-cache PVCs (moved here from the retired + # seed-immich KS; each carries prune: disabled so ownership transferred without + # a teardown). This KS gains the infrastructure-cnpg-barman dep + CNPG Cluster + # healthCheckExprs (see clusters/homelab/immich.yaml). + - cluster.yaml + - objectstore.yaml + - scheduled-backup.yaml + - barman-creds-externalsecret.yaml + - hetzner-creds-externalsecret.yaml + - pvcs.yaml diff --git a/kubernetes/seed/immich/objectstore.yaml b/kubernetes/apps/immich/objectstore.yaml similarity index 100% rename from kubernetes/seed/immich/objectstore.yaml rename to kubernetes/apps/immich/objectstore.yaml diff --git a/kubernetes/seed/immich/pvcs.yaml b/kubernetes/apps/immich/pvcs.yaml similarity index 100% rename from kubernetes/seed/immich/pvcs.yaml rename to kubernetes/apps/immich/pvcs.yaml diff --git a/kubernetes/seed/immich/scheduled-backup.yaml b/kubernetes/apps/immich/scheduled-backup.yaml similarity index 100% rename from kubernetes/seed/immich/scheduled-backup.yaml rename to kubernetes/apps/immich/scheduled-backup.yaml diff --git a/kubernetes/clusters/homelab/immich.yaml b/kubernetes/clusters/homelab/immich.yaml index aaf03796..01d0f5c5 100644 --- a/kubernetes/clusters/homelab/immich.yaml +++ b/kubernetes/clusters/homelab/immich.yaml @@ -4,8 +4,10 @@ metadata: name: immich namespace: flux-system spec: - # DB cluster + library PVC are populated by the seed phase; this - # Kustomization reconciles app manifests only. + # Owns the immich app plus its im-pg CNPG Cluster + ObjectStore + + # ScheduledBackup and the library/ml-cache PVCs (folded in from the retired + # seed-immich KS). The one-shot pg_restore + library-rsync seed Jobs that + # originally populated them are long gone. interval: 10m retryInterval: 1m timeout: 30m @@ -21,4 +23,9 @@ spec: - name: infrastructure - name: infrastructure-crds - name: infrastructure-ceph-cluster - - name: seed-immich + - name: infrastructure-cnpg-barman + healthCheckExprs: + - apiVersion: postgresql.cnpg.io/v1 + kind: Cluster + failed: "has(status.phase) && status.phase.startsWith('Failed')" + current: "has(status.phase) && (status.phase == 'Cluster in healthy state' || status.readyInstances > 0)" diff --git a/kubernetes/clusters/homelab/seed-immich.yaml b/kubernetes/clusters/homelab/seed-immich.yaml deleted file mode 100644 index d8d239fe..00000000 --- a/kubernetes/clusters/homelab/seed-immich.yaml +++ /dev/null @@ -1,35 +0,0 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1 -kind: Kustomization -metadata: - name: seed-immich - namespace: flux-system -spec: - # Per-app slice of the former monolithic `seed` KS — owns the im-pg - # CNPG Cluster, ObjectStore, ScheduledBackup, the pg_restore seed Job, - # and the long library-seed rsync (~250 GiB, the wall-time pole of - # the rebuild). Only the downstream `immich` KS gates on this; other - # apps are no longer blocked by it. The Cluster bootstraps via `initdb` - # (empty DB on cold rebuild); CNPG restore is manual — see the runbook - # at kubernetes/seed/RECOVERY.md (issue #190). - interval: 10m - retryInterval: 2m - # Long enough for the worst-case immich-library rsync (~30–45 min). - timeout: 4h - sourceRef: - kind: GitRepository - name: flux-system - path: ./kubernetes/seed/immich - prune: true - wait: true - # decryption block dropped 2026-07-14: path is sops-free — secrets come - # from OpenBao via ESO (MIGRATION-sops-openbao.md). - dependsOn: - - name: infrastructure - - name: infrastructure-crds - - name: infrastructure-ceph-cluster - - name: infrastructure-cnpg-barman - healthCheckExprs: - - apiVersion: postgresql.cnpg.io/v1 - kind: Cluster - failed: "has(status.phase) && status.phase.startsWith('Failed')" - current: "has(status.phase) && (status.phase == 'Cluster in healthy state' || status.readyInstances > 0)" diff --git a/kubernetes/e2e-test.sh b/kubernetes/e2e-test.sh index 1085c042..8af151a9 100755 --- a/kubernetes/e2e-test.sh +++ b/kubernetes/e2e-test.sh @@ -107,8 +107,8 @@ check "3 nodes Ready" \ echo "=== Flux Kustomizations ===" for ks in flux-system infrastructure infrastructure-crds infrastructure-ceph-cluster \ - seed-authentik seed-immich influxdb \ - apps authentik paperless audiobookshelf woodpecker; do + seed-authentik influxdb \ + apps authentik paperless audiobookshelf woodpecker immich; do check "kustomization/$ks Ready" \ bash -c "kubectl -n flux-system get kustomization $ks \ -o jsonpath='{.status.conditions[?(@.type==\"Ready\")].status}' | grep -q '^True\$'" diff --git a/kubernetes/infrastructure/openbao/snapshot-pvc.yaml b/kubernetes/infrastructure/openbao/snapshot-pvc.yaml index b43f2cad..42eb88a2 100644 --- a/kubernetes/infrastructure/openbao/snapshot-pvc.yaml +++ b/kubernetes/infrastructure/openbao/snapshot-pvc.yaml @@ -8,7 +8,7 @@ metadata: # snapshots — the raft data PVC itself is NOT backed up). Shield it from # Flux prune so a rename/removal/move of this manifest can never delete # the backup volume out from under a disaster recovery, matching the - # sibling data PVCs (apps/home-assistant, seed/immich, apps/paperless). + # sibling data PVCs (apps/home-assistant, apps/immich, apps/paperless). kustomize.toolkit.fluxcd.io/prune: disabled labels: # Velero's openbao-daily Schedule selects exactly this label — the raft diff --git a/kubernetes/seed/immich/kustomization.yaml b/kubernetes/seed/immich/kustomization.yaml deleted file mode 100644 index e447f1fb..00000000 --- a/kubernetes/seed/immich/kustomization.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: - - barman-creds-externalsecret.yaml - - hetzner-creds-externalsecret.yaml - - objectstore.yaml - - cluster.yaml - - scheduled-backup.yaml - - pvcs.yaml -- 2.54.0