diff --git a/Chart.yaml b/Chart.yaml index 3501f07..c9af467 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -23,8 +23,8 @@ description: | Git). type: application -version: 0.2.6 -appVersion: "0.2.6" +version: 0.3.0 +appVersion: "0.3.0" dependencies: - name: cert-manager @@ -35,3 +35,12 @@ dependencies: version: "33.2.1" repository: "https://traefik.github.io/charts" condition: traefik.enabled + # Longhorn — CSI block storage with snapshot + clone primitives. + # See ADR 0003 (in odooskyv3 monorepo). Phase 1 declares the + # dependency but the chart's default is `longhorn.enabled=false`, + # so `helm dep update` skips it on render unless a per-cluster + # Argo Application sets the flag. + - name: longhorn + version: "1.7.2" + repository: "https://charts.longhorn.io" + condition: longhorn.enabled diff --git a/templates/longhorn.yaml b/templates/longhorn.yaml new file mode 100644 index 0000000..2266b04 --- /dev/null +++ b/templates/longhorn.yaml @@ -0,0 +1,43 @@ +{{- if .Values.longhorn.enabled }} +# Tenant data StorageClass. Tower's instance overlays don't pin a +# storageClassName today (they let the cluster default decide). Phase +# 1 of ADR 0003 just defines this class so Phase 2/3 can flip new +# instances to bind here without further chart changes. +# +# `replicaCount` comes from values; Standalone tier ships replicas=1 +# (durability is hourly S3, not local mirrors). +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: longhorn-tenants + annotations: + # Not the cluster default in Phase 1 — explicit opt-in only. + storageclass.kubernetes.io/is-default-class: "false" +provisioner: driver.longhorn.io +allowVolumeExpansion: true +reclaimPolicy: Delete +volumeBindingMode: Immediate +parameters: + numberOfReplicas: "{{ .Values.longhorn.replicas }}" + staleReplicaTimeout: "30" + fromBackup: "" + # fsType: ext4 is the default; explicit so the contract is in Git. + fsType: "ext4" +--- +# VolumeSnapshotClass — the API surface the Tower backend will +# consume in Phase 3 to take snapshots of source PVCs before +# spawn-env / Refresh ↓. +# +# `type: snap` (Longhorn's in-place snapshot) is what we want for +# the fast Clone path: the snapshot is a CoW reference, not an S3 +# upload. `type: bak` is the slower S3-bound block backup, used +# only by the daily DR layer. +apiVersion: snapshot.storage.k8s.io/v1 +kind: VolumeSnapshotClass +metadata: + name: longhorn-snapshot-class +driver: driver.longhorn.io +deletionPolicy: Delete +parameters: + type: snap +{{- end }} diff --git a/values.yaml b/values.yaml index add0e07..fc2a0af 100644 --- a/values.yaml +++ b/values.yaml @@ -112,3 +112,41 @@ registry: limits: cpu: 500m memory: 256Mi + +# longhorn — CSI block storage. See ADR 0003 (odooskyv3 monorepo) for +# the full design. Phase 1 (this commit): declared but disabled. +# Per-server enablement happens via the per-cluster Argo Application's +# helm.parameters (set `longhorn.enabled=true`). +# +# Host prerequisites (already satisfied on bootstrap.sh-Connect'd +# servers): `open-iscsi` package + `iscsi_tcp` kernel module + +# `iscsid` service. Servers provisioned out-of-band must run +# `apt-get install -y open-iscsi && modprobe iscsi_tcp && +# systemctl enable --now iscsid` before flipping enabled=true. +# +# When `longhorn.enabled=true`, the chart additionally renders: +# - StorageClass `longhorn-tenants` (replicaCount = .replicas) +# - VolumeSnapshotClass `longhorn-snapshot-class` for the future +# VolumeClone Refresh ↓ path +# Existing instances on `local-path` are unaffected — Longhorn +# co-exists, doesn't replace local-path. +longhorn: + enabled: false + # Replicas per Longhorn volume. Standard tier (single server) = + # 1 — durability story is hourly S3 backup, not local replicas. + # HA-Active sets this to 2 across the cluster's worker nodes. + replicas: 1 + # Default data path. k3s nodes get `/var/lib/longhorn` by default; + # production servers may want this on a separate disk for IOPS + # isolation from the OS root volume. + defaultDataPath: /var/lib/longhorn + # S3 backup target for Longhorn's own block-level backups (DR + # layer alongside Tower's application-level pg_dump path). When + # set, Longhorn writes block-incremental backups to this prefix + # daily. Empty = block-level backup disabled, application backup + # only. + backupTarget: "" + # Same S3 secret Tower's application backup already uses. + backupCredsSecret: + namespace: tenants + name: s3-backup-creds