Phillip, Kubernetes-Betrieb bei Pexon Consulting | 11 Min. Lesezeit | 16.09.2026
TL;DR: spring boot kubernetes in fünf Sätzen
Spring Boot Kubernetes heißt: Actuator-Liveness ohne Datenbank, Readiness für Traffic, Heap unter dem Container-Limit, Graceful Shutdown gegen die Termination-Uhr. Pexon Consulting (Deutschland, Microsoft Partner) schneidet das in Reviews bei Java-Teams, die vom Docker-Host gekommen sind. Spring Boot 4.1.1 ist am 20.08.2026 erschienen. Die fünf Schnitte sind älter. Wer sie lässt, restartet nachts.
| Schnitt | Falsch | Richtig |
|---|---|---|
| Liveness | /actuator/health inkl. DB |
/actuator/health/liveness lokal |
| Speicher | Heap = Limit | Heap klar unter dem Limit, Requests gemessen |
| Shutdown | SIGKILL nach 30s | preStop plus server.shutdown=graceful |
| Start | Liveness sofort | startupProbe für den Boot |
| Image | Fat-JAR plus Root | Distroless oder JRE, non-root |
Das Problem: die App ist grün, der Dienst nicht
Freitag, 18:10. Das Deployment ist Ready. Der Shop antwortet 502. Drei Pods stehen auf CrashLoopBackOff. Die Liveness-Probe trifft /actuator/health. Health zieht die Datenbank. Die Datenbank ist langsam. Kubernetes killt den Prozess, der noch bootet.
Das ist kein Angriff. Das ist Spring Boot Kubernetes ohne Schnitt.
Wir sehen das in kleinen Softwareteams, oft Tochtergesellschaften. Sie sind vom Docker-Host gekommen, weil die Datenbank zu groß wurde. Compose lief auf zwei Hosts. Jetzt steht ein Cluster. Niemand hat RBAC gesetzt. Niemand hat eine Network Policy. Die App-YAML ist ein Deployment plus Service. Spring Boot 3.5 ist seit dem 30.06.2026 ohne OSS-Patches. Viele Images hängen trotzdem dort.
Dieser Text ist kein zweites Härtungs-Stück. Dort stehen CIS, Replica, Secrets. Hier steht der Java-Schnitt: Actuator, Heap, Shutdown. Den Lift vom Host haben wir in der VM-Migration gelegt. Das ist ein anderes Vorhaben.
Pexon Consulting sagt das ungern elegant: ein laufender Pod ist kein Produktivbetrieb.
1. Actuator-Probes: drei Jobs, drei Pfade
Die kurze Antwort: Liveness darf die App nicht wegen einer Abhängigkeit töten. Readiness darf Traffic fernhalten. Startup darf den Boot überleben.
Spring Boot kennt das seit Jahren. In einem Kubernetes-Umfeld legt Actuator die Gruppen /actuator/health/liveness und /actuator/health/readiness an. Wer /actuator/health als Liveness nimmt, prüft oft die Datenbank mit. Dann killt eine langsame Query den Prozess.
# Probe-Schnitt, nicht die ganze App-YAML
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
periodSeconds: 5
startupProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
failureThreshold: 30
periodSeconds: 10
Wir raten davon ab, Liveness auf die Datenbank zu legen. Ein toter Pool ist ein Readiness-Fall. Ein toter Prozess ist ein Liveness-Fall. Wer beides mischt, erzeugt den Restart, den er diagnostizieren will.
Kubernetes 1.37.0 (Garhwal, 26.08.2026) ändert daran nichts. startupProbe ist Alltag, nicht Extra.
Unsere klare Empfehlung: drei Pfade, drei Endpunkte. Ein Health-Check für alles ist Geldverschwendung, wenn er nachts restartet.
Zwei Details, die in Reviews oft fehlen. Actuator muss den Management-Port kennen. Wenn Management auf 8081 liegt und die Probe 8080 trifft, ist die Probe tot. Und management.endpoint.health.probes.enabled=true muss stehen, sobald die App nicht in einem erkannten Kubernetes-Environment startet. Lokal im Laptop ist das Environment oft leer. Im Cluster setzt die Downward-API oder der Service-Account das Signal. Wer das vergisst, sieht 404 auf /actuator/health/liveness.
management.endpoint.health.probes.enabled=true
management.health.livenessstate.enabled=true
management.health.readinessstate.enabled=true
Wir haben Teams gesehen, die Probes auf /actuator/health lassen, „weil es 200 liefert“. 200 inkl. Datenbank ist der Restart von Freitag. Spring Boot 4.1.1 ändert die Gruppen nicht. Es ändert höchstens, welches Starter-Modul Actuator zieht.
2. Heap gegen Limit: OOM 137 ist kein Rätsel
Die kurze Antwort: Der Heap muss unter dem Container-Limit bleiben. Requests werden gemessen, nicht geraten.
Java sieht den Container, seit UseContainerSupport Default ist. Trotzdem setzen Teams -Xmx auf dasselbe wie resources.limits.memory. Metaspace, Direct Buffer, Thread-Stacks, Native sitzen daneben. Exit 137, Reason OOMKilled. Das Dashboard zeigt Ready. Der Shop zeigt 502.
# Beispiel, nicht Ihr Sizing
resources:
requests:
memory: "768Mi"
cpu: "250m"
limits:
memory: "1536Mi"
env:
- name: JAVA_TOOL_OPTIONS
value: "-XX:MaxRAMPercentage=75.0 -XX:+ExitOnOutOfMemoryError"
Wir raten davon ab, Limits ohne Messung zu setzen. Erst kubectl top und Heap-Dumps, dann die Zahl. Ein Limit ohne Request ist Throttle-Theater. Ein Request ohne Limit ist Nachbarschaftsstreit auf dem Node.
Spring Boot 4.1.1 (20.08.2026) ändert die JVM-Rechnung nicht. Der Container ist die Rechnung.
3. Graceful Shutdown: die Uhr läuft vor SIGTERM
Die kurze Antwort: PreStop frisst dieselbe Termination-Uhr wie der App-Shutdown. Wer 10 Sekunden schläft und 30 Sekunden pro Phase braucht, stirbt oft an SIGKILL.
Die Spring-Docs und Issue 47198 sagen das klar: terminationGracePeriodSeconds gilt für PreStop plus Shutdown. server.shutdown=graceful und spring.lifecycle.timeout-per-shutdown-phase müssen in diese Uhr passen.
spec:
terminationGracePeriodSeconds: 60
containers:
- name: shop-api
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"]
server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=20s
Zehn Sekunden PreStop, 20 Sekunden Shutdown, 60 Sekunden Uhr. Das geht auf. Dreißig Sekunden pro Phase und drei Phasen gehen nicht auf. Wir haben das in Reviews gesehen: das Image ist neu, die In-Flight-Requests sind tot.
Unsere klare Empfehlung: die Uhr zuerst aufschreiben, dann die YAML. Nicht umgekehrt.
4. Was Java-Teams auf dem Cluster lassen
Die kurze Antwort: App-Schnitt und Cluster-Schnitt sind zwei Listen. Wer nur die App schneidet, bleibt offen.
Kein RBAC außer cluster-admin für alle. Keine Network Policy. Ein Namespace. Privileged nicht, aber runAsUser: 0. Secrets in Env, manchmal im Image. Das ist das Setup, das nach dem Docker-Host übrig bleibt.
Red Hat hat 2024 600 Leute in USA, UK und APAC befragt. 89 Prozent hatten in zwölf Monaten mindestens einen Container- oder Kubernetes-Security-Vorfall. 40 Prozent fanden Fehlkonfigurationen. Das ist keine DACH-Stichprobe. Es ist die gleiche Klasse Fehler.
Die Lemma-Texte liegen woanders. CIS-Härtung und Cilium als CNI sind die Betriebsseiten. Hier bleibt die Feststellung: Spring Boot Kubernetes ohne RBAC und Network Policy ist ein Host mit Scheduler.
CNCF hat am 20.01.2026 geschrieben, dass 82 Prozent der befragten Container-Nutzer Kubernetes produktiv betreiben. Produktiv heißen viele Cluster. Hart heißen wenige.
Image und User sind der fünfte Schnitt, den wir hier nur anreißen. Fat-JAR als Root im Distroless-Missverständnis: entweder Distroless ohne Shell, dann bricht preStop sleep, oder ein JRE-Image mit non-root. Beides geht. Root plus Shell „zum Debuggen“ bleibt der Default nach dem Host. Secrets im Image haben wir im Ops-Text getrennt. Hier zählt: runAsNonRoot: true und ein User, den das Image kennt. Spring Boot startet ohne Root. Tomcat auch.
securityContext:
runAsNonRoot: true
runAsUser: 10001
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
Wer das auf ein Image setzt, das nur UID 0 kennt, bekommt CrashLoop. Dann ist das Image falsch, nicht die Policy. Das ist der Moment, in dem Teams die SecurityContext-Zeile wieder löschen. Falsch. Image bauen, User anlegen, dann die Zeile.
CNCF (20.01.2026) nennt 82 Prozent produktive Nutzung. Produktiv und non-root sind zwei Sätze. Red Hat 2024 (600 Personen, USA/UK/APAC): 40 Prozent fanden Fehlkonfigurationen. Root im Container ist eine davon, auch wenn die App „nur Java“ ist.
Ein Satz zur Priorität, den wir wiederholen. Restarts zuerst: Probes und Heap. Shutdown als Zweites, weil er Deployments teuer macht. User und Policies danach. Wer mit Network Policies startet, während der Shop 502 liefert, priorisiert die Folie.
Häufig gestellte Fragen
Was kostet ein Review, wenn Spring Boot auf Kubernetes schon läuft?
Der Einstieg ist ein Cluster-Check in 45 Minuten. Das Festpreis-Assessment liegt typisch bei 5.000 EUR je Cluster, Scope nach dem Check. Ein Workshop (1 Tag Security 3.000 EUR, 3 Tage 7.500 EUR) ist das Enablement, nicht der Ersatz für den Ist-Stand.
Spring Boot Kubernetes oder nur Actuator richtig setzen: was zuerst?
Kommt drauf an, aber wenn Pods nachts restarten, zuerst Probes und Heap. RBAC und Policies bleiben Pflicht. Sie löschen keinen OOM. Beides in einem Review, nicht als zwei Religionen.
Reicht `/actuator/health` als einzige Probe?
Nein. Health zieht oft die Datenbank. Liveness muss lokal bleiben. Readiness darf Abhängigkeiten zeigen. startupProbe hält den Boot.
Spring Boot 3.5 oder 4.1.1 auf Kubernetes: was zählt mehr?
3.5 ist seit dem 30.06.2026 ohne OSS-Patches. 4.1.1 ist der aktuelle Zweig (20.08.2026). Der Probe-Schnitt ist in beiden derselbe. Ein altes Image mit richtigen Probes überlebt. Ein neues Image mit /actuator/health als Liveness nicht.
Brauchen wir ein Service Mesh für Spring Boot Kubernetes?
Selten als Erstes. Erst Probes, Heap, Shutdown, RBAC, Network Policies. Mesh kommt, wenn Ost-West-Auth wirklich fehlt. Nicht weil die Folie Mesh sagt.
Nächster Schritt
Verwandte Themen
→Kubernetes-Härtung, unabhängig vom Java-Schnitt
→VMs und Hosts nach Kubernetes



