DEV Community

Cover image for Kubernetes Learning Part V: Workload Resource - StatefulSet
Saravanan Gnanaguru for Kubernetes Community Days Chennai

Posted on • Edited on

Kubernetes Learning Part V: Workload Resource - StatefulSet

Kubernetes Learning Part V

Table of content


Introduction

  • This is article is In this blog, we will continue discuss Workload Resource - StatefulSets
  • Topics and definitions are hand picked from Kubernetes documentation for the purpose of learning.
  • This blog is part of the Kubernetes Learning series

StatefulSets

  • StatefulSet helps to create/manage one or more related Pods that requires to track the state of the Pods
  • For example, if any workload needs to store data persistently, then we can run it as a StatefulSet that matches each Pod with a PersistentVolume.
  • Our code, running in the Pods for that StatefulSet, can replicate data to other Pods in the same StatefulSet to improve overall resilience.

Usecase for choosing StatefulSet

  • Major use case of StatefulSet is, If we want to use storage volumes to provide persistence for our workload, a StatefulSet can be chosen.
  • Even though individual Pods in a StatefulSet is failed, the persistent Pod identifiers make it easier to match existing volumes to the new Pods, that replace any pods that have failed earlier.
  • As mentioned in the docs,

StatefulSets are valuable for applications that require one or more of the following.

  • Stable, unique network identifiers.
  • Stable, persistent storage.
  • Ordered, graceful deployment and scaling.
  • Ordered, automated rolling updates.

What makes a StatefulSet config

  • There are few important concepts we need to know, for creating StatefulSet
    • Persistent volume - Storage definition, A PersistentVolume (PV) is a piece of storage in the cluster that has been provisioned by an administrator or dynamically provisioned using Storage Classes.
    • Persistent volume claim - Storage definition identifier request by user. It is similar to a Pod. Pods consume node resources and PVCs consume PV resources. Pods can request specific levels of resources (CPU and Memory). Claims can request specific size and access modes. As we discussed earlier, StatefulSet is suitable for apps with persistent storage. So we need to have config defined for Persistent volume and Persistent volume claim. Refer the persistent-volumes docs for more details
  • Also we require below configs as well,
    • Service config - Definition of application service
    • StatefulSet config - Definition of application deployment

How to deploy a StatefulSet

  • Let us now try to create a MySql database using the StatefulSet configuration

Step 1 Define Database Storage as Persistent volume

  • Create config for PV and PVC for DB storage
  • We create a PVC requesting 20gig of storage and hence the PV creates a storage for 20gig of storage in the cluster
--- apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv-volume labels: type: local spec: storageClassName: manual capacity: storage: 20Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pv-claim spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 20Gi 
Enter fullscreen mode Exit fullscreen mode

Step 2 Define Database Creds as Secret

  • Create config mysql database, username and password as secret
  • Below example shows the creation of credentials using secret config, using the base64 encoded string
  • For the purpose of demo, it is not recommended to expose username and password in config yamls, it is recommended to integrate secret management tools for this purpose.
--- apiVersion: v1 kind: Secret metadata: name: mysql-password type: Opaque # Run `echo -n 'admin' | base64` to get the base64 encoded value data: password: YWRtaW4= user: YWRtaW4K --- apiVersion: v1 kind: Secret metadata: name: mysql-user type: Opaque # Run `echo -n 'admin' | base64` to get the base64 encoded value data: user: YWRtaW4K 
Enter fullscreen mode Exit fullscreen mode

Step 3 Define Database Service

  • We are creating a service that configures port 3306 as port and targetPort
  • What is the difference between port and targetPort
    • Applications running inside the
--- apiVersion: v1 kind: Service metadata: name: mysql spec: ports: - name: mysql-ports port: 3306 targetPort: 3306 selector: app: mysql clusterIP: None 
Enter fullscreen mode Exit fullscreen mode

Step 4 Define StatefulSet for Database deployment

