diff --git a/charts/jellyfin/Chart.yaml b/charts/jellyfin/Chart.yaml index 4a1c6b3..16a7eee 100644 --- a/charts/jellyfin/Chart.yaml +++ b/charts/jellyfin/Chart.yaml @@ -12,6 +12,8 @@ version: 2.5.1 appVersion: 10.11.2 annotations: artifacthub.io/changes: | + - kind: added + description: Add startup probe to prevent pod restarts during slow initial startup with large media libraries - kind: added description: Add persistence.cache configuration for dedicated cache volume support - kind: added diff --git a/charts/jellyfin/templates/NOTES.txt b/charts/jellyfin/templates/NOTES.txt index ccba928..1f2f807 100644 --- a/charts/jellyfin/templates/NOTES.txt +++ b/charts/jellyfin/templates/NOTES.txt @@ -22,6 +22,21 @@ To access Jellyfin, you can use port-forwarding: Then visit http://localhost:{{ .Values.service.port }} in your browser. {{- end }} +{{- if .Values.startupProbe }} +{{- $startupTimeout := mul (default 10 .Values.startupProbe.periodSeconds) (default 30 .Values.startupProbe.failureThreshold) }} + +Startup Configuration: + Startup Probe: Enabled + Max Startup Time: {{ $startupTimeout }}s ({{ div $startupTimeout 60 }} minutes) + + The startup probe gives Jellyfin enough time to initialize, especially + with large media libraries. After startup succeeds, liveness and + readiness probes take over for health monitoring. + + {{- if gt $startupTimeout 600 }} + ⚠ NOTE: Startup timeout is very long ({{ div $startupTimeout 60 }}+ minutes). + Consider optimizing your media library or reducing failureThreshold. + {{- end }} Persistence Configuration: Config: {{ if .Values.persistence.config.enabled }}{{ .Values.persistence.config.type | default "pvc" }}{{ if .Values.persistence.config.existingClaim }} (existing: {{ .Values.persistence.config.existingClaim }}){{ end }}{{ else }}emptyDir{{ end }} Media: {{ if .Values.persistence.media.enabled }}{{ .Values.persistence.media.type | default "pvc" }}{{ if .Values.persistence.media.existingClaim }} (existing: {{ .Values.persistence.media.existingClaim }}){{ end }}{{ else }}emptyDir{{ end }} diff --git a/charts/jellyfin/templates/deployment.yaml b/charts/jellyfin/templates/deployment.yaml index db0b023..a36d5e0 100644 --- a/charts/jellyfin/templates/deployment.yaml +++ b/charts/jellyfin/templates/deployment.yaml @@ -111,6 +111,10 @@ spec: hostPort: 1900 protocol: UDP {{- end }} + {{- with .Values.startupProbe }} + startupProbe: + {{- toYaml . | nindent 12 }} + {{- end }} livenessProbe: {{- toYaml .Values.livenessProbe | nindent 12 }} readinessProbe: diff --git a/charts/jellyfin/tests/startup_probe_test.yaml b/charts/jellyfin/tests/startup_probe_test.yaml new file mode 100644 index 0000000..ee7430f --- /dev/null +++ b/charts/jellyfin/tests/startup_probe_test.yaml @@ -0,0 +1,92 @@ +suite: test startup probe +templates: + - deployment.yaml +tests: + - it: should have startup probe by default + asserts: + - isNotNull: + path: spec.template.spec.containers[0].startupProbe + + - it: should use tcpSocket by default + asserts: + - isNotNull: + path: spec.template.spec.containers[0].startupProbe.tcpSocket + - equal: + path: spec.template.spec.containers[0].startupProbe.tcpSocket.port + value: http + + - it: should have default timing values + asserts: + - equal: + path: spec.template.spec.containers[0].startupProbe.initialDelaySeconds + value: 0 + - equal: + path: spec.template.spec.containers[0].startupProbe.periodSeconds + value: 10 + - equal: + path: spec.template.spec.containers[0].startupProbe.failureThreshold + value: 30 + + - it: should allow custom initialDelaySeconds + set: + startupProbe.initialDelaySeconds: 5 + asserts: + - equal: + path: spec.template.spec.containers[0].startupProbe.initialDelaySeconds + value: 5 + + - it: should allow custom periodSeconds + set: + startupProbe.periodSeconds: 15 + asserts: + - equal: + path: spec.template.spec.containers[0].startupProbe.periodSeconds + value: 15 + + - it: should allow custom failureThreshold + set: + startupProbe.failureThreshold: 60 + asserts: + - equal: + path: spec.template.spec.containers[0].startupProbe.failureThreshold + value: 60 + + - it: should support httpGet probe + set: + startupProbe: + httpGet: + path: /health + port: http + initialDelaySeconds: 0 + periodSeconds: 10 + failureThreshold: 30 + asserts: + - isNotNull: + path: spec.template.spec.containers[0].startupProbe.httpGet + - equal: + path: spec.template.spec.containers[0].startupProbe.httpGet.path + value: /health + - equal: + path: spec.template.spec.containers[0].startupProbe.httpGet.port + value: http + + - it: should support custom port + set: + startupProbe.tcpSocket.port: 9000 + asserts: + - equal: + path: spec.template.spec.containers[0].startupProbe.tcpSocket.port + value: 9000 + + - it: should calculate correct timeout window + set: + startupProbe.periodSeconds: 10 + startupProbe.failureThreshold: 30 + asserts: + - equal: + path: spec.template.spec.containers[0].startupProbe.periodSeconds + value: 10 + - equal: + path: spec.template.spec.containers[0].startupProbe.failureThreshold + value: 30 + # Total startup time allowed: 10 * 30 = 300 seconds (5 minutes) diff --git a/charts/jellyfin/values.yaml b/charts/jellyfin/values.yaml index 916e65e..8508198 100644 --- a/charts/jellyfin/values.yaml +++ b/charts/jellyfin/values.yaml @@ -148,7 +148,20 @@ resources: {} # cpu: 100m # memory: 128Mi +# -- Configure startup probe for Jellyfin. +# This probe gives Jellyfin enough time to start, especially with large media libraries. +# After the startup probe succeeds once, liveness and readiness probes take over. +startupProbe: + tcpSocket: + port: http + initialDelaySeconds: 0 + periodSeconds: 10 + failureThreshold: 30 + # With these defaults, Jellyfin has up to 5 minutes (30 * 10s) to start. + # Adjust failureThreshold if you have very large media libraries or slow storage. + # -- Configure liveness probe for Jellyfin. +# This probe is disabled during startup (startup probe handles initial checks). # Uses httpGet for compatibility with both IPv4 and IPv6. livenessProbe: httpGet: @@ -161,6 +174,7 @@ livenessProbe: # periodSeconds: 10 # -- Configure readiness probe for Jellyfin. +# This probe is disabled during startup (startup probe handles initial checks). # Uses httpGet for compatibility with both IPv4 and IPv6. readinessProbe: httpGet: