StatefulSets & Beständig Lagring i Kubernetes
Distribuera tillståndsbaserade appar med ordnad skalning och bestående data
Kubernetes StatefulSets är den bästa lösningen för att hantera tillståndsbaserade applikationer som kräver stabila identiteter, permanent lagring och ordnade distributionsmönster - essentiellt för databaser, distribuerade system och cache-lager.
Om du är ny på Kubernetes eller sätter upp en kluster, överväg att utforska Kubernetes distributioner som k3s eller MicroK8s för utveckling, eller installera Kubernetes med Kubespray för produktionskluster.
Det här trevliga bilden är genererad av AI-modellen Flux 1 dev.
Vad är StatefulSets?
StatefulSets är ett Kubernetes arbetsbelastnings-API-objekt som är speciellt utformat för att hantera tillståndsbaserade applikationer. Till skillnad från Deployments som behandlar alla pods som utbytbara, upprätthåller StatefulSets en unik identitet för varje pod med garantier om ordning och unikhet.
Nyckelfunktioner:
- Stabila nätverksidentifierare: Varje pod får ett förutsägbart värdnamn som består över omstart
- Permanent lagring: Dedikerade PersistentVolumeClaims som följer pods genom omplanering
- Ordnad distribution: Pods skapas sekventiellt (0, 1, 2…) och avslutas i omvänd ordning
- Ordnade uppdateringar: Rullande uppdateringar fortsätter i ordning, vilket säkerställer applikationsstabilitet
StatefulSets är kritiska för applikationer som PostgreSQL, MySQL, MongoDB, Cassandra, Elasticsearch, Kafka, ZooKeeper, Redis och etcd - alla arbetsbelastningar där podidentitet och datapermanens är viktiga.
Förstå permanent lagring i Kubernetes
Kubernetes erbjuder ett sofistikerat lagringsabstraktionslager som separerar lagringshantering från podlivscykeln:
Lagringskomponenter
PersistentVolume (PV): Ett lagringsutrymme i klustret som tillhandahålls av en administratör eller skapas dynamiskt via en StorageClass. PVs existerar oberoende av pods.
PersistentVolumeClaim (PVC): En begäran om lagring av en pod. PVCs binder till tillgängliga PVs som matchar deras krav (storlek, åtkomstläge, lagringsklass).
StorageClass: Definierar olika “klasser” av lagring med olika tillhandahållare (AWS EBS, GCE PD, Azure Disk, NFS etc.) och parametrar som replikering, prestanda-nivåer och säkerhetskopieringspolicyer.
Åtkomstlägen
- ReadWriteOnce (RWO): Volymen monteras som skriv- och läsläsbar av en enda nod
- ReadOnlyMany (ROX): Volymen monteras som skriftläsbar av många noder
- ReadWriteMany (RWX): Volymen monteras som skriv- och läsläsbar av många noder (kräver specialiserade lagringsbackends)
StatefulSet-lagringsarkitektur
StatefulSets använder volumeClaimTemplates för att automatiskt skapa PersistentVolumeClaims för varje podreplica. Detta skiljer sig fundamentalt från Deployments:
Hur volumeClaimTemplates fungerar
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
När du skapar denna StatefulSet:
- Kubernetes skapar pod
mysql-0och PVCdata-mysql-0 - Sedan skapar den pod
mysql-1och PVCdata-mysql-1 - Slutligen skapar den pod
mysql-2och PVCdata-mysql-2
Varje pod får sin egen dedikerade 10GB permanenta volym. Om mysql-1 tas bort eller omplaneras, återskapar Kubernetes den och bifogar samma data-mysql-1 PVC, vilket bevarar all data.
Skapa en Headless Service för StatefulSets
StatefulSets kräver en Headless Service för att tillhandahålla stabila nätverksidentiteter:
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
clusterIP: None # Detta gör det till en headless service
selector:
app: mysql
ports:
- port: 3306
name: mysql
Detta skapar DNS-poster för varje pod:
mysql-0.mysql-service.default.svc.cluster.localmysql-1.mysql-service.default.svc.cluster.localmysql-2.mysql-service.default.svc.cluster.local
Applikationer kan ansluta direkt till specifika podinstanser med hjälp av dessa stabila DNS-namn.
StatefulSet-distributionsmönster
För team som hanterar komplexa Kubernetes-distributioner, erbjuder Helm Charts ett kraftfullt sätt att paketera och distribuera StatefulSets med mallning, versionshantering och beroendehantering. Helm förenklar hanteringen av StatefulSet-konfigurationer över olika miljöer.
Ordnad skalning
När du skalas upp från 3 till 5 replikor:
kubectl scale statefulset mysql --replicas=5
Kubernetes skapar pods i ordning: mysql-3 → väntar på Klar → mysql-4
När du skalas ner från 5 till 3:
kubectl scale statefulset mysql --replicas=3
Kubernetes avslutar i omvänd ordning: mysql-4 → väntar på avslut → mysql-3
Rullande uppdateringar
StatefulSets stöder två uppdateringsstrategier:
OnDelete: Manuella uppdateringar - pods uppdateras bara när du tar bort dem RollingUpdate: Automatiska sekventiella uppdateringar i omvänd ordningsföljd
spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 2 # Endast uppdatera pods med ordinal >= 2
Parametern partition möjliggör canary-distributioner - du kan uppdatera pods med höga nummer först och testa innan du rullar ut till alla replikor.
Lagringsbästa praxis
Dynamisk tillhandahållning
Använd alltid StorageClasses för dynamisk volymtillhandahållning:
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: Aktiverar storleksändring av PVC utan att återskapa dem
reclaimPolicy: Retain behåller PV-data efter PVC-radering, Delete tar bort den automatiskt
PVC-bevarandepolicyer
Kubernetes 1.23+ stöder persistentVolumeClaimRetentionPolicy:
spec:
persistentVolumeClaimRetentionPolicy:
whenDeleted: Retain # Bevara PVCs när StatefulSet tas bort
whenScaled: Delete # Ta bort PVCs när skalning sker
Alternativ:
- Retain: Bevara PVCs (standardbeteende, säkraste)
- Delete: Ta automatiskt bort PVCs (användbart för utvecklingsmiljöer)
Säkerhetskopieringsstrategier
Volymsnappshot: Använd VolumeSnapshot-resurser för att skapa säkerhetskopior vid specifika tidpunkter
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: mysql-snapshot-20251113
spec:
volumeSnapshotClassName: csi-snapclass
source:
persistentVolumeClaimName: data-mysql-0
Applikationsnivå-säkerhetskopior: Använd verktyg som mysqldump, pg_dump eller Velero för databasspecifika säkerhetskopior
Distribuerad replikering: Konfigurera applikationsnivåreplikering (MySQL-replikering, PostgreSQL-strömningsreplikering) som första försvar
Reella användningsområden
Databaskluster (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
Distribuerad cache (Redis)
För Redis-kluster behöver du både StatefulSet och noggrann 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
Meddelandekö (Kafka)
Kafka kräver både permanent lagring för loggar och stabila nätverksidentiteter för brokersamordning:
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
Övervakning och felsökning
För en omfattande referens av Kubernetes-kommandon som används i detta avsnitt, se Kubernetes Cheatsheet.
Kontrollera StatefulSet-status
# Visa StatefulSet detaljer
kubectl get statefulset mysql
kubectl describe statefulset mysql
# Kontrollera pod-skapsordning och status
kubectl get pods -l app=mysql -w
# Visa PVC-status
kubectl get pvc
kubectl describe pvc data-mysql-0
Vanliga problem
Pod fast i väntande: Kontrollera PVC-status och lagringsutrymme
kubectl describe pod mysql-0
kubectl get events --sort-by='.lastTimestamp'
Lagring full: Expandera PVC om StorageClass tillåter
kubectl patch pvc data-mysql-0 -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'
Pod vill inte avslutas: Kontrollera för applikationsnivålås eller volymavmonteringsproblem
kubectl delete pod mysql-0 --grace-period=0 --force
Mätvärden att övervaka
- Lagringsanvändning: Övervaka PVC-kapacitet och användningsprocent
- I/O-prestanda: Följ IOPS, genomströmning och latens
- Pod-omstartar: Frekventa omstartar kan indikera lagringsproblem
- PVC-bindningstid: Långsam binding tyder på tilldelningsproblem
Migrationsstrategier
När du migrerar till StatefulSets, se till att din Kubernetes-kluster är korrekt konfigurerad. För hemkluster eller små klustermiljöer, granska vårt omfattande jämförelse av Kubernetes-distributioner för att välja rätt plattform för dina arbetsbelastningskrav.
Från Deployment till StatefulSet
- Skapa StatefulSet med volumeClaimTemplates
- Minska skalning på Deployment på ett smidigt sätt
- Återställ data från backup till StatefulSet-pods
- Uppdatera DNS/Tjänst referenser
- Ta bort gammal Deployment och PVCs
Backup innan migration
# Ta snapshot av befintliga PVCs
kubectl get pvc -o yaml > pvc-backup.yaml
# Skapa volymsnapshots
kubectl apply -f volume-snapshot.yaml
Säkerhetsöverväganden
Lagringskryptering
Aktivera kryptering i vila med StorageClass-parametrar:
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
Åtkomstkontroll
Använd RBAC för att begränsa vem som kan skapa/ändra StatefulSets och PVCs:
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"]
Nätverksregler
Begränsa pod-till-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
Prestandaoptimering
Lagringsprestandatier
Välj lämpliga StorageClasses baserat på arbetsbelastning:
- Hög IOPS: Databaser med tung slumpmässig läsning/skrivning (gp3, io2)
- Hög genomströmning: Loggaggregering, analys (st1, sc1)
- Balanserad: Allmänna ändamål (gp3)
Pod-fördelning
Använd pod-anti-affinitet för att sprida StatefulSet-pods över tillgänglighetszoner:
spec:
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: mysql
topologyKey: topology.kubernetes.io/zone
Resursbehov och gränser
Ange lämpliga resurser för konsekvent prestanda:
resources:
requests:
cpu: "2"
memory: "4Gi"
ephemeral-storage: "10Gi"
limits:
cpu: "4"
memory: "8Gi"
ephemeral-storage: "20Gi"
Avancerade mönster
Statisk applikation med init-containers
Använd init-containers för databashantering:
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
Lägg till backup-sidecars eller övervakningsagenter:
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 dynamisk konfiguration
Separera konfiguration från 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
Användbara länkar
- Kubernetes StatefulSets Dokumentation
- Persistent Volumes
- Storage Classes
- Volume Snapshots
- StatefulSet Best Practices
- CSI Drivers
- Velero Backup Solutions
- Rook Ceph Storage
- Kubernetes Cheatsheet
- Installera Kubernetes med Kubespray
- Jämförelse av Kubernetes-distributioner för ett 3-nodskluster
- Kubernetes-distributioner - översikt av kubeadm, k3s, MicroK8s, Minikube, Talos Linux och RKE2
- Mästare Helm Charts: Guide för Kubernetes-pakethantering