StatefulSets & Persistente Speicherung in Kubernetes
Bereitstellen von zustandsbehafteten Anwendungen mit geordneter Skalierung und persistenter Daten
Kubernetes StatefulSets sind die optimale Lösung für die Verwaltung von zustandsbehafteten Anwendungen, die stabile Identitäten, dauerhafte Speicherung und geordnete Bereitstellungsmuster benötigen – essenziell für Datenbanken, verteilte Systeme und Caching-Schichten.
Wenn Sie neu bei Kubernetes sind oder einen Cluster einrichten, sollten Sie Kubernetes-Distributionen wie k3s oder MicroK8s für die Entwicklung in Betracht ziehen oder Kubernetes mit Kubespray installieren für produktionsreife Cluster.
Dieses schöne Bild wurde von der KI-Modell Flux 1 dev erstellt.
Was sind StatefulSets?
StatefulSets sind ein Kubernetes-Arbeitslast-API-Objekt, das speziell für die Verwaltung von zustandsbehafteten Anwendungen entwickelt wurde. Im Gegensatz zu Deployments, die alle Pods als austauschbar behandeln, erhalten StatefulSets eine eindeutige Identität für jeden Pod mit Garantien hinsichtlich Reihenfolge und Eindeutigkeit.
Wichtige Merkmale:
- Stabile Netzwerk-Identifikatoren: Jeder Pod erhält einen vorhersehbaren Hostnamen, der über Neustarts hinweg besteht
- Dauerhafter Speicher: Dedizierte PersistentVolumeClaims, die Pods durch Neuplanungen folgen
- Geordnete Bereitstellung: Pods werden sequenziell erstellt (0, 1, 2…) und in umgekehrter Reihenfolge beendet
- Geordnete Updates: Rollierende Updates erfolgen in Reihenfolge, um die Anwendungsstabilität zu gewährleisten
StatefulSets sind entscheidend für Anwendungen wie PostgreSQL, MySQL, MongoDB, Cassandra, Elasticsearch, Kafka, ZooKeeper, Redis und etcd – für jede Arbeitslast, bei der Pod-Identität und Datenspeicherung wichtig sind.
Verständnis des dauerhaften Speichers in Kubernetes
Kubernetes bietet eine ausgefeilte Speicherabstraktionsschicht, die die Speicherverwaltung vom Pod-Lebenszyklus entkoppelt:
Speicherkomponenten
PersistentVolume (PV): Ein Speicherstück im Cluster, das von einem Administrator bereitgestellt oder dynamisch über eine StorageClass erstellt wird. PVs existieren unabhängig von Pods.
PersistentVolumeClaim (PVC): Eine Speicheranforderung durch einen Pod. PVCs binden an verfügbare PVs, die ihren Anforderungen (Größe, Zugriffsmodus, Speicherklasse) entsprechen.
StorageClass: Definiert verschiedene “Klassen” von Speicher mit verschiedenen Provisionern (AWS EBS, GCE PD, Azure Disk, NFS usw.) und Parametern wie Replikation, Leistungsebenen und Backup-Richtlinien.
Zugriffsmodi
- ReadWriteOnce (RWO): Volume wird als Schreib-Lese von einem einzelnen Knoten gemountet
- ReadOnlyMany (ROX): Volume wird als schreibgeschützt von vielen Knoten gemountet
- ReadWriteMany (RWX): Volume wird als Schreib-Lese von vielen Knoten gemountet (erfordert spezielle Speicher-Backends)
StatefulSet-Speicherarchitektur
StatefulSets verwenden volumeClaimTemplates, um automatisch PersistentVolumeClaims für jede Pod-Replik zu erstellen. Dies unterscheidet sich grundlegend von Deployments:
Wie volumeClaimTemplates funktionieren
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql-service
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: data
mountPath: /var/lib/mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "fast-ssd"
resources:
requests:
storage: 10Gi
Wenn Sie diesen StatefulSet erstellen:
- Kubernetes erstellt den Pod
mysql-0und den PVCdata-mysql-0 - Dann erstellt es den Pod
mysql-1und den PVCdata-mysql-1 - Schließlich erstellt es den Pod
mysql-2und den PVCdata-mysql-2
Jeder Pod erhält seinen eigenen dedizierten 10GB dauerhaften Speicher. Wenn mysql-1 gelöscht oder neu geplant wird, erstellt Kubernetes es neu und bindet den gleichen data-mysql-1 PVC, wodurch alle Daten erhalten bleiben.
Erstellung eines Headless Service für StatefulSets
StatefulSets benötigen einen Headless Service, um stabile Netzwerkidentitäten bereitzustellen:
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
clusterIP: None # Dies macht es zu einem headless Service
selector:
app: mysql
ports:
- port: 3306
name: mysql
Dies erstellt DNS-Einträge für jeden Pod:
mysql-0.mysql-service.default.svc.cluster.localmysql-1.mysql-service.default.svc.cluster.localmysql-2.mysql-service.default.svc.cluster.local
Anwendungen können sich direkt mit spezifischen Pod-Instanzen über diese stabilen DNS-Namen verbinden.
StatefulSet-Bereitstellungsmuster
Für Teams, die komplexe Kubernetes-Bereitstellungen verwalten, bieten Helm-Charts eine leistungsstarke Möglichkeit, StatefulSets mit Vorlagen, Versionierung und Abhängigkeitsverwaltung zu paketieren und bereitzustellen. Helm vereinfacht die Verwaltung von StatefulSet-Konfigurationen in verschiedenen Umgebungen.
Geordnetes Skalieren
Beim Hochskalieren von 3 auf 5 Replikate:
kubectl scale statefulset mysql --replicas=5
Kubernetes erstellt Pods in Reihenfolge: mysql-3 → wartet auf Bereit → mysql-4
Beim Herunterskalieren von 5 auf 3:
kubectl scale statefulset mysql --replicas=3
Kubernetes beendet in umgekehrter Reihenfolge: mysql-4 → wartet auf Beendigung → mysql-3
Rollierende Updates
StatefulSets unterstützen zwei Update-Strategien:
OnDelete: Manuelle Updates – Pods werden nur aktualisiert, wenn Sie sie löschen RollingUpdate: Automatische sequenzielle Updates in umgekehrter Ordnungsreihenfolge
spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 2 # Nur Pods mit Ordnungszahl >= 2 aktualisieren
Der Parameter partition ermöglicht Canary-Bereitstellungen – Sie können zunächst hoch nummerierte Pods aktualisieren und testen, bevor Sie auf alle Replikate ausrollen.
Speicher-Best Practices
Dynamische Bereitstellung
Verwenden Sie immer StorageClasses für die dynamische Volumenbereitstellung:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp3
iops: "3000"
throughput: "125"
allowVolumeExpansion: true
reclaimPolicy: Retain
allowVolumeExpansion: Ermöglicht das Vergrößern von PVCs ohne Neu-Erstellung
reclaimPolicy: Retain behält PV-Daten nach PVC-Löschung, Delete entfernt sie automatisch
PVC-Retentionsrichtlinien
Kubernetes 1.23+ unterstützt persistentVolumeClaimRetentionPolicy:
spec:
persistentVolumeClaimRetentionPolicy:
whenDeleted: Retain # PVCs behalten, wenn StatefulSet gelöscht wird
whenScaled: Delete # PVCs löschen, wenn herunterskaliert wird
Optionen:
- Retain: PVCs behalten (Standardverhalten, sicherste Option)
- Delete: PVCs automatisch löschen (nützlich für Entwicklungsumgebungen)
Backup-Strategien
Volume Snapshots: Verwenden Sie VolumeSnapshot-Ressourcen, um Backups zum Zeitpunkt der Erstellung zu erstellen
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: mysql-snapshot-20251113
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: data-mysql-0
Anwendungsbezogene Backups: Verwenden Sie Tools wie mysqldump, pg_dump oder Velero für datenbankspezifische Backups
Verteilte Replikation: Konfigurieren Sie die Replikation auf Anwendungsebene (MySQL-Replikation, PostgreSQL-Streaming-Replikation) als erste Verteidigungslinie
Echte Anwendungsfälle
Datenbank-Cluster (PostgreSQL)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "standard"
resources:
requests:
storage: 20Gi
Verteilter Cache (Redis)
Für Redis-Cluster benötigen Sie sowohl StatefulSet als auch sorgfältige Konfiguration:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis-service
replicas: 6
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
command:
- redis-server
- "--appendonly"
- "yes"
- "--appendfsync"
- "everysec"
ports:
- containerPort: 6379
name: redis
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 5Gi
Nachrichtenwarteschlange (Kafka)
Kafka benötigt sowohl dauerhaften Speicher für Protokolle als auch stabile Netzwerkidentitäten für die Broker-Koordination:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: kafka
spec:
serviceName: kafka-service
replicas: 3
selector:
matchLabels:
app: kafka
template:
metadata:
labels:
app: kafka
spec:
containers:
- name: kafka
image: confluentinc/cp-kafka:7.5.0
ports:
- containerPort: 9092
name: kafka
env:
- name: KAFKA_BROKER_ID
valueFrom:
fieldRef:
fieldPath: metadata.name
volumeMounts:
- name: data
mountPath: /var/lib/kafka/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Gi
Überwachung und Fehlerbehebung
Für eine umfassende Referenz der in diesem Abschnitt verwendeten Kubernetes-Befehle siehe den Kubernetes Cheatsheet.
StatefulSet-Status prüfen
# StatefulSet-Details anzeigen
kubectl get statefulset mysql
kubectl describe statefulset mysql
# Pod-Erstellungsreihenfolge und -status prüfen
kubectl get pods -l app=mysql -w
# PVC-Status anzeigen
kubectl get pvc
kubectl describe pvc data-mysql-0
Häufige Probleme
Pod bleibt im Status “Pending”: Prüfen Sie den PVC-Status und die Speicherverfügbarkeit
kubectl describe pod mysql-0
kubectl get events --sort-by='.lastTimestamp'
Speicher voll: Erweitern Sie den PVC, falls die StorageClass dies zulässt
kubectl patch pvc data-mysql-0 -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
Pod wird nicht beendet: Prüfen Sie auf Anwendungslevel-Sperren oder Volume-Unmount-Probleme
kubectl delete pod mysql-0 --grace-period=0 --force
Zu überwachende Metriken
- Speichernutzung: Überwachen Sie die PVC-Kapazität und den Nutzungsprozentsatz
- I/O-Leistung: Verfolgen Sie IOPS, Durchsatz und Latenz
- Pod-Neustarts: Häufige Neustarts können auf Speicherprobleme hinweisen
- PVC-Bindungszeit: Langsame Bindung deutet auf Bereitstellungsprobleme hin
Migrationsstrategien
Beim Migrieren zu StatefulSets stellen Sie sicher, dass Ihr Kubernetes-Cluster richtig konfiguriert ist. Für Homelab- oder kleine Cluster-Setups überprüfen Sie unseren umfassenden Vergleich von Kubernetes-Distributionen, um die richtige Plattform für Ihre Workload-Anforderungen zu wählen.
Von Deployment zu StatefulSet
- StatefulSet erstellen mit volumeClaimTemplates
- Deployment herunterskalieren sanft
- Daten wiederherstellen aus Backups zu StatefulSet-Pods
- DNS/Dienst-Referenzen aktualisieren
- Altes Deployment und PVCs löschen
Backup vor der Migration
# Snapshots bestehender PVCs erstellen
kubectl get pvc -o yaml > pvc-backup.yaml
# Volumesnapshots erstellen
kubectl apply -f volume-snapshot.yaml
Sicherheitsüberlegungen
Speicherverschlüsselung
Aktivieren Sie die Verschlüsselung im Ruhezustand mit StorageClass-Parametern:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: encrypted-storage
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp3
encrypted: "true"
kmsKeyId: arn:aws:kms:us-east-1:123456789012:key/abcd-1234
Zugriffskontrolle
Verwenden Sie RBAC, um zu beschränken, wer StatefulSets und PVCs erstellen/ändern darf:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: statefulset-manager
rules:
- apiGroups: ["apps"]
resources: ["statefulsets"]
verbs: ["get", "list", "create", "update", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "create", "delete"]
Netzwerkrichtlinien
Einschränken der Pod-zu-Pod-Kommunikation:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mysql-network-policy
spec:
podSelector:
matchLabels:
app: mysql
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 3306
Leistungsoptimierung
Speicherleistungsklassen
Wählen Sie geeignete StorageClasses basierend auf der Workload:
- Hohe IOPS: Datenbanken mit starkem zufälligen Lesen/Schreiben (gp3, io2)
- Hoher Durchsatz: Log-Aggregation, Analysen (st1, sc1)
- Ausgewogen: Allgemeine Anwendungen (gp3)
Pod-Verteilung
Verwenden Sie Pod-Anti-Affinität, um StatefulSet-Pods über Verfügbarkeitszonen zu verteilen:
spec:
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: mysql
topologyKey: topology.kubernetes.io/zone
Ressourcenanforderungen und -grenzen
Legen Sie geeignete Ressourcen für eine konsistente Leistung fest:
resources:
requests:
cpu: "2"
memory: "4Gi"
ephemeral-storage: "10Gi"
limits:
cpu: "4"
memory: "8Gi"
ephemeral-storage: "20Gi"
Fortgeschrittene Muster
Stateful-Anwendung mit Init-Containern
Verwenden Sie Init-Container für die Datenbankinitialisierung:
spec:
template:
spec:
initContainers:
- name: init-mysql
image: mysql:8.0
command:
- bash
- "-c"
- |
if [[ ! -d /var/lib/mysql/mysql ]]; then
mysqld --initialize-insecure --datadir=/var/lib/mysql
fi
volumeMounts:
- name: data
mountPath: /var/lib/mysql
Multi-Container-Pods für Sidecars
Fügen Sie Backup-Sidecars oder Überwachungsagenten hinzu:
spec:
template:
spec:
containers:
- name: mysql
image: mysql:8.0
# ... mysql-Konfiguration ...
- name: backup-sidecar
image: mysql-backup:latest
volumeMounts:
- name: data
mountPath: /var/lib/mysql
readOnly: true
ConfigMaps für dynamische Konfiguration
Trennen Sie die Konfiguration von der StatefulSet-Definition:
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
data:
my.cnf: |
[mysqld]
max_connections=200
innodb_buffer_pool_size=2G
---
spec:
template:
spec:
containers:
- name: mysql
volumeMounts:
- name: config
mountPath: /etc/mysql/conf.d
volumes:
- name: config
configMap:
name: mysql-config
Nützliche Links
- Kubernetes StatefulSets-Dokumentation
- Persistent Volumes
- Storage Classes
- Volume Snapshots
- StatefulSet-Best Practices
- CSI-Treiber
- Velero-Backup-Lösungen
- Rook Ceph Storage
- Kubernetes Cheatsheet
- Installation von Kubernetes mit Kubespray
- Vergleich von Kubernetes-Distributionen für ein 3-Knoten-Homelab
- Kubernetes-Distributionen - kurzer Überblick über kubeadm, k3s, MicroK8s, Minikube, Talos Linux und RKE2
- Meistern Sie Helm Charts: Kubernetes-Paketverwaltungsleitfaden