Start / Seminare / Quarkus für Spring-Boot-Teams
Modul
Container und Kubernetes
4 Kapitel in diesem Modul-Video · Laufzeit
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
Container und Kubernetes
0:00 Hier begegnen uns zwei Plattformen, die sich näher sind, als die Werbung beider Seiten nahelegt. Spring Boot baut Images und erzeugt Manifeste, Quarkus auch. Der Unterschied zeigt sich nicht beim Bauen, sondern erst, wenn der Pod unter Last steht — bei der Zeit bis zur Bereitschaft, beim Speicher pro Instanz, bei der Frage, wie viele Pods auf einen Knoten passen.
0:21 Dieses Modul ist deshalb weniger ein Werkzeugmodul als ein Messmodul. Am Ende haben Sie Zahlen, keine Eindrücke.
Container und Kubernetes
0:29 Wir sind im vorletzten Drittel. Resilienz und Observability stehen, jetzt kommt der Betrieb im Cluster. Direkt danach vergleichen wir JVM und Native Image — und dafür brauchen wir genau die Images, Manifeste und Messwerte, die in diesem Modul entstehen. Halten Sie Ihre Zahlen also fest; wir verwenden sie im nächsten Modul weiter.
Images bauen
0:50 Beginnen wir beim Image. Drei Wege führen zum Ziel, und alle drei haben ihre Berechtigung — je nachdem, wie viel Kontrolle Sie brauchen. Quarkus erzeugt Container-Images über eigene Extensions, etwa eine, die ohne Docker-Daemon auskommt. Der Imagename entsteht aus drei Konfigurationswerten für Gruppe, Name und Tag. Spring Boot erzeugt Images über Dockerfiles und über Buildpacks.
1:13 Das ist eine faire Ausgangslage: Beide Plattformen können dasselbe, sie kommen nur aus unterschiedlichen Richtungen. Für die Migration heißt das, dass Ihr bestehender Bauprozess weitgehend übertragbar ist — und dass es sich lohnt, ihn bei der Gelegenheit einmal zu vereinfachen. Die drei Schichten sind eine Skala von Kontrolle zu Bequemlichkeit.
1:34 Ein eigenes Dockerfile gibt Ihnen alles in die Hand und verpflichtet Sie zur Pflege — inklusive Basisimage-Updates. Buildpacks nehmen Ihnen die Datei ab, dafür haben Sie wenig Einfluss auf Details. Die Extension baut aus dem Build heraus, ohne dass Sie eine Datei schreiben. Entscheidend ist nicht, welcher Weg der beste ist, sondern dass es im Team genau einer ist. Drei parallele Wege für dieselbe Anwendung sind der eigentliche Fehler.
2:01 Vier Punkte, und der erste überrascht viele: Den Löwenanteil bestimmt das Basisimage, nicht Ihre Anwendung. Wer an der Größe arbeiten will, fängt dort an. Der zweite Punkt ist eine Frage der Schichtung — Abhängigkeiten ändern sich selten, Anwendungscode oft; wer das in dieser Reihenfolge anordnet, spart bei jedem Deployment Übertragung.
2:21 Der dritte gehört schon zum nächsten Modul: Ein Native Executable braucht keine JVM im Image. Und der vierte ist ein Sicherheitsargument: Was nicht im Image liegt, muss auch nicht aktualisiert werden. Der erste Punkt ist der schwerwiegendste und bekannt aus jeder CI/CD-Diskussion: Das Image wird je Umgebung neu gebaut — dann ist getestet und ausgeliefert nicht mehr dasselbe.
2:44 Der zweite macht Rollbacks unmöglich, weil ein beweglicher Tag keine Adresse ist. Der dritte ist ein Klassiker bei schlanken Basisimages: Zeitzone oder Gebietsschema fehlen, und die Datumsformatierung ändert sich still. Und der vierte ist ein Sicherheitsproblem: Build-Argumente mit Zugangsdaten landen in der Image-Historie und sind dort für jeden lesbar.
Betrieb auf Kubernetes
3:04 Weiter zum Cluster. Auch hier kann Quarkus etwas, das den Handbetrieb ablöst: Manifeste entstehen beim Bauen. Die Kubernetes-Extension erzeugt beim Bauen Manifeste in einem Unterverzeichnis des Zielordners, in beiden gängigen Formaten, und legt darin mindestens ein Deployment und einen Service an. Für OpenShift und für Knative gibt es eigene Konfigurationsnamensräume. Der Vorteil ist, dass die Manifeste zum Artefakt gehören und mit ihm versioniert werden.
3:32 Das Bild: Die Bedienungsanleitung liegt in derselben Kiste wie das Gerät — und nicht in einem Ordner, den jemand vor zwei Jahren angelegt hat. Sechs Zeilen, und die Fußnote enthält die Warnung, die zählt: Es gibt eine Einstellung, mit der der Build direkt in den Cluster ausrollt. Das ist praktisch für eine Demo und gefährlich in einem Projekt, weil plötzlich der Build deployt und nicht mehr die Pipeline.
3:55 Setzen Sie das bewusst und nie dauerhaft in der Konfigurationsdatei. Die Zeilen zu den Probes darüber sind der Anschluss an das vorige Modul — hier verbinden sich Health-Endpunkte und Plattform. Vier Punkte, die zusammen darüber entscheiden, ob ein Rolling Update unbemerkt bleibt oder Fehler erzeugt. Die Probes zeigen auf die Health-Endpunkte aus dem letzten Modul.
4:16 Ein sauberes Herunterfahren lässt laufende Anfragen zu Ende kommen — das ist bei einem Rolling Update der Unterschied zwischen null und einigen hundert abgebrochenen Verbindungen. Die Bereitschaftsprüfung muss echte Bereitschaft melden, nicht nur einen laufenden Prozess. Und Konfiguration und Secrets kommen aus dem Cluster, nicht aus dem Image — sonst bauen Sie je Umgebung ein eigenes Artefakt.
4:39 Der erste Punkt ist die Fortsetzung des Actuator-Themas: Probes zeigen auf alte Pfade und schlagen nach der Migration fehl — mit dem unangenehmen Ergebnis, dass Kubernetes den Pod für tot hält und neu startet. Der zweite ist die eben erwähnte Deploy-Einstellung, die in der Konfiguration stehen bleibt. Der dritte betrifft das Herunterfahren, das nicht sauber greift.
4:59 Und der vierte hebt den Vorteil generierter Manifeste wieder auf: Sie werden erzeugt und danach von Hand nachbearbeitet — spätestens beim nächsten Build ist diese Arbeit weg.
Ressourcen messen statt schätzen
5:09 Und jetzt der Teil, der über den wirtschaftlichen Nutzen der ganzen Migration entscheidet — und der trotzdem regelmäßig ausgelassen wird. Requests reservieren, Limits begrenzen. Beide sollten aus einer Messung unter realistischer Last stammen. Und jetzt kommt der Punkt, den man sich merken muss: Wenn Sie wegen des geringeren Speicherbedarfs migrieren und danach die alten Werte übernehmen, haben Sie den Vorteil vollständig verschenkt.
5:34 Der Cluster reserviert weiter dieselbe Menge, die Dichte auf den Knoten bleibt gleich, die Rechnung auch. Das passiert häufiger, als man denkt — weil die Werte in einem Manifest stehen, das niemand mehr anfasst. Fünf Schritte, und der erste ist der, an dem es scheitert: unter realistischer Last messen, nicht im Leerlauf.
5:53 Ein Dienst im Leerlauf sagt Ihnen nur, wie viel er im Leerlauf braucht. Beobachten Sie über einen ganzen Lastzyklus, damit auch der Abrechnungslauf um drei Uhr nachts in den Zahlen auftaucht. Requests am Normalbedarf, Limits mit Reserve für Spitzen. Und die Fußnote nennt den Zielkonflikt in einem Satz: Ein zu niedriges Limit beendet den Pod, ein zu hohes bezahlt ungenutzte Reserve.
6:16 Drei Zahlen, und zusammen ergeben sie erst eine wirtschaftliche Aussage. Die Imagegröße entscheidet über Verteilzeiten im Cluster — relevant, wenn viele Knoten das Image ziehen müssen. Die Zeit bis zur Bereitschaft entscheidet über das Skalierungsverhalten, also darüber, wie schnell Sie auf Lastspitzen reagieren. Und der Speicher je Instanz entscheidet über die Dichte auf den Knoten und damit über die Anzahl der Knoten.
6:40 Erst die dritte Zahl lässt sich in Geld übersetzen — und Geld ist die Währung, in der über Migrationen entschieden wird. Der erste Punkt ist der schon erwähnte verschenkte Vorteil: Requests und Limits werden unverändert übernommen. Der zweite ist die Leerlaufmessung. Der dritte wiederholt den ersten aus anderer Richtung, weil er so häufig ist.
6:59 Und der vierte ist ein methodischer Fehler, den man nur in einer eigenen Testumgebung macht: Gemessen wird auf einem leeren Cluster ohne Nachbarn. In der Realität teilt sich Ihr Pod den Knoten mit anderen, und genau dann werden Limits interessant.
Übung
7:14 In der Übung bringen wir beide Varianten von Pfandkreis in den Cluster — und erheben die Zahlen, die im nächsten Modul die Entscheidung tragen. Der Hinweis auf dieser Folie ist die halbe Aufgabe: dieselbe Last für beide Varianten. Alles andere macht den Vergleich wertlos, egal wie sorgfältig Sie messen. Erfolgreich sind Sie, wenn beide Varianten im Cluster laufen, die Probes greifen und Sie drei Zahlen dokumentiert haben — Imagegröße, Zeit bis zur Bereitschaft und Speicherbedarf unter Last.
7:42 Das ist bewusst wenig; drei belastbare Zahlen sind mehr wert als zwölf unklare. Und noch ein Hinweis zur Lastquelle: Ein einfaches Lastwerkzeug genügt vollkommen. Wichtiger als seine Raffinesse ist, dass es für beide Varianten identisch konfiguriert ist und dass Sie die Konfiguration mit den Zahlen zusammen ablegen. Die Schritte eins bis drei sind Einrichtung, vier und fünf sind die Substanz.
8:06 Achten Sie beim dritten Schritt auf die Probes, damit Ihre Zeitmessung überhaupt etwas Sinnvolles misst — nämlich Bereitschaft und nicht Prozessstart. Im fünften Schritt leiten Sie Requests und Limits ab und begründen sie. Diese Begründung ist wichtiger als der Zahlenwert selbst, weil sie in sechs Monaten erklärt, warum dort steht, was dort steht.
8:26 Und die Fußnote: Die Ergebnisse wandern direkt ins nächste Modul. Der erste Punkt macht jeden Vergleich kaputt: unterschiedliche Basisimages. Wenn Sie Imagegrößen vergleichen wollen, muss der Unterboden derselbe sein. Der zweite verhindert Wiederholbarkeit: Das Deployment wird von Hand gemacht und lässt sich nicht reproduzieren.
8:45 Der dritte ist die falsche Messgröße — Startzeit statt Zeit bis zur Bereitschaft; für den Cluster zählt nur die zweite. Und der vierte ist eine verschenkte Gelegenheit: Die erzeugten Manifeste landen nicht in der Versionsverwaltung und damit auch nicht im Review.
Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →