From df3e66c5f9fe803e9663a9621f932ef22eb2d72d Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Thu, 6 Nov 2025 00:04:39 +0300 Subject: [PATCH 1/2] feat(probes): add startup probe for handling slow initial startup Add startupProbe to give Jellyfin sufficient time to start, especially with large media libraries or slow storage. This prevents Kubernetes from killing the pod during initial startup phase. Changes: - Add startupProbe configuration in values.yaml with sensible defaults - failureThreshold: 30 (allows up to 5 minutes for startup) - periodSeconds: 10 - Uses tcpSocket check on http port - Update deployment.yaml to include startupProbe from values - Bump chart version 2.5.0 -> 2.5.1 - Add changelog annotation for Artifact Hub Benefits: - Prevents pod restarts during slow initial startup (large media libraries) - Liveness and readiness probes remain responsive after successful startup - Fully configurable and can be disabled by setting startupProbe: null - No breaking changes, backward compatible The startup probe gives Jellyfin up to 5 minutes (30 attempts * 10 seconds) to complete initialization. After the first success, liveness and readiness probes take over with their normal timing. Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- charts/jellyfin/Chart.yaml | 6 +++++- charts/jellyfin/templates/deployment.yaml | 4 ++++ charts/jellyfin/values.yaml | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/charts/jellyfin/Chart.yaml b/charts/jellyfin/Chart.yaml index 96a351b..5fc2d25 100644 --- a/charts/jellyfin/Chart.yaml +++ b/charts/jellyfin/Chart.yaml @@ -8,5 +8,9 @@ keywords: - jellyfin - media - self-hosted -version: 2.5.0 +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 diff --git a/charts/jellyfin/templates/deployment.yaml b/charts/jellyfin/templates/deployment.yaml index c235001..2b4265f 100644 --- a/charts/jellyfin/templates/deployment.yaml +++ b/charts/jellyfin/templates/deployment.yaml @@ -108,6 +108,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/values.yaml b/charts/jellyfin/values.yaml index 068c0ef..f5d4bf1 100644 --- a/charts/jellyfin/values.yaml +++ b/charts/jellyfin/values.yaml @@ -133,7 +133,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). livenessProbe: initialDelaySeconds: 10 tcpSocket: @@ -144,6 +157,7 @@ livenessProbe: # periodSeconds: 10 # -- Configure readiness probe for Jellyfin. +# This probe is disabled during startup (startup probe handles initial checks). readinessProbe: initialDelaySeconds: 10 tcpSocket: From 916087f1de1c7ccbd428cac9b53c79ca6ff651c2 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Fri, 7 Nov 2025 19:56:02 +0300 Subject: [PATCH 2/2] test(probes): add startup probe tests and deployment notes Add helm-unittest tests for startup probe: - Default configuration verification (tcpSocket, timing) - Custom timing parameters (initialDelaySeconds, periodSeconds, failureThreshold) - Alternative probe types (httpGet) - Custom port support - Timeout window calculation Add NOTES.txt with startup probe information: - Display max startup time calculation - Explain startup probe purpose for large libraries - Warning for very long startup timeouts Tests ensure startup probe works correctly for slow initial startup scenarios. Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- charts/jellyfin/templates/NOTES.txt | 40 ++++++++ charts/jellyfin/tests/startup_probe_test.yaml | 92 +++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 charts/jellyfin/templates/NOTES.txt create mode 100644 charts/jellyfin/tests/startup_probe_test.yaml diff --git a/charts/jellyfin/templates/NOTES.txt b/charts/jellyfin/templates/NOTES.txt new file mode 100644 index 0000000..dbe92dc --- /dev/null +++ b/charts/jellyfin/templates/NOTES.txt @@ -0,0 +1,40 @@ +Thank you for installing {{ .Chart.Name }}. + +Your release is named {{ .Release.Name }}. + +To learn more about the release, try: + + $ helm status {{ .Release.Name }} + $ helm get all {{ .Release.Name }} + +{{- if .Values.ingress.enabled }} + +Jellyfin is available via Ingress at: +{{- range .Values.ingress.hosts }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ .host }}{{ (index .paths 0).path }} +{{- end }} +{{- else }} + +To access Jellyfin, you can use port-forwarding: + + $ kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ include "jellyfin.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }} + +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 }} +{{- end }} 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)