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
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# What the JVM decides from the pod's resources, with no JVM flags at all.
# -> docs/output/jvm-ergonomics.txt
set -uo pipefail
source "$(dirname "$0")/env.sh"
# cpu.limit | cpu.request | mem.request | mem.limit. Requests are deliberately small and constant:
# the JVM ignores them (JDK-8281181 removed CPU shares from the calculation in JDK 19), and small
# requests let every case schedule on a 2-CPU node.
CASES=(
"none|100m|256Mi|2Gi"
"500m|100m|256Mi|512Mi"
"1|100m|256Mi|1Gi"
"1|100m|256Mi|2Gi"
"1500m|100m|256Mi|2Gi"
"2|100m|256Mi|1Gi"
"2|100m|256Mi|1700Mi"
"2|100m|256Mi|1800Mi"
"2|100m|256Mi|4Gi"
)
flag() { grep -E "^ *[a-z_]+ +$1 " <<< "$2" | awk '{print $4}'; }
{
echo "# JVM ergonomics per pod resources. Image: $IMAGE, no JVM options. Node: $(nproc) CPUs."
echo "# cgroup v$( [ -f /sys/fs/cgroup/cgroup.controllers ] && echo 2 || echo 1 ) node; see docs/03-jvm-ergonomics.md for the v2 equivalents."
echo
printf '%-7s %-7s %-7s %-7s | %-5s %-10s %9s %6s %6s %6s\n' "cpu.req" "cpu.lim" "mem.req" "mem.lim" "CPUs" "GC" "MaxHeap" "PGCThr" "CGCThr" "JITThr"
i=0
for c in "${CASES[@]}"; do
IFS='|' read -r cl cr mr ml <<< "$c"
if [ "$cl" = none ]; then res="{requests: {cpu: $cr, memory: $mr}, limits: {memory: $ml}}"
else res="{requests: {cpu: $cr, memory: $mr}, limits: {cpu: $cl, memory: $ml}}"; fi
out=$(oneoff "erg-$i" "$res" java -XX:+PrintFlagsFinal -version 2>&1)
gc=SerialGC; [ "$(flag UseG1GC "$out")" = true ] && gc=G1GC; [ "$(flag UseParallelGC "$out")" = true ] && gc=ParallelGC
cpus=$(oneoff "erg-$i" "$res" java -XshowSettings:system -version 2>&1 | grep -i 'Effective CPU Count' | awk -F: '{gsub(/ /,"",$2); print $2}')
heap=$(( $(flag MaxHeapSize "$out") / 1024 / 1024 ))
printf '%-7s %-7s %-7s %-7s | %-5s %-10s %8sM %6s %6s %6s\n' "$cr" "$cl" "$mr" "$ml" "$cpus" "$gc" "$heap" \
"$(flag ParallelGCThreads "$out")" "$(flag ConcGCThreads "$out")" "$(flag CICompilerCount "$out")"
i=$((i+1))
done
echo
echo "# java -XshowSettings:system for the 1500m case:"
oneoff erg-show "{requests: {cpu: 100m, memory: 256Mi}, limits: {cpu: 1500m, memory: 2Gi}}" java -XshowSettings:system -version 2>&1 | grep -vE '^(openjdk|OpenJDK)'
} | tee "$OUT/jvm-ergonomics.txt"