In the below example:

  • The StatefulSet, named mysql, has a Spec that indicates that 2 replicas of the mysql container will be launched in Pods.
  • The volumes section of config will provide stable storage using PersistentVolumes provisioned by a PersistentVolume Provisioner.
  • Pod Selector should match with the .spec.selector field of a StatefulSet to match the labels of its .spec.template.metadata.labels. Failing to specify a matching Pod Selector will result in a validation error during StatefulSet creation.
--- apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: selector: matchLabels: app: mysql serviceName: mysql replicas: 2 template: metadata: labels: app: mysql spec: containers: - image: mysql:5.7 name: mysql env: - name: MYSQL_USER valueFrom: secretKeyRef: name: mysql-user key: user - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: mysql-password key: password - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-password key: password ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql volumes: - name: mysql-persistent-storage persistentVolumeClaim: claimName: mysql-pv-claim 
Enter fullscreen mode Exit fullscreen mode

Deploy Database using Kubectl command

  • Let us now execute kubectl command and see what is created
  • First execute the PV and PVC to create storage config
$ kubectl apply -f mysql_pv_pvc.yml persistentvolume/mysql-pv-volume created persistentvolumeclaim/mysql-pv-claim created 
Enter fullscreen mode Exit fullscreen mode
  • Then execute stateful set creation config for database
$ kubectl apply -f mysql_statefulset_app.yml secret/mysql-password created secret/mysql-user created service/mysql created statefulset.apps/mysql created 
Enter fullscreen mode Exit fullscreen mode
  • We can also check the deployed pods using the command below,
$ kubectl get pods NAME READY STATUS RESTARTS AGE mysql-0 1/1 Running 0 11s mysql-1 1/1 Running 0 10s 
Enter fullscreen mode Exit fullscreen mode
  • Since we deployed the pods in default namespace, we can use the get pods command without any namespaces

Pod Replica Behavior

  • It shows the 2 replicas of mysql pods. In case if any healthy replica is failed, replica config make sure that, it spins up new pods and terminating other

Verify Deployed Database

  • We can test the deployed database server by running a MySQL client to connect to the server
  • This command creates a new Pod in the cluster running a MySQL client and connects it to the server through the Service.
$ kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -padmin 
Enter fullscreen mode Exit fullscreen mode
  • If it connects, we can see the mysql> prompt. This shows our stateful MySQL database is up and running.
If you don't see a command prompt, try pressing enter. mysql> 
Enter fullscreen mode Exit fullscreen mode

Notable other details

Deployment and Scaling Guarantees

For a StatefulSet with N replicas,

  • When Pods are being deployed, they are created sequentially, in order from {0..N-1}.
  • When Pods are being deleted, they are terminated in reverse order, from {N-1..0}.
  • Before a scaling operation is applied to a Pod, all of its predecessors must be Running and Ready.
  • Before a Pod is terminated, all of its successors must be completely shutdown.

Update strategies

  • A StatefulSet's .spec.updateStrategy field allows you to configure and disable automated rolling updates for containers, labels, resource request/limits, and annotations for the Pods in a StatefulSet. There are two possible values:
  • OnDelete When a StatefulSet's .spec.updateStrategy.type is set to OnDelete, the StatefulSet controller will not automatically update the Pods in a StatefulSet. Users must manually delete Pods to cause the controller to create new Pods
  • RollingUpdate The RollingUpdate update strategy implements automated, rolling update for the Pods in a StatefulSet. This is the default update strategy.

Conclusion

Hope this article is helpful to people getting started with kubernetes concepts on StatefulSets

Thanks for reading!

Further Reference

Workload Resources
StatefulSet
Persistent Volumes
Configure Persistent Volumes
Basics of StatefulSet
https://kubernetes.io/docs/concepts/workloads/

Full Source of Tutorial

  • The full source code can be accessible in this GitHub repo

Follow me on,

Top comments (0)