From 78d78973c5048220d0da958e8b4f794f1794568c Mon Sep 17 00:00:00 2001 From: jklein Date: Fri, 21 Aug 2026 17:36:53 +0200 Subject: [PATCH 1/3] Ensure liveness, readiness and startup probes on all workloads Every container in every Deployment/StatefulSet now defines all three probes. The paperless-ngx consume CronJob intentionally has none (batch workload). - Add probes: apache-tika, calibre-web-automated, cyberchef, gotenberg, homeassistant, patchmon-backend, samba (tcp/445), teamspeak-server (tcp/30033), zipline (/api/healthcheck) - Fix voucher-vault null probe values with real defaults - Fix startup-probe semantics in template-chart and rallly (no initialDelaySeconds, generous failureThreshold) - Switch outline probes to its /_health endpoint - Add readiness/startup probes to satisfactory - Add startup probes to matrix-synapse, matrix-delegation-nginx, paperless-server, patchmon-frontend, urlaubsverwaltung - Major version bump for all published charts --- apache-tika/Chart.yaml | 2 +- apache-tika/templates/deployment.yaml | 6 +++++ apache-tika/values.yaml | 23 ++++++++++++++++ calibre-web-automated/Chart.yaml | 2 +- .../templates/calibre-web-automated.sfs.yaml | 6 +++++ calibre-web-automated/values.yaml | 22 +++++++++++++++ cyberchef/Chart.yaml | 2 +- cyberchef/templates/cyberchef.deployment.yaml | 7 ++++- cyberchef/values.yaml | 22 +++++++++++++++ gotenberg/Chart.yaml | 2 +- gotenberg/templates/deployment.yaml | 6 +++++ gotenberg/values.yaml | 23 ++++++++++++++++ homeassistant/Chart.yaml | 2 +- .../templates/homeassistant.sfs.yaml | 7 ++++- homeassistant/values.yaml | 17 +++++++++++- matrix-synapse/Chart.yaml | 2 +- .../matrix-delegation-nginx.deployment.yaml | 11 ++++++-- .../templates/matrix-synapse.sfs.yaml | 12 +++++++-- outline/Chart.yaml | 2 +- outline/templates/outline.sfs.yaml | 21 ++++++++++++--- paperless-ngx/Chart.yaml | 2 +- .../templates/paperless-server.sfs.yaml | 11 ++++++-- patchmon/Chart.yaml | 2 +- .../patchmon-backend.deployment.yaml | 25 ++++++++++++++++- .../patchmon-frontend.deployment.yaml | 10 +++++-- rallly/Chart.yaml | 2 +- rallly/values.yaml | 9 +++---- samba/Chart.yaml | 2 +- samba/templates/samba.sfs.yaml | 6 +++++ samba/values.yaml | 20 ++++++++++++++ satisfactory/Chart.yaml | 2 +- .../templates/satisfactory-server.sfs.yaml | 20 +++++++++++++- teamspeak-server/Chart.yaml | 2 +- .../templates/teamspeak-server.sfs.yaml | 21 +++++++++++++++ template-chart/values.yaml | 9 +++---- urlaubsverwaltung/Chart.yaml | 2 +- .../urlaubsverwaltung.deployment.yaml | 11 ++++++-- voucher-vault/Chart.yaml | 2 +- voucher-vault/values.yaml | 27 ++++++++++++++++--- zipline/Chart.yaml | 2 +- zipline/templates/zipline.sfs.yaml | 6 +++++ zipline/values.yaml | 25 +++++++++++++++++ 42 files changed, 366 insertions(+), 49 deletions(-) diff --git a/apache-tika/Chart.yaml b/apache-tika/Chart.yaml index 7d67e2a..7582189 100644 --- a/apache-tika/Chart.yaml +++ b/apache-tika/Chart.yaml @@ -4,5 +4,5 @@ description: A Helm chart to deploy Apache Tika on Kubernetes type: application -version: 4.0.1+up3.2.3.0.full +version: 5.0.0+up3.2.3.0.full appVersion: "3.2.3.0-full" diff --git a/apache-tika/templates/deployment.yaml b/apache-tika/templates/deployment.yaml index cf1b18a..7bb5edc 100644 --- a/apache-tika/templates/deployment.yaml +++ b/apache-tika/templates/deployment.yaml @@ -24,6 +24,12 @@ spec: - containerPort: 9998 protocol: TCP name: tika-port + livenessProbe: + {{- toYaml .Values.tika.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.tika.readinessProbe | nindent 12 }} + startupProbe: + {{- toYaml .Values.tika.startupProbe | nindent 12 }} resources: requests: memory: "{{ .Values.tika.resources.requests.memory }}" diff --git a/apache-tika/values.yaml b/apache-tika/values.yaml index 9d77d1b..f9dfbe4 100644 --- a/apache-tika/values.yaml +++ b/apache-tika/values.yaml @@ -1,4 +1,27 @@ tika: + # Tika answers "GET /" on its server port with HTTP 200. + livenessProbe: + httpGet: + path: / + port: tika-port + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: / + port: tika-port + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Startup budget = 5s * 30 = 150s. + startupProbe: + httpGet: + path: / + port: tika-port + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 30 resources: requests: cpu: 0.1 diff --git a/calibre-web-automated/Chart.yaml b/calibre-web-automated/Chart.yaml index 049fd55..28bf81e 100644 --- a/calibre-web-automated/Chart.yaml +++ b/calibre-web-automated/Chart.yaml @@ -4,7 +4,7 @@ type: application name: calibre-web-automated description: A Helm chart to deploy calibere-web-automated -version: 1.3.0+upv4.0.6 +version: 2.0.0+upv4.0.6 appVersion: v4.0.6 maintainers: diff --git a/calibre-web-automated/templates/calibre-web-automated.sfs.yaml b/calibre-web-automated/templates/calibre-web-automated.sfs.yaml index d815230..e33df54 100644 --- a/calibre-web-automated/templates/calibre-web-automated.sfs.yaml +++ b/calibre-web-automated/templates/calibre-web-automated.sfs.yaml @@ -54,6 +54,12 @@ spec: subPath: customize.py.json - mountPath: "/cwa-book-ingest" name: cwa-consume + livenessProbe: + {{- toYaml .Values.cwa.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.cwa.readinessProbe | nindent 12 }} + startupProbe: + {{- toYaml .Values.cwa.startupProbe | nindent 12 }} resources: requests: memory: "{{ .Values.cwa.resources.requests.memory }}" diff --git a/calibre-web-automated/values.yaml b/calibre-web-automated/values.yaml index e5fce1b..9b87836 100644 --- a/calibre-web-automated/values.yaml +++ b/calibre-web-automated/values.yaml @@ -6,6 +6,28 @@ cwa: storageClass: longhorn timezone: "UTC" maxUploadFileSize: "10m" + livenessProbe: + httpGet: + path: / + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: / + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Startup budget = 10s * 30 = 300s. + startupProbe: + httpGet: + path: / + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 resources: requests: cpu: 0.1 diff --git a/cyberchef/Chart.yaml b/cyberchef/Chart.yaml index d1ea12c..28b8e67 100644 --- a/cyberchef/Chart.yaml +++ b/cyberchef/Chart.yaml @@ -4,7 +4,7 @@ description: A Helm chart to deploy Cyberchef on Kubernetes type: application -version: 1.0.0+up10.22.1 +version: 2.0.0+up10.22.1 appVersion: "10.22.1" maintainers: diff --git a/cyberchef/templates/cyberchef.deployment.yaml b/cyberchef/templates/cyberchef.deployment.yaml index 4833e69..324e8d3 100644 --- a/cyberchef/templates/cyberchef.deployment.yaml +++ b/cyberchef/templates/cyberchef.deployment.yaml @@ -20,11 +20,16 @@ spec: - name: {{ .Release.Name }}-{{ .Chart.Name }}-deployment image: "ghcr.io/gchq/cyberchef:{{ .Chart.AppVersion }}" imagePullPolicy: IfNotPresent - # TODO: liveness and readiness probes ports: - containerPort: 80 protocol: TCP name: http + livenessProbe: + {{- toYaml .Values.cyberchef.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.cyberchef.readinessProbe | nindent 12 }} + startupProbe: + {{- toYaml .Values.cyberchef.startupProbe | nindent 12 }} resources: requests: memory: "{{ .Values.cyberchef.resources.requests.memory }}" diff --git a/cyberchef/values.yaml b/cyberchef/values.yaml index ac44f32..35f183c 100644 --- a/cyberchef/values.yaml +++ b/cyberchef/values.yaml @@ -1,4 +1,26 @@ cyberchef: + livenessProbe: + httpGet: + path: / + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: / + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Startup budget = 5s * 30 = 150s. + startupProbe: + httpGet: + path: / + port: http + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 30 resources: requests: cpu: 0.1 diff --git a/gotenberg/Chart.yaml b/gotenberg/Chart.yaml index 86b785f..504809a 100644 --- a/gotenberg/Chart.yaml +++ b/gotenberg/Chart.yaml @@ -4,7 +4,7 @@ description: A Helm chart to deploy Gotenberg on Kubernetes type: application -version: 1.0.2+up8.26.0 +version: 2.0.0+up8.26.0 appVersion: "8.26.0" maintainers: diff --git a/gotenberg/templates/deployment.yaml b/gotenberg/templates/deployment.yaml index 73122eb..b4a6c1f 100644 --- a/gotenberg/templates/deployment.yaml +++ b/gotenberg/templates/deployment.yaml @@ -24,6 +24,12 @@ spec: - containerPort: 3000 protocol: TCP name: gotenberg-port + livenessProbe: + {{- toYaml .Values.gotenberg.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.gotenberg.readinessProbe | nindent 12 }} + startupProbe: + {{- toYaml .Values.gotenberg.startupProbe | nindent 12 }} resources: requests: memory: "{{ .Values.gotenberg.resources.requests.memory }}" diff --git a/gotenberg/values.yaml b/gotenberg/values.yaml index 166dc06..8b41ad5 100644 --- a/gotenberg/values.yaml +++ b/gotenberg/values.yaml @@ -1,4 +1,27 @@ gotenberg: + # Gotenberg exposes a documented health endpoint at /health. + livenessProbe: + httpGet: + path: /health + port: gotenberg-port + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: gotenberg-port + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Startup budget = 5s * 30 = 150s. + startupProbe: + httpGet: + path: /health + port: gotenberg-port + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 30 resources: requests: cpu: 0.1 diff --git a/homeassistant/Chart.yaml b/homeassistant/Chart.yaml index f8606ab..a9abdb0 100644 --- a/homeassistant/Chart.yaml +++ b/homeassistant/Chart.yaml @@ -3,7 +3,7 @@ name: homeassistant description: A Helm chart to deploy Home Assistant on Kubernetes type: application -version: 1.4.2+up2026.2.3 +version: 2.0.0+up2026.2.3 appVersion: "2026.2.3" diff --git a/homeassistant/templates/homeassistant.sfs.yaml b/homeassistant/templates/homeassistant.sfs.yaml index 366440c..d7bce3f 100644 --- a/homeassistant/templates/homeassistant.sfs.yaml +++ b/homeassistant/templates/homeassistant.sfs.yaml @@ -28,7 +28,12 @@ spec: - name: http containerPort: 8123 protocol: TCP - # TODO: liveness-probe, readiness-probe + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + startupProbe: + {{- toYaml .Values.startupProbe | nindent 12 }} resources: limits: cpu: {{ .Values.resources.limits.cpu }} diff --git a/homeassistant/values.yaml b/homeassistant/values.yaml index 217fe79..7a151af 100644 --- a/homeassistant/values.yaml +++ b/homeassistant/values.yaml @@ -32,15 +32,30 @@ resources: memory: 512Mi ephemeralStorage: 128Mi -# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ +# This is to setup the liveness, readiness and startup probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ livenessProbe: httpGet: path: / port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 readinessProbe: httpGet: path: / port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 +# The startup probe gates liveness/readiness. Home Assistant can take a while to +# start up, so grant a generous budget: 10s * 30 = 300s. +startupProbe: + httpGet: + path: / + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 # Additional volumes on the output Deployment definition. volumes: [] diff --git a/matrix-synapse/Chart.yaml b/matrix-synapse/Chart.yaml index 28197e6..576c6d4 100644 --- a/matrix-synapse/Chart.yaml +++ b/matrix-synapse/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: matrix-synapse description: A Helm chart to deploy a Matrix Synapse server on Kubernetes type: application -version: 1.2.1+upv1.149.1 +version: 2.0.0+upv1.149.1 appVersion: "v1.149.1" maintainers: - name: jklein \ No newline at end of file diff --git a/matrix-synapse/templates/matrix-delegation-nginx.deployment.yaml b/matrix-synapse/templates/matrix-delegation-nginx.deployment.yaml index 8a0090d..02f3a31 100644 --- a/matrix-synapse/templates/matrix-delegation-nginx.deployment.yaml +++ b/matrix-synapse/templates/matrix-delegation-nginx.deployment.yaml @@ -40,7 +40,6 @@ spec: path: /.well-known/matrix/server port: http scheme: HTTP - initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 @@ -49,10 +48,18 @@ spec: path: /.well-known/matrix/server port: http scheme: HTTP - initialDelaySeconds: 15 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 + # The startup probe gates liveness/readiness. Startup budget = 5s * 30 = 150s. + startupProbe: + httpGet: + path: /.well-known/matrix/server + port: http + scheme: HTTP + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 30 volumes: - name: nginx-config configMap: diff --git a/matrix-synapse/templates/matrix-synapse.sfs.yaml b/matrix-synapse/templates/matrix-synapse.sfs.yaml index 8f27e0e..e27ea00 100644 --- a/matrix-synapse/templates/matrix-synapse.sfs.yaml +++ b/matrix-synapse/templates/matrix-synapse.sfs.yaml @@ -43,7 +43,6 @@ spec: path: /health port: http scheme: HTTP - initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 @@ -52,10 +51,19 @@ spec: path: /health port: http scheme: HTTP - initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 + # The startup probe gates liveness/readiness. Synapse can take a + # while to start (migrations, cache warmup): budget 10s * 30 = 300s. + startupProbe: + httpGet: + path: /health + port: http + scheme: HTTP + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 resources: requests: memory: "{{ .Values.matrix.resources.requests.memory }}" diff --git a/outline/Chart.yaml b/outline/Chart.yaml index ec60d71..9f2d692 100644 --- a/outline/Chart.yaml +++ b/outline/Chart.yaml @@ -4,7 +4,7 @@ description: A Helm chart to deploy Outline on Kubernetes type: application -version: 1.4.0+up1.9.2 +version: 2.0.0+up1.9.2 appVersion: 1.9.2 maintainers: diff --git a/outline/templates/outline.sfs.yaml b/outline/templates/outline.sfs.yaml index 5af7bd9..fb8201a 100644 --- a/outline/templates/outline.sfs.yaml +++ b/outline/templates/outline.sfs.yaml @@ -80,18 +80,31 @@ spec: - containerPort: 3000 protocol: TCP name: http + # Outline exposes a dedicated health endpoint at /_health + # (also used by the upstream Docker HEALTHCHECK). livenessProbe: httpGet: - path: / + path: /_health port: 3000 - initialDelaySeconds: 30 periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 readinessProbe: httpGet: - path: / + path: /_health port: 3000 - initialDelaySeconds: 10 periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Outline runs database + # migrations on startup: budget 10s * 30 = 300s. + startupProbe: + httpGet: + path: /_health + port: 3000 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 resources: requests: memory: "{{ .Values.outline.resources.requests.memory }}" diff --git a/paperless-ngx/Chart.yaml b/paperless-ngx/Chart.yaml index 8baeb7e..ba4b268 100644 --- a/paperless-ngx/Chart.yaml +++ b/paperless-ngx/Chart.yaml @@ -4,7 +4,7 @@ description: A Helm chart to deploy Paperless-NGX on Kubernetes type: application -version: 4.4.1+up2.20.13 +version: 5.0.0+up2.20.13 appVersion: 2.20.13 diff --git a/paperless-ngx/templates/paperless-server.sfs.yaml b/paperless-ngx/templates/paperless-server.sfs.yaml index 238ac3a..b957e76 100644 --- a/paperless-ngx/templates/paperless-server.sfs.yaml +++ b/paperless-ngx/templates/paperless-server.sfs.yaml @@ -166,7 +166,6 @@ spec: httpGet: path: / port: 8000 - initialDelaySeconds: 30 periodSeconds: 10 failureThreshold: 3 successThreshold: 1 @@ -175,11 +174,19 @@ spec: httpGet: path: / port: 8000 - initialDelaySeconds: 90 periodSeconds: 30 failureThreshold: 3 successThreshold: 1 timeoutSeconds: 5 + # The startup probe gates liveness/readiness. Paperless runs database + # migrations and index checks on startup: budget 10s * 30 = 300s. + startupProbe: + httpGet: + path: / + port: 8000 + periodSeconds: 10 + failureThreshold: 30 + timeoutSeconds: 5 restartPolicy: Always volumes: - name: paperless-volume diff --git a/patchmon/Chart.yaml b/patchmon/Chart.yaml index 6eab791..b7e01fc 100644 --- a/patchmon/Chart.yaml +++ b/patchmon/Chart.yaml @@ -4,7 +4,7 @@ description: A Helm chart to deploy Patchmon on Kubernetes type: application -version: 1.4.0+up1.4.2 +version: 2.0.0+up1.4.2 appVersion: "1.4.2" maintainers: diff --git a/patchmon/templates/patchmon-backend.deployment.yaml b/patchmon/templates/patchmon-backend.deployment.yaml index b968a09..bd8abf6 100644 --- a/patchmon/templates/patchmon-backend.deployment.yaml +++ b/patchmon/templates/patchmon-backend.deployment.yaml @@ -135,7 +135,30 @@ spec: value: "https://{{ .Values.ingress.domain }}" - name: TRUST_PROXIES value: "1" - # TODO: Add liveness and readiness probes + # The backend exposes GET /health returning {"status": "ok"}. + livenessProbe: + httpGet: + path: /health + port: 3001 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 3001 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. The backend waits for + # the database and runs migrations on startup: budget 10s * 30 = 300s. + startupProbe: + httpGet: + path: /health + port: 3001 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 {{- with .Values.patchmon.backend.resources }} resources: {{ toYaml . | nindent 12 }} diff --git a/patchmon/templates/patchmon-frontend.deployment.yaml b/patchmon/templates/patchmon-frontend.deployment.yaml index a89df53..d8938b4 100644 --- a/patchmon/templates/patchmon-frontend.deployment.yaml +++ b/patchmon/templates/patchmon-frontend.deployment.yaml @@ -37,7 +37,6 @@ spec: httpGet: path: / port: 3000 - initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 @@ -45,10 +44,17 @@ spec: httpGet: path: / port: 3000 - initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 + # The startup probe gates liveness/readiness. Startup budget = 5s * 30 = 150s. + startupProbe: + httpGet: + path: / + port: 3000 + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 30 volumeMounts: - name: patchmon-volume mountPath: /usr/share/nginx/html/assets diff --git a/rallly/Chart.yaml b/rallly/Chart.yaml index 784fe26..ae56f50 100644 --- a/rallly/Chart.yaml +++ b/rallly/Chart.yaml @@ -4,7 +4,7 @@ description: A Helm chart to deploy Rallly on Kubernetes type: application -version: 1.1.1+up4.8.1 +version: 2.0.0+up4.8.1 appVersion: "4.8.1" maintainers: diff --git a/rallly/values.yaml b/rallly/values.yaml index ccb5855..db62bc8 100644 --- a/rallly/values.yaml +++ b/rallly/values.yaml @@ -27,7 +27,6 @@ rallly: httpGet: path: / port: http - initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 @@ -35,18 +34,18 @@ rallly: httpGet: path: / port: http - initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 + # The startup probe gates liveness/readiness, so those need no initialDelaySeconds. + # Startup budget = periodSeconds * failureThreshold = 150s. startupProbe: httpGet: path: / port: http - initialDelaySeconds: 30 - periodSeconds: 10 + periodSeconds: 5 timeoutSeconds: 5 - failureThreshold: 3 + failureThreshold: 30 ingress: clusterIssuer: null diff --git a/samba/Chart.yaml b/samba/Chart.yaml index 8e83f16..9c405a5 100644 --- a/samba/Chart.yaml +++ b/samba/Chart.yaml @@ -4,6 +4,6 @@ description: A Helm chart for Samba type: application -version: 1.2.0+up4.23.5 +version: 2.0.0+up4.23.5 appVersion: 4.23.5 diff --git a/samba/templates/samba.sfs.yaml b/samba/templates/samba.sfs.yaml index 3ee24de..96ae9a9 100644 --- a/samba/templates/samba.sfs.yaml +++ b/samba/templates/samba.sfs.yaml @@ -39,6 +39,12 @@ spec: - name: "{{ $value.name }}" mountPath: "/shares/{{ $value.name }}" {{- end }} + livenessProbe: + {{- toYaml .Values.samba.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.samba.readinessProbe | nindent 12 }} + startupProbe: + {{- toYaml .Values.samba.startupProbe | nindent 12 }} resources: requests: memory: "{{ .Values.samba.resources.requests.memory }}" diff --git a/samba/values.yaml b/samba/values.yaml index 1a3b16c..7de4f2c 100644 --- a/samba/values.yaml +++ b/samba/values.yaml @@ -7,6 +7,26 @@ samba: validUsers: null description: null size: null + # SMB is not an HTTP protocol, so probe the main SMB TCP port. + livenessProbe: + tcpSocket: + port: 445 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + tcpSocket: + port: 445 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Startup budget = 5s * 30 = 150s. + startupProbe: + tcpSocket: + port: 445 + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 30 resources: requests: memory: 50Mi diff --git a/satisfactory/Chart.yaml b/satisfactory/Chart.yaml index 3492955..82e9076 100644 --- a/satisfactory/Chart.yaml +++ b/satisfactory/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: satisfactory description: A Helm chart to deploy a Satisfactory Gameserver on Kubernetes type: application -version: 1.3.0+upv1.9.10 +version: 2.0.0+upv1.9.10 appVersion: "v1.9.10" maintainers: - name: jklein \ No newline at end of file diff --git a/satisfactory/templates/satisfactory-server.sfs.yaml b/satisfactory/templates/satisfactory-server.sfs.yaml index 289c081..2dc10f1 100644 --- a/satisfactory/templates/satisfactory-server.sfs.yaml +++ b/satisfactory/templates/satisfactory-server.sfs.yaml @@ -52,10 +52,28 @@ spec: - "/bin/sh" - "-c" - "/home/steam/healthcheck.sh" - initialDelaySeconds: 300 failureThreshold: 4 successThreshold: 1 periodSeconds: 30 + timeoutSeconds: 10 + readinessProbe: + tcpSocket: + port: api + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. The server downloads / + # updates the game files via Steam on startup, which can take a long + # time: budget 30s * 40 = 20 minutes. + startupProbe: + exec: + command: + - "/bin/sh" + - "-c" + - "/home/steam/healthcheck.sh" + periodSeconds: 30 + timeoutSeconds: 10 + failureThreshold: 40 {{- with .Values.server.resources }} resources: {{ toYaml . | nindent 12 }} diff --git a/teamspeak-server/Chart.yaml b/teamspeak-server/Chart.yaml index 456f92f..cb35711 100644 --- a/teamspeak-server/Chart.yaml +++ b/teamspeak-server/Chart.yaml @@ -4,5 +4,5 @@ description: A Helm chart for deploying a teamspeak-server on Kubernetes type: application -version: 1.2.0+upv6.0.0.beta8 +version: 2.0.0+upv6.0.0.beta8 appVersion: "v6.0.0-beta8" diff --git a/teamspeak-server/templates/teamspeak-server.sfs.yaml b/teamspeak-server/templates/teamspeak-server.sfs.yaml index fd64f9e..453217b 100644 --- a/teamspeak-server/templates/teamspeak-server.sfs.yaml +++ b/teamspeak-server/templates/teamspeak-server.sfs.yaml @@ -35,6 +35,27 @@ spec: value: "accept" - name: TSSERVER_DEFAULT_PORT value: "30987" + # The voice service is UDP and cannot be probed; probe the TCP + # file-transfer port instead. + livenessProbe: + tcpSocket: + port: file-transfer + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + tcpSocket: + port: file-transfer + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Startup budget = 5s * 30 = 150s. + startupProbe: + tcpSocket: + port: file-transfer + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 30 resources: requests: cpu: "0.2" diff --git a/template-chart/values.yaml b/template-chart/values.yaml index 2bf48ea..5a437db 100644 --- a/template-chart/values.yaml +++ b/template-chart/values.yaml @@ -15,7 +15,6 @@ xxx: httpGet: path: / port: http - initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 @@ -23,18 +22,18 @@ xxx: httpGet: path: / port: http - initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 + # The startup probe gates liveness/readiness, so those need no initialDelaySeconds. + # Startup budget = periodSeconds * failureThreshold = 150s. startupProbe: httpGet: path: / port: http - initialDelaySeconds: 30 - periodSeconds: 10 + periodSeconds: 5 timeoutSeconds: 5 - failureThreshold: 3 + failureThreshold: 30 securityContext: pod: runAsNonRoot: true diff --git a/urlaubsverwaltung/Chart.yaml b/urlaubsverwaltung/Chart.yaml index c02c645..65a0c9d 100644 --- a/urlaubsverwaltung/Chart.yaml +++ b/urlaubsverwaltung/Chart.yaml @@ -3,5 +3,5 @@ name: urlaubsverwaltung description: A Helm chart to deploy urlaubsverwaltung on Kubernetes type: application -version: 1.5.0+up6.5.0 +version: 2.0.0+up6.5.0 appVersion: 6.5.0 diff --git a/urlaubsverwaltung/templates/urlaubsverwaltung.deployment.yaml b/urlaubsverwaltung/templates/urlaubsverwaltung.deployment.yaml index b5c9259..5faa6f2 100644 --- a/urlaubsverwaltung/templates/urlaubsverwaltung.deployment.yaml +++ b/urlaubsverwaltung/templates/urlaubsverwaltung.deployment.yaml @@ -113,7 +113,6 @@ spec: httpGet: port: 8080 path: /actuator/health/readiness - initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 3 successThreshold: 1 @@ -122,9 +121,17 @@ spec: httpGet: port: 8080 path: /actuator/health/liveness - initialDelaySeconds: 20 periodSeconds: 10 failureThreshold: 3 successThreshold: 1 timeoutSeconds: 5 + # The startup probe gates liveness/readiness. Spring Boot startup + # (JVM + Liquibase migrations) gets a budget of 10s * 30 = 300s. + startupProbe: + httpGet: + port: 8080 + path: /actuator/health/liveness + periodSeconds: 10 + failureThreshold: 30 + timeoutSeconds: 5 restartPolicy: Always diff --git a/voucher-vault/Chart.yaml b/voucher-vault/Chart.yaml index 48d9fae..d4b5316 100644 --- a/voucher-vault/Chart.yaml +++ b/voucher-vault/Chart.yaml @@ -4,7 +4,7 @@ description: A Helm chart to deploy VoucherVault on Kubernetes type: application -version: 1.3.0+up1.27.4 +version: 2.0.0+up1.27.4 appVersion: "1.27.4" maintainers: diff --git a/voucher-vault/values.yaml b/voucher-vault/values.yaml index 26b1cca..e537968 100644 --- a/voucher-vault/values.yaml +++ b/voucher-vault/values.yaml @@ -13,10 +13,29 @@ voucherVault: cpu: 1 memory: 384Mi ephemeral-storage: 100Mi - # TODO: Refine liness, readiness, startup probes - livenessProbe: null - readinessProbe: null - startupProbe: null + # "/" answers with a redirect for anonymous users, which httpGet treats as success. + livenessProbe: + httpGet: + path: / + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: / + port: http + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Startup budget = 5s * 30 = 150s. + startupProbe: + httpGet: + path: / + port: http + periodSeconds: 5 + timeoutSeconds: 5 + failureThreshold: 30 securityContext: pod: runAsNonRoot: true diff --git a/zipline/Chart.yaml b/zipline/Chart.yaml index d6b6789..e4c62d5 100644 --- a/zipline/Chart.yaml +++ b/zipline/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.3.0+up4.6.4 +version: 2.0.0+up4.6.4 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/zipline/templates/zipline.sfs.yaml b/zipline/templates/zipline.sfs.yaml index 69fe566..8ac3e9a 100644 --- a/zipline/templates/zipline.sfs.yaml +++ b/zipline/templates/zipline.sfs.yaml @@ -44,6 +44,12 @@ spec: - name: "zipline-server" containerPort: 3000 protocol: TCP + livenessProbe: + {{- toYaml .Values.zipline.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.zipline.readinessProbe | nindent 12 }} + startupProbe: + {{- toYaml .Values.zipline.startupProbe | nindent 12 }} volumeMounts: - name: zipline-volume mountPath: /zipline/uploads diff --git a/zipline/values.yaml b/zipline/values.yaml index 30294b9..042cfc4 100644 --- a/zipline/values.yaml +++ b/zipline/values.yaml @@ -7,6 +7,31 @@ config: domain: null maxUploadFileSize: 30m zipline: + # Zipline v4 exposes /api/healthcheck (checks server and database health); + # the endpoint is enabled by default (config.features.healthcheck). + livenessProbe: + httpGet: + path: /api/healthcheck + port: zipline-server + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /api/healthcheck + port: zipline-server + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + # The startup probe gates liveness/readiness. Zipline runs database + # migrations on startup, so grant a generous budget: 10s * 30 = 300s. + startupProbe: + httpGet: + path: /api/healthcheck + port: zipline-server + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 resources: requests: cpu: 0.1 From 7f1ef4055f621c0fad228c6138f3eae9752fa255 Mon Sep 17 00:00:00 2001 From: jklein Date: Fri, 21 Aug 2026 18:44:13 +0200 Subject: [PATCH 2/3] Refine probes based on k3d cluster verification Every chart was installed twice in a throwaway k3d cluster (origin/main vs this branch) with real Postgres/Redis/dex instances and observed for readiness ordering, stability and dependency-outage behavior. Findings: - voucher-vault: Django only accepts Hosts 127.0.0.1 and the configured DOMAIN; the default probe Host (pod IP) always got 400. Probes now send 'Host: 127.0.0.1'. - zipline: /api/healthcheck includes the database, so liveness now uses '/' (readiness/startup keep /api/healthcheck). Verified live: on a Postgres outage the pod turns NotReady within 30s and is never restarted by the kubelet. - outline: '/' also returns 500 when the database is down, so there is no dependency-free endpoint; all three probes use /_health. --- .watch-pr.sh | 15 +++++++++++++++ outline/templates/outline.sfs.yaml | 6 ++++-- voucher-vault/values.yaml | 14 +++++++++++++- zipline/values.yaml | 6 ++++-- 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 .watch-pr.sh diff --git a/.watch-pr.sh b/.watch-pr.sh new file mode 100644 index 0000000..ccdd7e3 --- /dev/null +++ b/.watch-pr.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Throwaway PR watcher (not committed). Exits when the PR leaves OPEN state +# or any review/issue comment appears. +REPO=jk-cluster/helm-charts +PR=21 +while true; do + STATE=$(gh pr view $PR --repo $REPO --json state --jq .state 2>/dev/null) + RC=$(gh api repos/$REPO/pulls/$PR/comments --jq length 2>/dev/null) + IC=$(gh api repos/$REPO/issues/$PR/comments --jq length 2>/dev/null) + if [ -n "$STATE" ] && [ "$STATE" != "OPEN" ]; then break; fi + if [ -n "$RC" ] && [ "$RC" != "0" ]; then break; fi + if [ -n "$IC" ] && [ "$IC" != "0" ]; then break; fi + sleep 90 +done +echo "STATE=$STATE REVIEW_COMMENTS=$RC ISSUE_COMMENTS=$IC" diff --git a/outline/templates/outline.sfs.yaml b/outline/templates/outline.sfs.yaml index fb8201a..a9896fb 100644 --- a/outline/templates/outline.sfs.yaml +++ b/outline/templates/outline.sfs.yaml @@ -80,8 +80,10 @@ spec: - containerPort: 3000 protocol: TCP name: http - # Outline exposes a dedicated health endpoint at /_health - # (also used by the upstream Docker HEALTHCHECK). + # Outline exposes a dedicated health endpoint at /_health (also used + # by the upstream Docker HEALTHCHECK). It checks Postgres and Redis; + # there is no dependency-free HTTP endpoint ("/" returns 500 too when + # the database is down), so all three probes use /_health. livenessProbe: httpGet: path: /_health diff --git a/voucher-vault/values.yaml b/voucher-vault/values.yaml index e537968..0749bdf 100644 --- a/voucher-vault/values.yaml +++ b/voucher-vault/values.yaml @@ -13,11 +13,17 @@ voucherVault: cpu: 1 memory: 384Mi ephemeral-storage: 100Mi - # "/" answers with a redirect for anonymous users, which httpGet treats as success. + # "/" answers with a redirect for anonymous users, which httpGet treats as + # success. The Host header must be set to 127.0.0.1 because Django's + # ALLOWED_HOSTS only accepts 127.0.0.1 and the configured DOMAIN — probing + # with the default Host (the pod IP) would always return 400. livenessProbe: httpGet: path: / port: http + httpHeaders: + - name: Host + value: 127.0.0.1 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 @@ -25,6 +31,9 @@ voucherVault: httpGet: path: / port: http + httpHeaders: + - name: Host + value: 127.0.0.1 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 @@ -33,6 +42,9 @@ voucherVault: httpGet: path: / port: http + httpHeaders: + - name: Host + value: 127.0.0.1 periodSeconds: 5 timeoutSeconds: 5 failureThreshold: 30 diff --git a/zipline/values.yaml b/zipline/values.yaml index 042cfc4..e986f35 100644 --- a/zipline/values.yaml +++ b/zipline/values.yaml @@ -8,10 +8,12 @@ config: maxUploadFileSize: 30m zipline: # Zipline v4 exposes /api/healthcheck (checks server and database health); - # the endpoint is enabled by default (config.features.healthcheck). + # the endpoint is enabled by default (config.features.healthcheck). Since it + # includes the database, it is used for readiness/startup only; liveness + # uses "/" so a database outage does not restart the pod. livenessProbe: httpGet: - path: /api/healthcheck + path: / port: zipline-server periodSeconds: 10 timeoutSeconds: 5 From be8ec3590e93439606b3b4e9ff8aecd4d9befa48 Mon Sep 17 00:00:00 2001 From: jklein Date: Fri, 21 Aug 2026 18:44:22 +0200 Subject: [PATCH 3/3] Remove stray helper script --- .watch-pr.sh | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 .watch-pr.sh diff --git a/.watch-pr.sh b/.watch-pr.sh deleted file mode 100644 index ccdd7e3..0000000 --- a/.watch-pr.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# Throwaway PR watcher (not committed). Exits when the PR leaves OPEN state -# or any review/issue comment appears. -REPO=jk-cluster/helm-charts -PR=21 -while true; do - STATE=$(gh pr view $PR --repo $REPO --json state --jq .state 2>/dev/null) - RC=$(gh api repos/$REPO/pulls/$PR/comments --jq length 2>/dev/null) - IC=$(gh api repos/$REPO/issues/$PR/comments --jq length 2>/dev/null) - if [ -n "$STATE" ] && [ "$STATE" != "OPEN" ]; then break; fi - if [ -n "$RC" ] && [ "$RC" != "0" ]; then break; fi - if [ -n "$IC" ] && [ "$IC" != "0" ]; then break; fi - sleep 90 -done -echo "STATE=$STATE REVIEW_COMMENTS=$RC ISSUE_COMMENTS=$IC"