Files
spring-boot-demo/kubernetes-deployment
asmhatreandClaude Opus 5 a065696478 Add kubernetes-deployment: probes, shutdown, JVM ergonomics, HPA
Companion code for "Deploying Spring Boot 4 on Kubernetes: Probes, Graceful
Shutdown, Limits and JVM Ergonomics". A dependency outage under three
probe-group setups, a rolling restart under load four ways (three runs
each), the JVM's ergonomic choices for nine pod shapes, one GC-heavy load
under five CPU limits with throttling counters, and an HPA driven by a
Micrometer gauge through prometheus-adapter. Measured on k3s v1.36.4.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C3TETMrqVUWeFkNtz3Jbo3
2026-09-11 17:12:10 +00:00
..

Spring Boot 4 on Kubernetes: probes, graceful shutdown, limits and JVM ergonomics

Companion project for Deploying Spring Boot 4 on Kubernetes: Probes, Graceful Shutdown, Limits and JVM Ergonomics on ankurm.com.

A small Spring Boot 4 service, the manifests that deploy it, and one script per experiment - a dependency outage under three probe configurations, a rolling restart under load four ways, the JVM's ergonomic choices for nine pod shapes, the same GC-heavy load under five CPU limits, and a HorizontalPodAutoscaler driven by a Micrometer gauge. Every figure in the article is in docs/output/.

Versions

Spring Boot 4.1.1
JDK Temurin 25.0.4.1 (in gcr.io/distroless/java25-debian13:nonroot)
Kubernetes k3s v1.36.4+k3s1, single node, 2 vCPU / 8 GB, cgroup v1 (docs/01-the-lab.md)
Prometheus 3.14.0
prometheus-adapter 0.12.0

Quickstart

export JAVA_HOME=/path/to/jdk-25
mvn -DskipTests package
docker build -f docker/Dockerfile -t sbd/k8s-demo:1 .
# load the image into your cluster (k3s ctr images import / kind load docker-image / minikube image load)
kubectl apply -f k8s/00-namespace.yaml -f k8s/downstream.yaml -f k8s/orders.yaml -f k8s/client.yaml
./scripts/demo-probes.sh            # ...and the other demo-*.sh; see the table below

What is in it

Path
k8s/orders.yaml the baseline Deployment: startup/liveness/readiness probes, preStop: sleep, MaxRAMPercentage=75
k8s/downstream.yaml a dependency to take away
k8s/gc-lab.yaml the single pod the CPU-limit experiment reshapes
k8s/hpa/ Prometheus, prometheus-adapter with one rule, the HPA
WorkController /work (timed requests, the app.inflight.requests gauge), /alloc (GC load)
DownstreamHealthIndicator a health indicator whose probe group is the experiment
JvmController /diag/jvm, /diag/gc - ergonomics and cgroup throttling counters. Diagnostic; delete before shipping
LoadGen the in-cluster load generator, run from the same image

Documentation

  1. The lab
  2. Probes: which checks belong in which probe
  3. JVM ergonomics: what the JVM decides from your pod spec
  4. CPU limits and the garbage collector
  5. Graceful shutdown and the rolling-update race
  6. HPA on a custom Micrometer metric

Captured output

File Produced by
probes-*.txt scripts/demo-probes.sh
startup-probe.txt scripts/demo-startup.sh
jvm-ergonomics.txt scripts/demo-ergonomics.sh
gc-throttling.txt + raw GC logs scripts/demo-gc-throttling.sh
shutdown-post-summary.txt, shutdown-*.txt scripts/demo-shutdown.sh (METHOD=GET for the -get- files)
hpa-custom-metric.txt, hpa-custom-metrics-api.txt scripts/demo-hpa.sh