# StatefulSet

## [About](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/)

A **StatefulSet** is a Kubernetes controller that manages the deployment and scaling of a set of **Pods with unique, stable identities and persistent storage**.

It’s used for **stateful applications** such as:

* Databases (MySQL, PostgreSQL, MongoDB)
* Distributed systems (Cassandra, Kafka, Zookeeper)
* Anything requiring **stable Pod names, stable storage, or ordered startup/shutdown**

#### Stable storage

* Each Pod can get its own **PersistentVolumeClaim (PVC)**, automatically created by the StatefulSet.
* The storage is bound to the Pod’s identity (`mydb-0` always uses `pvc-mydb-0`).
* Even if the Pod is rescheduled on another node, it reattaches to the same storage.

#### Ordered, graceful deployment and scaling

* Pods are created **one by one, in order** (`mydb-0`, then `mydb-1`, then `mydb-2`).
* Similarly, they are deleted in **reverse order**.
* Useful when apps require strict initialization order (like primary DB before replicas).

#### Rolling updates

* StatefulSets support rolling updates, but they also ensure ordering and readiness at each step.
* This prevents breaking distributed systems during upgrades.

{% hint style="warning" %}
In Production use StatefulSets if:

* You need stable Pod IDs (databases, queues, clustered systems).
* Each Pod must keep its own persistent data.
* Startup order matters.
  {% endhint %}

## Commands

To apply and run a StatefulSet configuration:

```bash
kubectl apply -f statefulset.yaml
```

To list the StatefulSets:

```bash
kubectl get statefulsets
```

To describe a StatefulSet:

```bash
kubectl describe statefulset <statefulset-name>
```

To delete a StatefulSet:

```bash
kubectl delete statefulset <statefulset-name>
```

To update image through the CLI:

```bash
kubectl set image statefulset/<statefulset-name> nginx=nginx:1.25
```

To get the rollout history of StatefulSets:

```bash
kubectl rollout history statefulset <statefulset-name>
```

To rollback a StatefulSet to a previous version:

```bash
kubectl rollout undo statefulset <statefulset-name>

# To a specific revision number
kubectl rollout undo statefulset <statefulset-name> --to-revision=<rev-number>
```

To scale StatefulSets:

```bash
kubectl scale statefulset <statefulset-name> --replicas=5
```

Check consumption of a StatefulSet:

```bash
kubectl top statefulset <statefulset-name>
```

## [Example](https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/)

In this example, the Headless Service provides DNS por Pods and StatefulSet creates Pods with stable names.

Each Pod gets its own PVC.

{% code title="headless-service.yaml" %}

```yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-headless-service
spec:
  clusterIp: None   # headless service
  selector:
    app: myapp-stateful
  ports:
    - port: 3306
      name: myapp-container
```

{% endcode %}

{% code title="statefulset.yaml" %}

```yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myapp-stateful
spec:
  serviceName: myapp-headless-service
  replicas: 3
  selector:
    matchLabels:
      app: myapp-container
  # Pod template
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp-container
          image: mysql
          ports:
            - containerPort: 3306
          env:
            ...
          volumeMounts:
            - name: myapp-container-data
              mountPath: /var/lib/mysql
  volumeClaimTemplates:
    - metadata:
        name: myapp-container-data
      spec:
        accessNodes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi
```

{% endcode %}
