Begriff
StatefulSet (K8s)
Warum wichtig?
Dieser Begriff ist ein Knoten im SengakujiWorks-Wissensnetz. Nutze Level 0 für die erste Einordnung, Level 1 für Praxis, Level 2 für technische Struktur und Level 3 für Grenzen, Fallstricke und Expertenkontext.
Deployments sind für Webserver (Rinder).
Alle Pods (web-x8z, web-9a1) sind gleich. Wenn einer stirbt, startet ein neuer. Egal welcher.
Datenbanken (Postgres, Mongo, Kafka) sind wie Haustiere (Pets).
Sie haben Namen (mongo-0, mongo-1).
Sie haben festen Wohnsitz (Disk).
mongo-0 ist der Master. mongo-1 ist der Slave.
Du kannst sie nicht beliebig tauschen.
Wenn mongo-0 stirbt, muss er als mongo-0 wiederkommen (mit derselben Disk!).
Das StatefulSet garantiert diese Ordnung.
Es startet sie auch nacheinander: Erst 0, dann 1, dann 2.
Merksatz: Ein Kubernetes-Controller für Anwendungen, die eine stabile Netzwerkidentität, persistenten Speicher und eine geordnete Bereitstellung/Skalierung benötigen.
Die Pods heißen immer name-0, name-1 usw. (Ordinal Index).
Sie haben auch stabile DNS-Namen: web-0.service.ns.svc.cluster.local.
Wichtig:
Du brauchst einen Headless Service (clusterIP: None), damit DNS funktioniert.
Du nutzt volumeClaimTemplates im YAML, damit jeder Pod seinen eigenen PVC (data-web-0, data-web-1) bekommt.
(Bei Deployments teilen sich alle den gleichen PVC oder crashen wegen RWO).
1. Ordered Graceful Termination
Wenn du ein Deployment skalierst (10 -> 0), killt es alle gleichzeitig (Chaos).
Ein StatefulSet killt immer umgekehrt zur Startreihenfolge: Erst 2, dann 1, dann 0.
Das erlaubt mongo-2 seine Daten an mongo-1 zu übergeben (Replication Drain), bevor er stirbt.
Datenbanken lieben das.
2. Pod Management Policies
Standard ist OrderedReady. (Warte auf 0, bis er Ready ist, dann starte 1).
Das dauert beim Starten ewig.
Für Cassandra oder Elasticsearch (die Peer-to-Peer sind und keine feste Master-Slave Ordnung brauchen) kannst du podManagementPolicy: Parallel setzen.
Dann starten alle 0, 1, 2 gleichzeitig. Schneller, aber immer noch stabile Namen.
3. Split Brain Probleme
Wenn ein Node "unreachable" ist (Netzwerk weg), weiß K8s nicht: Ist der Pod tot oder nur offline?
StatefulSet ist hyper-vorsichtig.
Es startet web-0 auf einem anderen Node niemals, solange es nicht sicher ist, dass der alte web-0 tot ist.
Grund: Wenn zwei web-0 gleichzeitig in dieselbe Disk schreiben, sind die Daten korrupt (Data Corruption).
Du musst den alten Pod oft manuell löschen (force delete), um den neuen zu starten. "Fencing".
Die Anatomie des Headless Service
Warum nutzt man bei StatefulSets keinen normalen, lastverteilenden Kubernetes-Service?
Ein normaler Service (ClusterIP) routet Traffic per Round-Robin auf einen beliebigen Pod. Bei einer Datenbank fragt dein Backend "Gib mir Datensatz X". Wenn Request 1 auf mysql-0 (Master) landet, wird X geschrieben. Wenn Request 2 auf mysql-1 (Read-Replica) landet, liest es den State. Um Daten direkt an den Primary Node zu schreiben, benötigt die App exaktes Routing.
Ein Headless Service (clusterIP: None) schaltet den Kube-Proxy komplett ab. Er erzeugt keine LoadBalancer-IP, sondern programmiert lediglich den Kube-DNS-Server. Fragst du mysql-svc.default.svc.cluster.local, erhältst du direkt ein Array aller einzelnen Pod-IPs. Und viel wichtiger: Kube-DNS generiert A-Records für jeden namentlichen Pod (mysql-0.mysql-svc...). So können Clients gezielt "Hallo Master" sagen.
Split-Brain & das Fencing-Dilemma
Was geschieht in einem StatefulSet bei einem Hard-Node-Crash (Netzwerk isoliert Node A vom Master-Plane, aber Node A und mongo-0 laufen lokal noch)?
Der K8s Controller-Manager verliert den Herzschlag von Node A (Status NotReady). Im Gegensatz zu Deployments, die den Pod sofort gnadenlos auf Node B neu spawnen würden (was zu zwei laufenden Applikationen führen würde, die denken, sie wären Master), friert der StatefulSet Controller ein. Er weigert sich (VolumeNodeAffinityConflict) mongo-0 woanders zu booten!
Würde er es tun, und das Netzwerkproblem behebt sich nach 10 Minuten, gäbe es plötzlich zwei Data-Writern im gleichen Dateisystem – das gefürchtete Split-Brain.
Der Admin muss den toten Node offiziell per API aus K8s evicten oder den Pod per kubectl delete --force --grace-period=0 zwingen. Erst dieser "Fencing"-Akt erlaubt ein sicheres Re-Scheduling.
PVC Retention Management
Wenn du ein Deployment löschst, sind die Pods weg.
Löschst du ein StatefulSet (kubectl delete sts my-db), verschwinden die Pods, aber alle erzeugten PVCs (data-my-db-0) bleiben untouched im Cluster!
Kubernetes hat die goldene Design-Regel: "Wir löschen niemals unaufgefordert Stateful-Volumen."
Wenn du die DB "sauber" entfernen willst, bist du für den Cleanup-Prozess selbst zuständig (kubectl delete pvc -l app=my-db). Wenn du jedoch denselben STS-Namen später neu deployt, adoptiert das neue StatefulSet sofort wieder die alten, überlebenden Datenträger.
Quick-Check
Warum "Pet Set"?
Der alte Name in Alpha Versionen. Anspielung auf "Cattle vs Pets". Deployments sind Cattle (austauschbar). StatefulSets sind Pets (einzigartig, müssen gepflegt werden).Update Strategie?
OnDelete: K8s macht gar nichts, wenn du das Image änderst. Du musst die Pods manuell löschen.RollingUpdate: K8s löscht erst Index N, wartet, dann Index N-1. Das ist sicherer für Leader Election.PVC Retain?
Wenn du das StatefulSet löschst, werden die PVCs nicht gelöscht. K8s sagt: "Daten sind heilig". Du musst die 50 PVCs manuell löschen, wenn du aufräumen willst.