Make probe paths configurable (liveness on /status.php restarts healthy pods during dependency outages)
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 72/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- helm, kubernetes
- Lĩnh vực
- devops
Hướng nghiên cứu
Bắt đầu với templates/deployment.yaml và values.yaml: issue xác định cả sáu đường dẫn probe được hardcode và ba phần giá trị probe. Thêm đường dẫn tùy chọn cho từng probe, giữ /status.php làm mặc định, và cập nhật README với các giá trị mới. Xác minh rằng cả nhánh template nginx và không dùng nginx đều render chính xác cho cả ba probe.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Description of the change
The chart renders all three probes (livenessProbe, readinessProbe, startupProbe) with a hardcoded httpGet.path: /status.php, while every other probe field is configurable:
templates/deployment.yaml— 6 hardcoded occurrences: lines 97 / 113 / 129 (non-nginx branch) and 158 / 174 / 190 (nginx.enabledbranch).values.yaml—livenessProbe/readinessProbe/startupProbeexpose onlyenabled,initialDelaySeconds,periodSeconds,timeoutSeconds,failureThreshold,successThreshold. There is nopath.
/status.php is served by PHP and depends on external systems (database, Redis, and the persistent volume mounted at /var/www/html). Using it for liveness means that when any dependency is slow or unavailable for longer than failureThreshold × periodSeconds (default 3 × 10s), the kubelet kills a perfectly healthy container. Kubernetes guidance is that liveness probes should not depend on external systems — dependency checks belong in readiness probes, where /status.php is exactly right and should stay.
What this caused in our cluster (chart 9.4.0, image.flavor: fpm + nginx.enabled: true, RKE2 v1.33)
| Time (UTC) | Event |
|---|---|
| 09:37:27 | the app persistent volume (RWX, CSI) became unreachable; every /status.php request exceeded timeoutSeconds: 5 |
| 09:37:57 | liveness failed 3× → kubelet sent SIGQUIT to the nginx sidecar (Container nextcloud-nginx failed liveness probe, will be restarted) |
| 09:37:57 → | nginx stopped accepting connections but never exited — its workers were blocked in uninterruptible I/O against the dead volume. nginx stayed running, restarts=0, startedAt unchanged, port 80 connection refused (×146 events) |
| +20 min | the pod could not be restarted by the kubelet and could not be deleted without --force --grace-period=0; the service stayed down until an operator intervened |
A readiness-only failure would have self-healed: as soon as the dependency returned, readiness would pass again and the pod would be re-added to the Service. With liveness on the same dependency-aware endpoint, the outage was converted into a wedged pod.
Mitigations available to operators today via values: none, other than livenessProbe.enabled: false (which also gives up restarting a genuinely deadlocked process). We verified that neither image.flavor nor the nginx.* values offer a probe path, and that the default files/nginx.config.tpl ships no dependency-free health endpoint.
Proposal 1 — minimal, backward compatible (requested)
Expose an optional path per probe and default it to the current value, so existing installations are unaffected:
# values.yaml
livenessProbe:
enabled: true
path: /status.php # NEW – optional, defaults to /status.php
initialDelaySeconds: 10
...
readinessProbe:
enabled: true
path: /status.php # NEW – optional
...
startupProbe:
enabled: false
path: /status.php # NEW – optional
...
--- a/charts/nextcloud/templates/deployment.yaml
+++ b/charts/nextcloud/templates/deployment.yaml
@@
{{- with .Values.livenessProbe }}
{{- if .enabled }}
livenessProbe:
httpGet:
- path: /status.php
+ path: {{ .path | default "/status.php" }}
port: {{ $.Values.nextcloud.containerPort }}
(same for readinessProbe / startupProbe, in both the non-nginx and the nginx.enabled branches.)
This alone lets operators implement the correct split — liveness = process liveness, readiness = dependencies — without patching the Deployment after every helm upgrade.
Proposal 2 — recommended follow-up: ship a dependency-free endpoint for liveness
Add a static location to the default nginx config (files/nginx.config.tpl, inside the existing server {} block):
location = /healthz {
access_log off;
return 200;
}
and default liveness to /healthz (readiness stays on /status.php). This endpoint is answered by nginx itself — no PHP, no database, no Redis, no persistent volume — so it fails only when the web server process is actually unable to serve.
Because this changes restart behaviour, it should land as an explicit, documented change (chart minor/major + README note), and it only applies where nginx is present:
nginx.enabled: true→ the probe targets the nginx container,/healthzis served there ✅nginx.enabled: false(mod_php / fpm without sidecar) → probes target the app container, so/healthzwould not exist. For these setups Proposal 1 (configurable path) is the useful part, or/healthzcould be provided as a static file / Apache snippet as a separate piece of work.
Workaround available today (worth documenting either way)
nginx:
config:
serverBlockCustom: |
client_max_body_size 512M;
client_body_timeout 300s;
fastcgi_buffers 64 4K;
fastcgi_read_timeout 3600s;
location = /healthz { access_log off; return 200; }
Note: serverBlockCustom is a full replacement of the default block (so the four default lines must be repeated), and it is injected into the server {} block of default.conf — a bare location therefore works there. The sibling key nginx.config.custom renders a separate file (zz-custom.conf) that is included in the http context, where a bare location would make nginx fail to start.
The endpoint exists afterwards, but making the kubelet use it still requires patching the Deployment, and that patch is reverted by the next Helm upgrade:
kubectl -n <ns> patch deploy nextcloud --type=strategic \
-p '{"spec":{"template":{"spec":{"containers":[{"name":"nextcloud-nginx","livenessProbe":{"httpGet":{"path":"/healthz"}}}]}}}}'
Benefits
- Removes a well-known Kubernetes anti-pattern (liveness depending on external systems) from the default configuration.
- Dependency outages (DB failover, Redis restart, NFS/RWX/CSI hiccup, storage maintenance) stop turning into container restarts and, in the worst case, wedged pods.
- Operators regain a real liveness signal: a deadlocked nginx/php-fpm is still detected and restarted, without coupling that decision to storage/database availability.
- Proposal 1 is fully backward compatible and useful on its own — it also helps with reverse proxies / other orchestrators that need a different probe path.
Possible drawbacks
- Proposal 2 changes default behaviour: pods are no longer restarted when
/status.phpfails. That is the intent, but it is a behavioural change and should be called out in the chart changelog and README. - A
/healthzanswered by nginx alone cannot detect a wedged php-fpm pool. Mitigation: keepstartupProbe/readinessProbeon/status.php(so traffic stops when PHP is unhealthy) — optionally recommendpm.max_requests/request_terminate_timeoutin the docs. - One more endpoint is exposed; it returns only
200and reveals nothing sensitive, but it is routable through the ingress unless restricted. - Chart surface grows by three optional values.
Additional information
Environment
- Kubernetes distribution: RKE2 v1.33 (guest cluster of a Harvester/HCI deployment)
- Helm: chart 9.4.0 (appVersion 35.0.1), managed through the Rancher UI
image.flavor: fpm+nginx.enabled: true;/var/www/html(code/config) on an RWX CSI volume, user data on a separate NFS CSI volume- Probes: chart defaults (
timeoutSeconds: 5,periodSeconds: 10,failureThreshold: 3)
Relevant chart facts (verified against main on 2026-10-06, chart 9.4.0 / appVersion 35.0.1)
templates/deployment.yamllines 97 / 113 / 129 / 158 / 174 / 190 →path: /status.php(hardcoded, both branches).values.yamllivenessProbe/readinessProbe/startupProbe→ nopathkey.files/nginx.config.tpl→ no health endpoint.nginx.config.serverBlockCustomis injected inside theserver {}block (files/nginx.config.tpl, line 53) — so it can carry alocation;nginx.config.customrenderszz-custom.confinto/etc/nginx/conf.d/(httpcontext), where a barelocationis invalid.- The shipped default
serverBlockCustomcontainsfastcgi_read_timeout 3600s;(server level), so a stuck PHP upstream can hold nginx workers for up to an hour — this is what made the graceful-shutdown hang in our incident possible. worker_shutdown_timeout(which would bound that shutdown) is amain-context directive and therefore cannot be injected throughnginx.config.customorserverBlockCustom; only a fullnginx.confreplacement would do it.
I'm happy to submit a PR for Proposal 1 (small and backward compatible: values.yaml + templates/deployment.yaml + one README row).
- Ngôn ngữ chính
- Go Template
- Star
- 539
- Fork
- 316
- Merge trung bình
- 4 ngày 17 giờ
- Pull request đã merge (30 ngày)
- 4
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của nextcloud/helm
-
No native support for REDIS_USER enviroment varCó thể đã có người làm @jholmes802 đã nhận 16 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
-
Failed to inspect imageĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
-
Nextcloud pods run as the namespace's default service account: the chart's account is only created with rbac.enabled, which binds the removed PodSecurityPolicyCó thể đã có người làm @martin-mat đã nhận 7 ngày trước. Đang mở
Độ khó 3/5 Nửa ngày Mức phù hợp với người mới 55/100
-
nextcloud.openmetrics.allowedClients is silently ignored unless nextcloud.configs is setCó thể đã có người làm @JanWelker đã nhận 32 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 78/100
-
External Redis not working: redis-session.ini: Permission deniedCó thể đã có người làm @antoinetran đã nhận 37 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 55/100
Tất cả issue của nextcloud/helm
Issue tương tự
-
[BUG] deploy.restart_policy without condition drops the restart policyCó thể đã có người làm @akshat-lakhera đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
docker/compose#14383 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
melodic-software/claude-code-plugins#9619 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
Maintainer thường phản hồi trong vòng 1 ngày
-
body-parser 2.3.0 in the published ai-dial-chat-bff image is vulnerable (CVE-2026-111181, HIGH)Có thể đã có người làm @illya-havsiyevych đã nhận hôm nay. Đang mởbug
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 87/100
epam/ai-dial-chat#9566 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
code-maintenance
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
Maintainer thường phản hồi trong vòng 1 ngày