The 39Gi/node Longhorn data disks at 1:1 over-provisioning can't fit the media stack (plex 20Gi replica failed: 'insufficient storage'). Volumes are thin-provisioned config-only, so 200% lets the full catalog fit without a disk resize; physical fill risk is low. Also right-sized plex config (20Gi was excessive for metadata). Prod-grade path: grow the data disks (WS-STORAGE follow-up).
82 lines
3.9 KiB
YAML
82 lines
3.9 KiB
YAML
---
|
|
# Longhorn — distributed replicated block storage across the 3 nodes (ADR-0003).
|
|
# Serves R-STATE-01 (state survives destroy/rebuild) and R-STATE-02 (3-way replication).
|
|
#
|
|
# Dev-appropriate values. Environment differences enter ONLY via ${...} substitution from
|
|
# cluster-vars (R-ENV-02); everything else is identical base config for dev and prod.
|
|
apiVersion: helm.toolkit.fluxcd.io/v2
|
|
kind: HelmRelease
|
|
metadata:
|
|
name: longhorn
|
|
namespace: longhorn-system
|
|
spec:
|
|
interval: 30m
|
|
chart:
|
|
spec:
|
|
chart: longhorn
|
|
version: ">=1.7.0 <1.8.0" # TODO(WS-STORAGE): pin at bring-up; Renovate maintains
|
|
sourceRef:
|
|
kind: HelmRepository
|
|
name: longhorn
|
|
namespace: longhorn-system
|
|
install:
|
|
createNamespace: false # namespace.yaml owns it (GitOps-managed, labelled)
|
|
remediation:
|
|
retries: 3
|
|
upgrade:
|
|
remediation:
|
|
retries: 3
|
|
values:
|
|
# We own the StorageClasses (storageclasses.yaml) so the default 3-replica class and the bulk
|
|
# tier are explicit and GitOps-managed. Disable the chart's built-in default SC so there is
|
|
# exactly one default-class annotation in the cluster.
|
|
persistence:
|
|
defaultClass: false
|
|
|
|
defaultSettings:
|
|
# --- data path (R-STATE-02) ---
|
|
# Dedicated Longhorn data disk (/dev/vdb → ext4) is mounted here by cloud-init on every node
|
|
# (infra/cloud-init/user-data.yaml.tftpl). Longhorn stores replicas on this disk only.
|
|
defaultDataPath: "/var/lib/longhorn"
|
|
|
|
# --- replication (R-STATE-02) ---
|
|
# Global fallback replica count. The `longhorn` StorageClass sets numberOfReplicas explicitly
|
|
# (authoritative); this keeps any volume created without an explicit count consistent.
|
|
# Substituted from cluster-vars.longhorn_default_replica_count (=3 in dev).
|
|
defaultReplicaCount: ${LONGHORN_DEFAULT_REPLICA_COUNT}
|
|
|
|
# --- replica anti-affinity across nodes (R-STATE-02 durability guarantee) ---
|
|
# HARD anti-affinity: never place two replicas of the same volume on the same node, so a
|
|
# single node loss cannot take down more than one replica. On a 3-node / 3-replica cluster
|
|
# this yields exactly one replica per node.
|
|
replicaSoftAntiAffinity: false
|
|
# Single zone (3 mini-PCs, no failure zones): allow replicas within the one zone.
|
|
replicaZoneSoftAntiAffinity: true
|
|
# When a downed node returns, rebalance replicas back toward one-per-node (best-effort so it
|
|
# never blocks scheduling).
|
|
replicaAutoBalance: "best-effort"
|
|
|
|
# --- capacity guardrails (docs/04 "reserve disk headroom") ---
|
|
# Reserve 20% of the dedicated data disk so a node never fills to 100% (which wedges the
|
|
# kubelet and Longhorn alike). Dev disks are small, so headroom matters.
|
|
storageReservedPercentageForDefaultDisk: "20"
|
|
# Stop scheduling new replicas onto a disk once free space drops below 25%.
|
|
storageMinimalAvailablePercentage: "25"
|
|
# Dev: 200% thin over-provisioning — config-only volumes use little actual space, so the small
|
|
# 39Gi data disks host the full app catalog. Physical fill risk is low (watch monitoring PVCs).
|
|
# Prod-grade alternative: grow the Longhorn data disks and return to 1:1 (WS-STORAGE).
|
|
storageOverProvisioningPercentage: "200"
|
|
|
|
# --- misc dev-appropriate defaults ---
|
|
# Keep replicas spread for durability rather than co-locating with the pod.
|
|
defaultDataLocality: "disabled"
|
|
# Reclaim replica space of deleted/failed volumes promptly in dev.
|
|
orphanAutoDeletion: true
|
|
|
|
# Longhorn's own manager/UI stay in-cluster; UI exposure (if any) is gated behind
|
|
# oauth2-proxy forward-auth (ADR-0014) by WS-SEC — not exposed here.
|
|
|
|
# TODO(WS-STORAGE, Phase 4): off-cluster backup target (defaultSettings.backupTarget +
|
|
# backupTargetCredentialSecret) is configured alongside Velero (ADR-0003, R-STATE-03).
|
|
# Credentials referenced BY NAME only, SOPS-encrypted (WS-SEC) — never inline here.
|