What is a StatefulSet?
StatefulSet is the workload API object used to manage stateful applications. It manages the deployment and scaling of a set of Pods, and provides guarantees about the ordering and uniqueness of these Pods.
Key Characteristics
- For Pods that must persist or maintain state
- Maintains a sticky identity for each Pod
- Each Pod has a persistent identifier (name-0, name-1, etc.)
- If a pod dies, it's replaced with another using the same identifier
- Creates Pods in sequence from 0 to X and deletes them from X to 0
Typical Use Cases
- Stable, unique network identifiers
- Databases using persistent storage (MySQL, PostgreSQL, MongoDB)
- Applications requiring stable persistent storage
- Applications needing ordered deployment and scaling
Stateful vs Stateless Containers
Containers are stateless by design, but StatefulSets offer a solution for stateful scenarios. However, a better approach could be to use Cloud provider database services when possible.
Important: Deleting a StatefulSet will not delete the Persistent Volume Claims (PVCs). You have to delete them manually.
kubectl Commands for StatefulSets
Create a StatefulSet
List StatefulSets
Get Detailed Info
Delete a StatefulSet
kubectl delete sts [statefulSetName]
Two ways to delete: using the YAML file or the StatefulSet name
StatefulSet YAML Configuration
A StatefulSet requires a Headless Service to manage the network identity of the Pods. Here's a complete example:
# Headless Service
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
ports:
- name: mysql
port: 3306
clusterIP: None
selector:
app: mysql
---
# StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql
replicas: 4
selector:
matchLabels:
run: nginx-sts-demo
template:
metadata:
labels:
run: nginx-sts-demo
spec:
containers:
- name: init-mysql
image: mysql:5.7
volumeMounts:
- name: conf
mountPath: /mnt/conf.d
volumeClaimTemplates:
- metadata:
name: data
spec:
storageClassName: default
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 16Gi
Key Configuration Elements:
- serviceName: Must match the name of the Headless Service
- volumeClaimTemplates: Defines PVCs that will be created for each Pod
- stable network identity: Each Pod gets a stable hostname based on its ordinal index
- ordered operations: Pods are created sequentially and terminated in reverse order
Headless Service
A Headless Service is used to control the domain of the StatefulSet. It doesn't provide load balancing or a stable IP, but allows direct Pod-to-Pod communication.
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
ports:
- name: mysql
port: 3306
clusterIP: None # This makes it a Headless Service
selector:
app: mysql
Write Operations
Use specific pod hostname for write operations:
This directs writes to the primary/master pod (mysql-0)
Read Operations
Use service name for read operations:
This allows load balancing across all replicas for reads
Important: The clusterIP: None field is what makes this a
Headless Service. Without it, the Service would get a cluster IP and load balance
traffic.
StatefulSet vs Deployment
| Feature | StatefulSet | Deployment |
|---|---|---|
| Pod Identity | Stable, unique | Fungible, interchangeable |
| Storage | Persistent, pod-specific | Ephemeral or shared |
| Networking | Stable hostnames | Unstable, service-based |
| Scaling | Ordered | Unordered |
| Use Cases | Databases, stateful apps | Web servers, stateless apps |