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
This commit is contained in:
2026-09-11 17:12:10 +00:00
co-authored by Claude Opus 5
parent 644da9e65e
commit a065696478
72 changed files with 28415 additions and 2 deletions
+64
View File
@@ -0,0 +1,64 @@
# 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**](https://ankurm.com/spring-boot-4-kubernetes-probes-graceful-shutdown-cpu-limits-hpa/)
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/`](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](docs/01-the-lab.md)) |
| Prometheus | 3.14.0 |
| prometheus-adapter | 0.12.0 |
## Quickstart
```bash
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`](k8s/orders.yaml) | the baseline Deployment: startup/liveness/readiness probes, `preStop: sleep`, `MaxRAMPercentage=75` |
| [`k8s/downstream.yaml`](k8s/downstream.yaml) | a dependency to take away |
| [`k8s/gc-lab.yaml`](k8s/gc-lab.yaml) | the single pod the CPU-limit experiment reshapes |
| [`k8s/hpa/`](k8s/hpa) | Prometheus, prometheus-adapter with one rule, the HPA |
| [`WorkController`](src/main/java/com/ankurm/k8s/web/WorkController.java) | `/work` (timed requests, the `app.inflight.requests` gauge), `/alloc` (GC load) |
| [`DownstreamHealthIndicator`](src/main/java/com/ankurm/k8s/health/DownstreamHealthIndicator.java) | a health indicator whose probe group is the experiment |
| [`JvmController`](src/main/java/com/ankurm/k8s/diag/JvmController.java) | `/diag/jvm`, `/diag/gc` - ergonomics and cgroup throttling counters. Diagnostic; delete before shipping |
| [`LoadGen`](src/main/java/com/ankurm/k8s/loadgen/LoadGen.java) | the in-cluster load generator, run from the same image |
## Documentation
1. [The lab](docs/01-the-lab.md)
2. [Probes: which checks belong in which probe](docs/02-probes.md)
3. [JVM ergonomics: what the JVM decides from your pod spec](docs/03-jvm-ergonomics.md)
4. [CPU limits and the garbage collector](docs/04-cpu-limits-and-gc.md)
5. [Graceful shutdown and the rolling-update race](docs/05-graceful-shutdown.md)
6. [HPA on a custom Micrometer metric](docs/06-hpa-custom-metrics.md)
## Captured output
| File | Produced by |
|---|---|
| `probes-*.txt` | `scripts/demo-probes.sh` |
| [`startup-probe.txt`](docs/output/startup-probe.txt) | `scripts/demo-startup.sh` |
| [`jvm-ergonomics.txt`](docs/output/jvm-ergonomics.txt) | `scripts/demo-ergonomics.sh` |
| [`gc-throttling.txt`](docs/output/gc-throttling.txt) + raw GC logs | `scripts/demo-gc-throttling.sh` |
| [`shutdown-post-summary.txt`](docs/output/shutdown-post-summary.txt), `shutdown-*.txt` | `scripts/demo-shutdown.sh` (`METHOD=GET` for the `-get-` files) |
| [`hpa-custom-metric.txt`](docs/output/hpa-custom-metric.txt), [`hpa-custom-metrics-api.txt`](docs/output/hpa-custom-metrics-api.txt) | `scripts/demo-hpa.sh` |