Adetayo Akinsanya unkletayo.dev

Stateful Workloads: StatefulSets, Stable Network Identities, and Ordered Scaling

Understanding ordinal indexing, headless services, volumeClaimTemplates, and ordered provisioning.

Adetayo Akinsanya (unkletayo) 2026-09-18

Part 10 in Series — Catch up on the previous article: Controllers Deep Dive: ReplicaSets, Deployments, and Rolling Update Mechanics (Part 9) before diving into this post.

An engineering team attempts to deploy a 3-node distributed database cluster (such as Apache Cassandra, Kafka, or PostgreSQL) using a standard Kubernetes Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cassandra
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: cassandra
        image: cassandra:4.1

Within hours, the database cluster collapses:

  1. Random Pod Names: When Pods restart, their names change randomly (cassandra-7d4f9b-x9k42 \to cassandra-9f8e7d-a1b2c), breaking database cluster peer configuration lists.
  2. Shared Volume Race Conditions: All 3 database pods attempt to mount the exact same storage volume concurrently, causing data file corruption.
  3. Unordered Startup: Pods initialize simultaneously before the primary seed database node finishes creating schema tables.

Why did a standard Deployment fail for a database cluster?

Deployments treat Pods as stateless, interchangeable, disposable entities.

For stateful applications requiring unique network identities, dedicated persistent storage, and ordered startup/teardown, Kubernetes provides the StatefulSet.


1. Deployments vs StatefulSets

To understand stateful workloads, we must contrast how Deployments and StatefulSets handle Pod identity:

DEPLOYMENT (Stateless Interchangeable Replicas)  STATEFULSET (Stateful Unique Entities)

[ Pod: web-7d4f9-x9k42 ]                           [ Pod: kafka-0 ] <---> [ Volume: data-kafka-0 ]
[ Pod: web-7d4f9-a1b2c ]                           [ Pod: kafka-1 ] <---> [ Volume: data-kafka-1 ]
[ Pod: web-7d4f9-9f8e7 ]                           [ Pod: kafka-2 ] <---> [ Volume: data-kafka-2 ]

- Random hash names                                - Deterministic ordinal index (0, 1, 2)
- Replaced by ANY new Pod                          - Replaced by EXACT SAME ordinal name
- Shared / ephemeral storage                       - Dedicated 1-to-1 persistent volume
- Scaled concurrently                              - Scaled strictly in sequential order

2. The Four Guarantees of a StatefulSet

A StatefulSet provides four core structural guarantees required by distributed databases, search indexes, and message brokers:

1. Stable Ordinal Indexing

Pods in a StatefulSet receive a deterministic, zero-based integer index:

Pod Name=StatefulSet NameOrdinal Index\text{Pod Name} = \text{StatefulSet Name} - \text{Ordinal Index}

For a StatefulSet named kafka with replicas: 3, the Pods are named kafka-0, kafka-1, and kafka-2.

If kafka-1 crashes or gets rescheduled onto another worker node, its replacement Pod is guaranteed to be named kafka-1.


2. Stable Network Identity via Headless Services

StatefulSets require a Headless Service (clusterIP: None) to establish persistent network identities for every individual Pod.

# Headless Service (No virtual ClusterIP):
apiVersion: v1
kind: Service
metadata:
  name: kafka-service
spec:
  clusterIP: None # Headless!
  selector:
    app: kafka

Each Pod acquires a persistent DNS domain record that remains fixed across restarts and node rescheduling:

Pod Domain=$(pod-name).$(service-name).$(namespace).svc.cluster.local\text{Pod Domain} = \text{\$(pod-name)}.\text{\$(service-name)}.\text{\$(namespace)}.svc.cluster.local

kafka-0.kafka-service.default.svc.cluster.local  -> Resolves to IP of kafka-0
kafka-1.kafka-service.default.svc.cluster.local  -> Resolves to IP of kafka-1
kafka-2.kafka-service.default.svc.cluster.local  -> Resolves to IP of kafka-2

Database peers can hardcode kafka-0.kafka-service in configuration files with 100% confidence that DNS will always route traffic to the 0 ordinal node!


3. Dedicated Storage via volumeClaimTemplates

Instead of sharing a volume, a StatefulSet creates a dedicated, 1-to-1 PersistentVolumeClaim (PVC) for each ordinal index Pod:

spec:
  serviceName: "kafka-service"
  replicas: 3
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 100Gi

When kafka-1 is created, Kubernetes binds PVC data-kafka-1 exclusively to kafka-1. If kafka-1 is rescheduled onto another node, data-kafka-1 follows kafka-1 to the new node.


4. Ordered Graceful Provisioning & Teardown

StatefulSets scale Pods strictly in sequential order:

  • Scaling Up (0120 \to 1 \to 2): kafka-0 must become Running and Ready before kafka-1 begins initialization.
  • Scaling Down (2102 \to 1 \to 0): kafka-2 is completely terminated and unmounted before kafka-1 shutdown begins.

Deployments vs StatefulSets Feature Matrix

FeatureDeploymentStatefulSet
Pod Naming SchemeRandom hash suffix (web-7d4f9b-x9k42)Deterministic ordinal index (kafka-0)
Network IdentityDynamic, ephemeral Pod IPsStable DNS domain via Headless Service
Storage BindingShared volume or ephemeral layerDedicated 1-to-1 PVC per ordinal (volumeClaimTemplates)
Scaling OrderParallel / Concurrent startupSequential ordered startup (0120 \to 1 \to 2)
Primary Use CaseStateless Web APIs, microservicesDatabases (Postgres, MySQL, Kafka, Elasticsearch)

Summary & Next Steps

StatefulSets manage applications that require identity and state persistence:

  • Deployments treat Pods as stateless, interchangeable units.
  • StatefulSets assign deterministic Ordinal Indexes (pod-0) that persist across restarts.
  • Headless Services (clusterIP: None) provide persistent per-Pod DNS domains (pod-0.service-name).
  • volumeClaimTemplates provision 1-to-1 dedicated PersistentVolumes bound exclusively to each ordinal index.
  • Ordered Scaling ensures database cluster nodes initialize and terminate in predictable sequence.

In the next article, we transition to Module 4 and explore The Kubernetes Pod Networking Model: Flat IP-per-Pod Networks and CNI Plugins.

References & Further Reading

  1. Cloud Native Computing Foundation. CNCF Container Network Interface (CNI) Specification v1.0.0. CNCF GitHub.
  2. Isovalent. eBPF-based Networking, Observability, and Security Architecture in Cilium. Cilium Docs.
  3. Tigera. IP-in-IP and VXLAN Overlay Networking in Calico. Calico Docs.

Up Next in Series →

Part 11: The Kubernetes Pod Networking Model: Flat IP-per-Pod Networks and CNI Plugins

Continue to Part 11 →