Skip to content

EN_CS_StatefulSet

somaz edited this page Sep 22, 2026 · 4 revisions

Q6: Stateful Applications (StatefulSet) and Stateless Applications

Question: Explain the difference between Stateful applications (StatefulSet) and Stateless applications, and how each is deployed and scaled in Kubernetes. Focus on the role of Persistent Volumes, Headless Services, and stable Pod identifiers.


Key Terms

Term Description
StatefulSet Kubernetes object that manages applications with state
Stateless Application Application that keeps no internal state and handles each request independently
Headless Service Service whose ClusterIP is None — returns Pod IPs directly
Ordinal Index Ordinal number of a StatefulSet Pod (pod-0, pod-1, pod-2)
PVC (PersistentVolumeClaim) Object through which a Pod requests a PV
volumeClaimTemplates Template that automatically creates a PVC for each Pod in a StatefulSet

Stateless vs Stateful Concepts

Stateless (Deployment):               Stateful (StatefulSet):
┌──────┐ ┌──────┐ ┌──────┐           ┌──────────┐ ┌──────────┐ ┌──────────┐
│Pod A │ │Pod B │ │Pod C │           │ mysql-0  │ │ mysql-1  │ │ mysql-2  │
│      │ │      │ │      │           │ (Master) │ │ (Slave)  │ │ (Slave)  │
└──────┘ └──────┘ └──────┘           │  PV-0    │ │  PV-1    │ │  PV-2    │
         ↓                           └──────────┘ └──────────┘ └──────────┘
  Shared Database                         └─────── Replication ──────┘
  (External State)

Stateless vs Stateful Comparison

Aspect Stateless (Deployment) Stateful (StatefulSet)
Pod Name Random (nginx-abc123) Ordinal (mysql-0, mysql-1)
Creation Order Can be created simultaneously Sequential creation (0 → 1 → 2)
Deletion Order Can be deleted simultaneously Reverse-order deletion (2 → 1 → 0)
Network Identity Unstable (Pod IP changes) Stable (DNS preserved)
Storage Shared or none PVC per Pod
Service Type ClusterIP / LoadBalancer Headless + ClusterIP
Use Cases Web servers, API servers DBs, messaging, distributed storage

Kubernetes Deployment (Stateless)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"

Rolling Update:

  • maxSurge: 1 → allows up to replica+1 Pods running at the same time
  • maxUnavailable: 0 → always keeps the replica count (zero downtime)

Kubernetes StatefulSet (Stateful)

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-headless   # Headless Service required
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:          # Auto-creates a PVC per Pod
  - metadata:
      name: mysql-data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: gp3
      resources:
        requests:
          storage: 10Gi

Headless Service

Setting clusterIP: None returns Pod IPs directly, without a VIP.

apiVersion: v1
kind: Service
metadata:
  name: mysql-headless
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
  - port: 3306

DNS lookup result:

mysql-headless → 10.244.1.10 (mysql-0)
              → 10.244.2.20 (mysql-1)
              → 10.244.3.30 (mysql-2)

Per-Pod DNS:
mysql-0.mysql-headless.default.svc.cluster.local → 10.244.1.10
mysql-1.mysql-headless.default.svc.cluster.local → 10.244.2.20

DNS names persist even after a Pod restart → Master/Slave can be addressed directly.


Persistent Volume Management

  • Deleting a StatefulSet does not delete the PVCs (data is preserved)
  • When a Pod is recreated, the existing PVC is reused
  • PVCs must be deleted manually: kubectl delete pvc mysql-data-mysql-0

Volume expansion (requires allowVolumeExpansion: true in the StorageClass):

kubectl patch pvc mysql-data-mysql-0 \
  -p '{"spec":{"resources":{"requests":{"storage":"20Gi"}}}}'

Update Strategy

Strategy Behavior
RollingUpdate (default) Sequential update in reverse order (mysql-2 → mysql-1 → mysql-0)
OnDelete No automatic update; a Pod is recreated with the new version when manually deleted

To create and delete all Pods at once without ordering, use the separate field podManagementPolicy: Parallel (default OrderedReady), not an update strategy.


→ Back to List

Clone this wiki locally