Files
spring-boot-demo/kubernetes-deployment/scripts/demo-startup.sh
T
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

45 lines
2.6 KiB
Bash

#!/usr/bin/env bash
# An application that needs ~45 s to start, with and without a startupProbe. 1 replica; each
# phase is ONE patch, so there is one new ReplicaSet per phase. -> docs/output/startup-probe.txt
set -uo pipefail
source "$(dirname "$0")/env.sh"
D="deploy/orders"
observe() {
local label="$1"
echo "## $label"
local start; start=$(date +%s)
for _ in $(seq 1 20); do
local t=$(( $(date +%s) - start ))
printf 't=%3ds ' "$t"
kubectl -n "$NS" get pods -l app=orders --no-headers \
-o custom-columns=N:.metadata.name,H:.metadata.labels.pod-template-hash,R:.status.containerStatuses[0].ready,C:.status.containerStatuses[0].restartCount,W:.status.containerStatuses[0].state.waiting.reason,X:.metadata.deletionTimestamp \
| awk '{ if ($6 != "<none>") next; printf "[%s ready=%s restarts=%s%s] ", substr($1,length($1)-4), $3, $4, ($5=="<none>"?"":" "$5)}'
echo
sleep 6
done
echo
}
kubectl -n "$NS" scale "$D" --replicas=1 > /dev/null
kubectl -n "$NS" rollout status "$D" --timeout=120s > /dev/null
kubectl -n "$NS" delete events --all > /dev/null 2>&1
{
echo "# DEMO_STARTUP_DELAY=40s: the context takes ~45 s to refresh, and Tomcat only listens after that."
echo "# 1 replica, rolling update (maxSurge 1, maxUnavailable 0). Liveness: period 5 s, failureThreshold 3."
echo "# Pods being deleted are not listed. The old pod keeps serving while the new one is not ready."
echo
kubectl -n "$NS" patch "$D" --type=json -p '[
{"op":"remove","path":"/spec/template/spec/containers/0/startupProbe"},
{"op":"add","path":"/spec/template/spec/containers/0/env/-","value":{"name":"DEMO_STARTUP_DELAY","value":"40s"}}]' > /dev/null
observe "no startupProbe"
echo "# Events so far:"
kubectl -n "$NS" get events --sort-by=.lastTimestamp | grep -E 'Unhealthy|Killing|BackOff' | awk '{$1=""; $4=""; print}' | sed 's/^ *//' | sort | uniq -c | head -6
echo
kubectl -n "$NS" delete events --all > /dev/null 2>&1
kubectl -n "$NS" patch "$D" --type=json -p '[{"op":"add","path":"/spec/template/spec/containers/0/startupProbe","value":{"httpGet":{"path":"/actuator/health/liveness","port":"http"},"periodSeconds":2,"failureThreshold":60}}]' > /dev/null
observe "startupProbe: /actuator/health/liveness every 2 s, failureThreshold 60 (a 120 s budget)"
echo "# Events during the startupProbe run:"
kubectl -n "$NS" get events --sort-by=.lastTimestamp | grep -E 'Unhealthy|Killing|BackOff' | awk '{$1=""; $4=""; print}' | sed 's/^ *//' | sort | uniq -c | head -6
} | tee "$OUT/startup-probe.txt"
kubectl -n "$NS" set env "$D" DEMO_STARTUP_DELAY- > /dev/null
kubectl -n "$NS" scale "$D" --replicas=2 > /dev/null