diff --git a/apps/base/jellyfin/kustomization.yaml b/apps/base/jellyfin/kustomization.yaml index 1374887..e1b1262 100644 --- a/apps/base/jellyfin/kustomization.yaml +++ b/apps/base/jellyfin/kustomization.yaml @@ -20,8 +20,6 @@ resources: - statefulset.yaml - pdb.yaml - service.yaml - - redis-deployment.yaml - - redis-pvc.yaml - - redis-service.yaml + - valkey.yaml - gateway.yaml - httproute.yaml diff --git a/apps/base/jellyfin/redis-deployment.yaml b/apps/base/jellyfin/redis-deployment.yaml deleted file mode 100644 index eeae15b..0000000 --- a/apps/base/jellyfin/redis-deployment.yaml +++ /dev/null @@ -1,66 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: redis - namespace: jellyfin -spec: - replicas: 1 - selector: - matchLabels: - app: redis - strategy: - type: Recreate - template: - metadata: - labels: - app: redis - spec: - containers: - - name: redis - image: redis:7-alpine - imagePullPolicy: IfNotPresent - command: - - redis-server - - --save - - "20" - - "1" - ports: - - containerPort: 6379 - name: redis - protocol: TCP - livenessProbe: - exec: - command: - - redis-cli - - ping - failureThreshold: 3 - initialDelaySeconds: 30 - periodSeconds: 30 - successThreshold: 1 - timeoutSeconds: 5 - readinessProbe: - exec: - command: - - redis-cli - - ping - failureThreshold: 3 - initialDelaySeconds: 5 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - resources: - limits: - cpu: 500m - memory: 512Mi - requests: - cpu: 50m - memory: 128Mi - volumeMounts: - - mountPath: /data - name: data - restartPolicy: Always - volumes: - - name: data - persistentVolumeClaim: - claimName: jellyfin-redis-data diff --git a/apps/base/jellyfin/redis-pvc.yaml b/apps/base/jellyfin/redis-pvc.yaml deleted file mode 100644 index a6717ad..0000000 --- a/apps/base/jellyfin/redis-pvc.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: jellyfin-redis-data - namespace: jellyfin - annotations: - # Exclude from the jellyfin-config k8up Schedule (skipWithoutAnnotation is - # false cluster-wide, so unannotated PVCs are swept in). Redis holds only - # ephemeral transcode-lease state; RWO would also fail to mount while in use. - k8up.io/backup: "false" -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 5Gi - storageClassName: cephrbd-fast-delete - volumeMode: Filesystem diff --git a/apps/base/jellyfin/redis-service.yaml b/apps/base/jellyfin/redis-service.yaml deleted file mode 100644 index 6e0e34f..0000000 --- a/apps/base/jellyfin/redis-service.yaml +++ /dev/null @@ -1,17 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: redis - namespace: jellyfin -spec: - internalTrafficPolicy: Cluster - ports: - - name: redis - port: 6379 - protocol: TCP - targetPort: redis - selector: - app: redis - sessionAffinity: None - type: ClusterIP diff --git a/apps/base/jellyfin/statefulset.yaml b/apps/base/jellyfin/statefulset.yaml index 11fdbd4..273acc3 100644 --- a/apps/base/jellyfin/statefulset.yaml +++ b/apps/base/jellyfin/statefulset.yaml @@ -5,7 +5,7 @@ metadata: name: jellyfin namespace: jellyfin spec: - # HA: two replicas coordinate transcode session ownership through Redis and + # HA: two replicas coordinate transcode session ownership through Valkey and # resume each other's HLS segments off the shared RWX transcode PVC. Stable # pod names (jellyfin-0/1) are the lease owner identity, hence StatefulSet. replicas: 2 @@ -118,7 +118,7 @@ spec: containerPort: 8096 protocol: TCP env: - # Pod identity for the Redis transcode lease owner. The fork reads + # Pod identity for the Valkey transcode lease owner. The fork reads # JELLYFIN_INSTANCE_ID (falling back to MachineName); the stable # StatefulSet pod name gives each replica a unique lease identity so # takeover can target a dead replica. JELLYFIN_HA_POD_NAME is set for @@ -139,7 +139,7 @@ spec: value: /config/config # Distributed transcode session store (jellyfin-ha additions). - name: Jellyfin__TranscodeStore__RedisConnectionString - value: "redis:6379,abortConnect=false" + value: "valkey-jellyfin-valkey:6379,abortConnect=false" - name: Jellyfin__TranscodeStore__LeaseDurationSeconds value: "30" # PostgreSQL main DB via the CNPG-generated app secret, routed through diff --git a/apps/base/jellyfin/valkey.yaml b/apps/base/jellyfin/valkey.yaml new file mode 100644 index 0000000..bd018a3 --- /dev/null +++ b/apps/base/jellyfin/valkey.yaml @@ -0,0 +1,29 @@ +--- +# Single-instance Valkey managed by valkey-operator, replacing the self-managed +# redis Deployment as Jellyfin's distributed transcode-session store. shards:1 + +# replicas:0 is one primary with no replicas. This operator always runs Valkey +# cluster-mode-enabled with protected-mode off and leaves the built-in `default` +# user passwordless, so clients connect with no auth/TLS (parity with the old +# open redis); StackExchange.Redis auto-discovers the single node. HA (more +# shards/replicas) is a follow-up. Persistence is intentionally omitted so /data +# is an emptyDir: the lease state is ephemeral, and the operator-managed PVC +# cannot carry the k8up.io/backup:"false" annotation the namespace's cluster-wide +# k8up Schedule needs to skip an in-use RWO volume. +apiVersion: valkey.io/v1alpha1 +kind: ValkeyCluster +metadata: + name: jellyfin-valkey + namespace: jellyfin +spec: + shards: 1 + replicas: 0 + image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/valkey/valkey:9.0.0 + exporter: + enabled: false + resources: + requests: + cpu: 50m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi