summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-10 10:57:44 +0300
committerPaul Buetow <paul@buetow.org>2026-05-10 10:57:44 +0300
commitcd837ea69dc4afe69d48c0f33b3011a8023996d1 (patch)
treee1a5a395af36691021dd18defdd3d0061d19b207
parent19f8e01ac35aeca761e08a74c087d62b78c8c021 (diff)
navidrome: move /data PVC from NFS to local-path on r1
SQLite over NFS causes two problems: file-lock races on rolling restarts (fixed with Recreate strategy but underlying fragility remains), and 19s image-cache init at startup due to stunnel TLS latency on every cache read. Replace navidrome-data-pv/pvc (static hostPath over NFS at /data/nfs/k3svolumes/navidrome/data) with a dynamic local-path PVC provisioned on r1 (/var/lib/rancher/k3s/storage). Pin the deployment to r1 via nodeSelector so the local PV is always reachable. Existing DB and cache migrated: navidrome.db (23 MB), image/background/ plugin caches (~118 MB) copied via a migration pod before first start. Result: startupTime=41ms (was ~20s), Image cache init=29ms (was ~19s). Music PVC stays on NFS (200 GB library, unchanged). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--f3s/navidrome/helm-chart/templates/deployment.yaml8
-rw-r--r--f3s/navidrome/helm-chart/templates/persistent-volume.yaml34
2 files changed, 25 insertions, 17 deletions
diff --git a/f3s/navidrome/helm-chart/templates/deployment.yaml b/f3s/navidrome/helm-chart/templates/deployment.yaml
index 5a3862e..d85bb47 100644
--- a/f3s/navidrome/helm-chart/templates/deployment.yaml
+++ b/f3s/navidrome/helm-chart/templates/deployment.yaml
@@ -18,6 +18,12 @@ spec:
labels:
app: navidrome
spec:
+ # Pin to r1 so the local-path PVC (which lives on r1's disk at
+ # /var/lib/rancher/k3s/storage) is always reachable. Without this, if
+ # the pod reschedules to a different node it would not find the data
+ # volume and Navidrome would start with an empty DB.
+ nodeSelector:
+ kubernetes.io/hostname: r1.lan.buetow.org
containers:
- name: navidrome
image: deluan/navidrome:latest
@@ -34,7 +40,7 @@ spec:
httpGet:
path: /ping
port: 4533
- # Allow up to 5 min for cold start (NFS cache warm-up, scan, etc.)
+ # Allow up to 5 min for cold start (DB open, first scan, etc.)
initialDelaySeconds: 15
periodSeconds: 5
timeoutSeconds: 3
diff --git a/f3s/navidrome/helm-chart/templates/persistent-volume.yaml b/f3s/navidrome/helm-chart/templates/persistent-volume.yaml
index 960bee3..3ca2867 100644
--- a/f3s/navidrome/helm-chart/templates/persistent-volume.yaml
+++ b/f3s/navidrome/helm-chart/templates/persistent-volume.yaml
@@ -1,31 +1,33 @@
-apiVersion: v1
-kind: PersistentVolume
-metadata:
- name: navidrome-data-pv
-spec:
- capacity:
- storage: 10Gi
- volumeMode: Filesystem
- accessModes:
- - ReadWriteOnce
- persistentVolumeReclaimPolicy: Retain
- hostPath:
- path: /data/nfs/k3svolumes/navidrome/data
- type: Directory
----
+# navidrome-data: local-path PVC (dynamic provisioning).
+# The SQLite DB, image cache, and artwork cache must NOT live on NFS because:
+# 1. SQLite file-lock semantics are fragile over NFS: under concurrent
+# access (e.g. rolling restart) the new pod blocks on fcntl() until
+# the old pod fully releases its locks.
+# 2. Every image/background cache read traverses the stunnel TLS tunnel,
+# adding latency to every UI thumbnail and a 19 s "Image cache" init
+# at startup.
+# The local-path storageClass provisions a directory on the node's own disk
+# (/var/lib/rancher/k3s/storage), eliminating both problems. The deployment
+# pins the pod to r1 via nodeSelector so the local PV is always reachable.
+# Trade-off: if r1 is down and the pod reschedules, it starts with a fresh
+# DB (loses play counts / scrobble queue) — acceptable for a home server.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: navidrome-data-pvc
namespace: services
spec:
- storageClassName: ""
+ # local-path is the k3s default dynamic provisioner; WaitForFirstConsumer
+ # means the PV is created on the node where the pod is first scheduled.
+ storageClassName: local-path
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
+# navidrome-music: keep on NFS — 200 GB library shared across nodes.
+# This is a static PV backed by hostPath at the NFS mount point.
apiVersion: v1
kind: PersistentVolume
metadata: