What is StatefulSet in Kubernetes and How to use it?
It can be challenging to choose between Deployment and StatefulSet for beginners, while both can be used to manage Pods. Therefore, this post intentionally paves the way for you to select one of them appropriately.
Before we get started on the topic of StatefulSet, I would like to introduce the general concept of stateful applications and stateless applications.
Stateful applications are referring to applications where that keep track of client data, and information, or can be a session for future processing. A good example of this should be database applications.
As opposed to Stateful applications, Stateless applications don’t store client data or any references, for example, REST APIs.
Now as the name StatefulSet suggested, it’s mainly used for constructing stateful applications. Similar to Deployments, it controls the pod using container spec from your config file. Although the pod shares the same container spec from a config file, they are not interchangeable; each has its own unique persistent volume and is not shareable with another pod. Moreover, it’s special that the Stateful pod’s names are identical by following a conventional format statefulsetname-ordinal_number. For instance, if you deploy a StatefulSet with 3 replicas and named it to statefulapp, so from the 1st pod to the 3rd pod must have given names statefulapp-0, statefulapp-1, and statefulapp-2 respectively. In addition, both scaling and rolling updates of StatefulSet are in sequence order.
StatefulSet itself will require you to create a headless service in case you want the pod to have inter-pod discovery and access each other.
I hope my explanation is clear, so now let’s have a practical exam to intensify your understanding.
apiVersion: v1
kind: Service
metadata:
name: headless-stateful-svc
labels:
app: headless-stateful
spec:
ports:
- port: 3000 # if target port is not set it will use the same value as port
clusterIP: None
selector:
app: stateful
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: statefulapp
spec:
serviceName: headless-stateful-svc
replicas: 3
selector:
matchLabels:
app: stateful
template:
metadata:
labels:
app: stateful
spec:
containers:
- name: stateful-container
image: stateful-app-image # to be replaced
ports:
- containerPort: 3000
volumeMounts:
- name: data
mountPath: /data
securityContext:
runAsUser: 0
volumes:
- name: data
persistentVolumeClaim:
claimName: stateful-pvc
In this example, you can replace an image name base on your own need.
I have created:
- A headless service, named headless-stateful-svc. By setting clusterIP to None, you can create a headless service. However, if you want your apps to be publicly accessed from external, you will need to create either a new node port service or a load balancer service.
- A StatefulSet with 3 replicas of unique pods
- A volume, named data that claimed from stateful-pvc
apiVersion: v1
kind: PersistentVolume
metadata:
name: stateful-pv
spec:
storageClassName: manual
persistentVolumeReclaimPolicy: Retain
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/tmp/data"
Look at our PV file:
- A PV named stateful-pv
- Set accessModes to ReadWriteOnce (RWO) to make sure that no more than a pod at a time can access this storage. This will ensure that no more than one pod can start on each node, so this help creates the uniqueness of the pod.
- Used a Node path (/tmp/data) to store data
Eventually, we can create a PVC for claiming storage that we have just created as follows.
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: stateful-pvc
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
To conclude, StatefulSet is useful when you want to deploy stateful applications into the Kubernetes cluster. With the stable pod name, you can easily match a selector to the pod name and also ability to roll out apps in an orderly manner.
Thanks for your reading!! If you like the post please give me a clap and follow me for more posts. 🍺