Das Bild ausgemalt: Am einen Schalter staut sich die Schlange, also baut man den Schalter zu einem größeren Schalter um, an dem mehr Menschen gleichzeitig bedient werden. Der Umbau braucht Zeit, und währenddessen ist der Schalter zu. Schöner ist es, einen zweiten, gleichen Schalter zu öffnen, der sofort arbeiten kann. Und fällt ein Schalter aus, bleibt der andere besetzt.
Fachlich ist das vertikales Skalieren: Die bestehende Instanz, also eine virtuelle Maschine wie EC2, wird durch eine leistungsstärkere ersetzt. Horizontales Skalieren heißt stattdessen, zusätzliche Instanzen derselben Art daneben zu schalten und die Anfragen auf sie zu verteilen. Der Schalterausfall ist ein Single Point of Failure, eine Komponente, deren Ausfall alles stoppt.
In der Praxis: Mehr gleichzeitige Anfragen sprechen für horizontal, denn Lastverteilung wächst nach Bedarf, und die Abrechnung folgt der Nutzung. Größere einzelne Anfragen, etwa eine Datenbank mit hohem Speicherbedarf, sprechen für vertikal. Kubernetes hält dabei die gewünschte Anzahl laufender Container-Instanzen automatisch ein.
Das Bild hat eine Grenze: Ein Schalterteam braucht nur Menschen, Instanzen brauchen einen Lastverteiler, der die Anfragen auf die Instanzen verteilt, und geteilte Zustände wie Datenbanken. Und vertikal stößt man an die größte angebotene Instanzgröße, während horizontales Ergänzen nahezu unbegrenzt bleibt.
Horizontales Skalieren heißt nicht teurer, sondern redundanter: Mehr Instanzen schützen vor Ausfall, eine große Instanz bleibt ein einziger Schwachpunkt.
📌 Horizontale Skalierung · Vertikale Skalierung · Redundanz
📚 Cloud von Grund auf · Tag 6 von 30
#aws #devops #CloudHosting
Viele denken, Kubernetes brauche eine einzige Gesundheitsprüfung, denn gesund ist gesund. Plausibel klingt das, weil beide Sonden denselben HTTP-Aufruf machen, etwa GET /healthz mit Antwortcode 200 bis 399 als Erfolg.
Tatsächlich stellen die Sonden zwei verschiedene Fragen. Die Liveness-Probe (Lebenssonde) prüft, ob der Container überhaupt noch funktionsfähig ist oder durch einen Neustart repariert werden kann. Die Readiness-Probe (Bereitschaftsonde) prüft, ob er gerade Verkehr annehmen darf. Schlägt Readiness fehl, nimmt der Kubelet – der Agent auf jedem Knoten, der Container startet und überwacht – den Pod (die kleinste Einheit in Kubernetes) aus den Endpoints des Service; der Container läuft weiter, es kommt nur kein Verkehr mehr an.
Der Irrtum entsteht, weil beide Prüfungen technisch identisch aussehen. Was fehlt, ist die Frage nach der Folge: Neustart oder Pause.
Eine Anwendung lädt beim Start große Datenmengen und antwortet noch nicht. Wer hier Liveness mit Readiness gleichschaltet, startet den Container neu, obwohl er nur Zeit bräuchte. Noch schlimmer: Eine Liveness-Probe, die die externe Datenbank mitprüft, löst bei deren Ausfall eine Neustartschleife aus, die nichts behebt. Abhängigkeiten gehören deshalb in die Readiness-Probe.
Woran man es erkennt: Mit den Standardwerten gilt ein Container nach drei aufeinanderfolgenden Fehlversuchen im Abstand von zehn Sekunden als nicht gesund. Wer Container im Kreis drehen sieht, obwohl sie nur langsam starten, hat Liveness zu scharf gestellt.
Liveness heißt nicht „alles prüfen, was wichtig ist“, sondern „nur prüfen, was ein Neustart reparieren kann“.
📌 Liveness vs. Readiness · Kubelet · failureThreshold 3
📚 Cloud von Grund auf · Tag 4 von 30
#kubernetes #devops #sre
In Kubernetes wird beim Start jedes Containers festgelegt, wie viel CPU und Speicher ihm garantiert und wie viel er höchstens verbrauchen darf. Das betrifft jede Web-Anwendung, jeden Job, jeden Dienst im Cluster – einem Cluster, einer Gruppe von Rechnern, die Container gemeinsam betreiben.
Zuerst definiert man die Requests: die Mengen an CPU und Speicher, die der Scheduler, die Komponente, die Container auf Knoten verteilt, fest einplant und garantiert. CPU misst man in Millicores: 1000m sind ein voller Kern, 500m die Hälfte. Speicher steht in Bytes, etwa mit dem Suffix Mi für Mebibyte.
Dann prüft der Scheduler anhand der Requests, ob ein Knoten noch Platz hat. Er kennt die Limits bei der Platzierung nicht. Fehlen Requests, bucht er Knoten über, weil er den Bedarf nicht kennt – Engpässe treten dann erst zur Laufzeit auf.
Danach läuft der Container und darf über seinen Request hinaus wachsen, solange Ressourcen frei sind. Ein Beispiel: Request 100m CPU und 128Mi Speicher, Limit 500m und 256Mi. Kurzzeitig darf er also auf das Fünffache der zugesicherten CPU wachsen.
Zuletzt greifen die Limits zur Laufzeit. Überschreitet der Container sein Speicher-Limit, beendet ihn der Kernel sofort per OOM-Kill und Kubernetes startet ihn neu. Am CPU-Limit wird er nicht beendet, sondern gedrosselt: Er läuft langsamer, arbeitet aber weiter. Pods ganz ohne Werte erhalten die Klasse BestEffort und werden bei Speicherknappheit zuerst verdrängt.
Requests sind das Versprechen an den Scheduler, Limits die Grenze im Betrieb. Wer Limits als Requests deutet, plant Knoten falsch voll; wer beides weglässt, überlässt die Verteilung dem Zufall.
📌 Request · Limit · OOM-Kill
📚 Cloud von Grund auf · Tag 4 von 30
#kubernetes #devops #CloudHosting
Verwechselt werden beide, weil sie im Alltag zusammen auftreten. Immer wenn eine Anwendung Pods startet, steht ein Service davor.
Ein Pod ist die kleinste Einheit in Kubernetes und enthält einen oder mehrere Container, die sich Netzwerk und Speicher teilen. Ein Deployment hält eine gewünschte Anzahl gleicher Pods am Laufen. Pods sind bewusst kurzlebig: Bei jedem Update, bei Knotenausfall oder Neustart ersetzt Kubernetes alte Pods durch neue – und jeder neue Pod erhält eine neue Cluster-IP. Ein Webshop-Deployment verwaltet etwa drei Pods, von denen jeder Neustart mit einer frischen IP startet.
Ein Service ist dagegen eine feste Adresse für diese wechselnde Gruppe. Er besitzt eine eigene IP-Adresse und einen DNS-Namen (DNS übersetzt Namen in IP-Adressen) innerhalb des Clusters, die sich nicht ändern, solange der Service existiert. Der Service wählt seine Pods über ein Label-Selektor-Kriterium aus: Alle Pods mit einem bestimmten Label gehören zur Gruppe. Der Service „frontend“ verteilt alle Aufrufe von „frontend“ immer auf einen der gerade laufenden Pods – egal, wer gerade neu gestartet wurde.
Der Pod liefert die Arbeit, der Service liefert die Erreichbarkeit. Pod-IPs bleiben hinter dem Service verborgen; fällt ein Pod aus, wandern seine Anfragen automatisch zu den verbleibenden.
Faustregel: Pods nie direkt adressieren, sondern immer über den Service – eine Pod-IP in einer Konfiguration ist nach dem nächsten Neustart unbrauchbar.
Der Service heißt nicht Lastverteiler für Container, sondern feste Anlaufstelle vor kurzlebigen Pods.
📌 Pod · Service · Label-Selektor
📚 Cloud von Grund auf · Tag 4 von 30
#kubernetes #CloudHosting #devops
Der Vorarbeiter hat einen Plan: Drei Arbeiter an einer Station. Kommt einer nicht, schickt er einen Ersatz. Der Ersatz übernimmt dieselbe Aufgabe, ohne dass jemand nachfragen muss. Der Vorarbeiter prüft dabei nicht die Stimmung oder die Leistung. Er zählt nur: Sind noch drei da? Solange die Zahl stimmt, greift er nicht ein.
In Kubernetes ist der Vorarbeiter das Deployment, eine Verwaltungseinheit für gleichartige Pods. Der Pod ist die kleinste betreibbare Einheit und umhüllt einen oder mehrere Container, also Anwendungen samt Abhängigkeiten. Der Plan steckt im Feld replicas: Dort steht die Soll-Stärke, etwa die Zahl drei. Fällt ein Pod aus, startet das Deployment automatisch einen neuen. Kubernetes verteilt die Pods dabei auf die Knoten, die Arbeitsrechner des Clusters.
Ein Deployment für eine Webanwendung mit replicas: 3 erzeugt drei gleiche Pods. Stürzt einer ab, läuft die Zahl ohne Eingriff auf drei zurück. Die Container eines Pods teilen sich eine IP-Adresse und reden über localhost miteinander.
Das Bild hat eine Grenze: Ein Arbeiter bleibt derselbe Mensch, ein ersetzter Pod ist eine neue Instanz mit neuer IP-Adresse. Der Vorarbeiter delegiert auch aktiv, das Deployment vergleicht nur Ist und Soll. Stabile Adressen für Anfragen liefert deshalb ein Kubernetes-Service.
Pods also nie von Hand starten: Wer replicas selbst überwacht, ersetzt keine ausgefallenen Pods. Deployment heißt nicht Pod, sondern Soll-Stärke, die Kubernetes von selbst hält.
📌 Pod · Deployment · replicas
📚 Cloud von Grund auf · Tag 4 von 30
#kubernetes #devops #docker
Das Symptom: Nach jeder noch so kleinen Codeänderung läuft der Bau minutenlang durch. Pakete werden erneut installiert, obwohl sich daran nichts geändert hat. Der Build-Cache, also das Zwischenspeichern bereits gebauter Schritte, greift scheinbar nie.
Dahinter steckt das Schichtprinzip: Jede Zeile im Dockerfile (der Bauanleitung für ein Image) erzeugt eine eigene Schicht. Das fertige Image, also die unveränderliche Vorlage für Container, besteht aus diesen Schichten wie ein Stapel. Eine unveränderte Schicht wird aus dem Cache wiederverwendet. Ändert sich eine Zeile, wird sie neu gebaut, und alle folgenden ebenso, weil sie auf dem Ergebnis aufbauen. Steht COPY, das Kopieren eigener Dateien, früh im Dockerfile, macht jede Codeänderung den Rest ungültig.
Konkret: Ein Dockerfile beginnt mit FROM, dann RUN zum Installieren der Abhängigkeiten, dann erst COPY des Quellcodes. Wer umgekehrt erst den Code kopiert und danach RUN ausführt, baut die Abhängigkeiten bei jedem Fix neu. Die Regel lautet: Anweisungen mit selten ändernden Inhalten wie RUN an den Anfang, Anweisungen mit häufig ändernden Inhalten wie COPY ans Ende.
So prüft man es: Beim Bau die Ausgabe der Zeilen ansehen, die als wiederverwendet markiert sind. Zeigen die frühen Zeilen wie die Abhängigkeiten einen Treffer und startet der Neubau erst beim Kopieren des Quellcodes, stimmt die Anordnung.
Schichten sind keine Zufallsprodukte, sondern ein Stapel: Ein früher Treffer im Cache spart alles darunter. Ordnung im Dockerfile heißt Reihenfolge nach Änderungshäufigkeit.
📌 Dockerfile-Schichten · Build-Cache · Reihenfolge nach Änderungshäufigkeit
📚 Cloud von Grund auf · Tag 4 von 30
#docker #kubernetes #devops
Die Verwechslung liegt an der Sprache: Docker nennt beides fast gleich, und die Begriffe treten immer paarweise auf. Ein Fehler im laufenden Container zeigt sich erst später als verlorene Arbeit.
Ein Image ist eine unveränderliche Vorlage: eine Datei-Sammlung, in der Anwendung, Laufzeit-Umgebung, Bibliotheken und Konfiguration fest eingefroren sind. Nach dem Bau wird es nicht mehr geändert, sondern nur durch ein neues ersetzt – das Prinzip heißt Immutable Infrastructure. Beschrieben wird der Bau in einem Dockerfile, einer Schritt-für-Schritt-Anleitung. Beispiel: Ein Image enthält Python in einer festen Version plus den eigenen Anwendungscode.
Ein Container ist die laufende Instanz, die aus genau diesem Image gestartet wird. Er verpackt die Anwendung mit ihren Abhängigkeiten und teilt sich den Kernel (den Kern) des Host-Betriebssystems, startet dadurch schneller als eine virtuelle Maschine. Aus ein und demselben Image lassen sich beliebig viele Container starten, die alle identisch beginnen. Beispiel: Drei Container aus demselben Python-Image laufen gleichzeitig auf drei Rechnern.
Das Image bleibt unverändert, der Container ist vergänglich. Jede Änderung am laufenden Container verliert mit dessen Löschung ihre Spur.
Faustregel: Änderungen gehören immer in ein neues Image, das man über das Dockerfile baut – niemals in den laufenden Container.
Ein Image ist die Vorlage, ein Container deren laufende Kopie. Wer am Container schraubt, arbeitet im Sandkasten; wer am Image baut, arbeitet für jeden künftigen Start.
📌 Image = Vorlage · Container = Instanz · Änderungen ins Dockerfile
📚 Cloud von Grund auf · Tag 3 von 30
#docker #devops #kubernetes
Wer nicht systematisch danach sucht, merkt den Ausfall erst, wenn Nutzer eine Fehlerseite sehen. Betroffen ist jede Cloud-Anwendung, die ohne Ausfallschutz betrieben wird.
Ein Single Point of Failure ist eine Komponente, deren Ausfall das ganze System stoppt. Hochverfügbarkeit entsteht, indem genau solche Komponenten mehrfach vorhanden sind. Erst wenn eine zweite Instanz die Arbeit übernehmen kann, ist der Ausfall abgefangen.
Man geht den Weg einer Anfrage von vorne nach hinten durch – DNS (übersetzt Domainnamen in IP-Adressen), Load Balancer (ein Verkehrsverteiler vor den Servern), Anwendungsserver, Datenbank, Speicher. Eine Anwendung, die nur in einer einzigen Availability Zone (einem Rechenzentrumverbund mit eigener Stromversorgung und Netzanbindung) läuft, hat daher einen Single Point of Failure: Fällt diese Zone aus, ist die Anwendung weg. Der Ausfallschutz entsteht erst durch das Betreiben in mindestens zwei Zonen. Auch vorne droht eine Falle: Ein Load Balancer, der alleinstehend vor der Anwendung sitzt, ist selbst ein Single Point of Failure. In Kubernetes fängt ein Deployment mit mehreren Pods (kleinste Einheit in Kubernetes mit einem oder mehreren Containern) den Ausfall einzelner Pods ab; ein Service gibt ihnen eine stabile Adresse und verteilt Anfragen, auch wenn Pods neu starten.
Verwechselt wird der Single Point of Failure oft mit Redundanz an nur einer Stelle. Die nützt nichts, wenn dahinter alles über genau eine Instanz läuft.
Ein Single Point of Failure ist also nicht „ein kaputtes Teil“, sondern die einzige Instanz, an der alles hängt.
📌 Anfrage-Weg abgehen · einzige Instanz prüfen · zweite Zone einplanen
📚 Cloud von Grund auf · Tag 3 von 30
#aws #sre
Was wir unterschätzt haben: Persistent Volumes und StatefulSets sind deutlich trickreicher als Stateless-Deployments. Unsere PostgreSQL-Migration auf K8s hat 3 Anläufe gebraucht. Lesson learned: Datenbanken gehören (noch) nicht in Kubernetes, es sei denn man hat dediziertes DB-Ops-Know-how.
Was sich gelohnt hat: GitOps-Workflow mit ArgoCD, automatische Rollbacks bei fehlgeschlagenen Health-Checks, und Resource-Quotas die verhindern dass ein Team den gesamten Cluster lahmlegt. #kubernetes #devops #cloudnative