--- # Default replicated StorageClass — 3 replicas (ADR-0003, R-STATE-02). The durable home for # app/config state, databases, and KubeVirt VM disks (via CDI). Destroying a pod/VM leaves the PVC # and its data intact; rebuilding re-attaches it (R-STATE-01). # # This is the cluster's ONLY default StorageClass (the chart's built-in default is disabled in # helmrelease.yaml), so PVCs without an explicit storageClassName land here. apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: longhorn annotations: storageclass.kubernetes.io/is-default-class: "true" provisioner: driver.longhorn.io allowVolumeExpansion: true reclaimPolicy: Delete # dev: reclaim space when the PVC is deleted volumeBindingMode: Immediate parameters: # 3 replicas across 3 nodes (topology-LOCKED). HARD node anti-affinity in helmrelease.yaml # (replicaSoftAntiAffinity=false) guarantees these land on distinct nodes, so any single node # loss keeps the volume available. # HARDCODED, not ${LONGHORN_DEFAULT_REPLICA_COUNT}: StorageClass.parameters is map[string]string, # but kustomize strips the quotes around a bare "${VAR}" placeholder, so Flux postBuild substitution # yields an unquoted numeric (3) that server-side apply rejects (int, not string). A quoted numeric # literal like "3"/"30" IS preserved by kustomize. The replica knob still drives the GLOBAL default # via defaultSettings.defaultReplicaCount in helmrelease.yaml (a Helm int value, unaffected). numberOfReplicas: "3" staleReplicaTimeout: "30" # minutes before a down replica is considered stale and rebuilt dataLocality: "disabled" # keep replicas spread for durability, not co-located with the pod fsType: "ext4" --- # Bulk media tier — large, NON-replicated data (Plex library, download staging, arr handoff). # docs/04 / R-STATE-04: 3x replicating multi-TB media across 3 mini-PCs is impractical, so bulk # media lives OUTSIDE the cluster and is consumed as an external NFS/SMB mount via this thin # indirection. Services reference storageClassName: bulk; the concrete backing is filled in later # WITHOUT touching service definitions. # # ⚠️ STUB — OQ-2 UNRESOLVED (human operator decision). The provisioner + parameters below are # PLACEHOLDERS: they name the standard external NFS CSI driver but the server/share are REPLACE-ME. # This class will NOT provision until OQ-2 is answered and the NFS CSI driver is installed. That is # intentional — per docs/04 the bulk backing does not block the core platform. # # Plex's config/metadata DB is small and MUST stay on the 3-replica `longhorn` class regardless # (docs/04, ADR-0003) — only the large media files use `bulk`. apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: bulk provisioner: nfs.csi.k8s.io # TODO(OQ-2): external NFS/SMB backing — driver + endpoint TBD allowVolumeExpansion: true reclaimPolicy: Retain # bulk media is precious/reacquirable — never auto-delete on PVC removal volumeBindingMode: Immediate parameters: server: REPLACE-ME # TODO(OQ-2): NAS/NFS host holding the bulk media share share: REPLACE-ME # TODO(OQ-2): exported path (e.g. /export/media) mountOptions: - nfsvers=4.1