Repository navigation
[ISSUE #8072] Harden container distributions and document the Kubernetes runtime contract - #8107
Conversation
d9c9c7d to
7fac331
Compare
…ubernetes runtime contract - Modernize the admin/bootstrap image bases: both images now use amazoncorretto:17.0.21-alpine3.24 (linux/amd64, linux/arm64) with an alpine:3.24 prepare stage; the bootstrap image no longer uses the EOL CentOS 7 base. - Pin a fixed numeric non-root UID/GID (USER 10001:10001), declare STOPSIGNAL SIGTERM and a HEALTHCHECK against /actuator/health, and keep the runtime read-only friendly: /tmp is the only writable path by default. wget is installed explicitly in both images (admin also keeps curl). - Rewrite both entrypoint.sh scripts as POSIX sh (the Alpine images do not ship bash), exec the JVM so SIGTERM reaches the Spring Boot shutdown hooks, support a read-only conf directory by falling back to a conf-ext classpath override (and to the classpath when a writable copy only partially succeeds), and keep the BOOT_JVM/ADMIN_JVM overrides intact. - Add docs/container-runtime.md: base-image update policy, runtime contract (user, writable paths, signals/exit codes), JVM and container memory budgets, Kubernetes requests/limits, readiness/liveness probe wiring (including management.endpoint.health.probes.enabled and initial-sync-readiness), Deployment/PDB examples for bootstrap and admin, upgrade/rollback procedure (including the whole-pod-template caveat), measured baseline image size/startup/memory numbers, and SBOM/scanning/signing guidance that stays within the ASF release process. - Add script/docker-image-smoke.sh and .github/workflows/docker-image-smoke.yml: CI smoke test for UID 10001, read-only rootfs, /tmp writability, conf-ext overrides (read-only classpath fallback and legacy copy path), BOOT_JVM/ADMIN_JVM, SIGTERM graceful shutdown (exit code 0/143, not 137), restarts with the same mounted configuration and (real-dist mode) the declared HEALTHCHECK plus /actuator/health = UP. SHENYU_SMOKE_REAL_DIST=1 runs the same checks against real distributions, and SHENYU_SMOKE_PREVIOUS_TAG=<release> verifies a previous published release still starts and stops gracefully with the same mounts. - Add a make smoke-image convenience target, refresh the integrated-test base-image pre-pull list, make the compose healthcheck read-only-rootfs safe, add .gitattributes so the container scripts stay on LF, and fix the pre-existing BOOSTRAP_REPOSITORY typo in the Makefile publish target.
436b806 to
360be28
Compare
Aias00
left a comment
There was a problem hiding this comment.
Approved. The container-hardening side of this PR is solid and self-contained: the new docker-image-smoke.yml is thoughtfully path-filtered with an explicit comment not to promote it to a required status check (so docs-only PRs never get blocked), the Dockerfile/entrypoint and docs/container-runtime.md changes are clean, and integrated-test.yml pinning alpine:3.24 / amazoncorretto:17.0.21-alpine3.24 while dropping EOL centos:7 is sensible. The InstanceCheckService.collectStateData() rework (per-namespace state history under historyLock, retaining/resetting namespaces) is also correct in isolation.
One coordination note: this PR's collectStateData() rework duplicates the per-namespace history change already in #7855 (issue #7695) - both add namespaceStateHistoryMap + historyLock and rewrite the same method - and #7971 also edits InstanceCheckService. All three touch the same file/method, so please coordinate a rebase so the namespace-history work lands exactly once (#7855 or this PR, not both) and the three are merged in an order that avoids a conflict on InstanceCheckService. The mergeable state currently shows "blocked", consistent with that overlap.
|
Thanks for the review, @Aias00! One clarification about the diff that was under review: an intermediate force-push briefly carried an unrelated local cherry-pick (the
The approval is recorded on |
|
Quick nudge: the corrected head |
Purpose
Harden the
shenyu-admin/shenyu-bootstrapdistribution images and document the runtime contract they now guarantee, closing the remaining acceptance items of #8072.Changes
Images
eclipse-temurin:17-centos7(bootstrap, EOL CentOS 7) andamazoncorretto:17.0.11-alpine3.19(admin) →amazoncorretto:17.0.21-alpine3.24for both, amd64 + arm64; prepare stage onalpine:3.24.USER 10001:10001) sorunAsUser/runAsNonRootin Kubernetes manifests are stable and verifiable.STOPSIGNAL SIGTERMand aHEALTHCHECKon/actuator/health(bootstrap start-period 60s, admin 90s).wgetis installed explicitly for the healthcheck; the admin image also keepscurlfor operators.sh(no bash in Alpine images):set -eu,execthe JVM so SIGTERM reaches Spring Boot shutdown hooks (exit 143),TMPDIR-awarejava.io.tmpdir, unchanged defaultBOOT_JVM/ADMIN_JVMstrings./tmpis the only writable path by default;conf-extoverrides are copied whenconfis writable and loaded from the classpath when it is not (a partially failed copy also falls back to the classpath with a warning).Docs
docs/container-runtime.md: base-image update policy, filesystem/signal/exit-code contract, JVM and container memory budgets, production Kubernetes Deployment/PDB examples for both distributions with the correct 9195/9095 ports, admin DB profile + requiredSHENYU_JWT_SECRETKEY, readiness/liveness probe wiring (/actuator/health/readiness|liveness,management.endpoint.health.probes.enabled,shenyu.sync.websocket.initial-sync-readiness), upgrade/rollback guidance (including the whole-pod-template caveat), measured baselines, SBOM/scanning/signing guidance, and local verification steps.Verification tooling
script/docker-image-smoke.sh(stub distributions by default,SHENYU_SMOKE_REAL_DIST=1for real tarballs) and amake smoke-imagetarget..github/workflows/docker-image-smoke.ymlruns the stub smoke test on PRs touching the dist Dockerfiles/entrypoints, assembly descriptors,Makefile, the script or the guide.SHENYU_SMOKE_PREVIOUS_TAG=2.7.1pulls the previous published release and verifies it still starts/stops gracefully with the same mounted configuration.integrated-test.ymlpre-pulls the new base tags; the compose example healthcheck no longer writes a file into the container;.gitattributeskeeps the container scripts on LF; fixed the pre-existingBOOSTRAP_REPOSITORYtypo in the Makefile publish target.Verification
bash script/docker-image-smoke.sh(stub): all checks pass (UID 10001, read-only rootfs,/tmp, declared HEALTHCHECK,conf-extclasspath fallback + legacy copy,BOOT_JVM/ADMIN_JVM, SIGTERM exit 143, restart with the same mounted configuration).SHENYU_SMOKE_REAL_DIST=1against the locally built2.7.2-SNAPSHOTtarballs (Docker 29, linux/amd64, 4 vCPU):745,138,547bytes,/actuator/healthUP after ~11s, Docker HEALTHCHECKhealthyafter ~11s, graceful SIGTERM (143);751,105,046bytes,/actuator/healthUP after ~21s, Docker HEALTHCHECKhealthyafter ~22s, graceful SIGTERM (143).SHENYU_SMOKE_PREVIOUS_TAG=2.7.1(published release):apache/shenyu-bootstrap:2.7.1andapache/shenyu-admin:2.7.1both start and stop gracefully with the sameconf-extmount under their own (writable rootfs) contract../mvnw -Prelease packageforshenyu-dist/shenyu-bootstrap-dist,shenyu-dist/shenyu-admin-dist -amsucceeds;bash -npasses for all touched shell scripts; docs YAML blocks and workflow/compose YAML parse.Out of scope / follow-ups
Closes #8072