Home >Backend Development >Golang >Beginners guide to Kubernetes Statefulsets
StatefulSets are API objects in Kubernetes that are used to manage stateful applications. There are two types of applications in Kubernetes, Stateful applications and stateless applications. There are two ways to deploy these applications:
Those applications that maintain some form of persistent state or data are called stateful applications. The key characteristic that differentiates them from stateless applications is that these applications don't rely on storing data locally and they don't treat each request as independent. They manage data between interactions. Sometimes stateless applications connect to the stateful application to forward the requests to a database.
Those applications that do not maintain any form of persistent state or data locally are called stateless applications. In stateless applications, each request or interaction is treated independently. These applications are designed to be highly scalable, easy to manage, and fault-tolerant because, unlike Stateful applications, they don't have to track past interactions or requests.
Stateless applications are deployed using deployment component. Deployment is an abstraction of pods and allows you to replicate the application, meaning it allows you to run to 1, 5, 10 or n identical pods of the same stateless application.
In simplest terms StatefulSets are Kubernetes component that is used specifically for stateful applications. These are workload API object used to manage stateful applications. They manage the deployment and scaling of a set of Pods (Creating more replicas or deleting them), and StatefulSets are also responsible for the ordering and uniqueness of these Pods. StatefulSet was released in the Kubernetes 1.9 release.
StatefulSets will represent the set of pods with different (unique), persistent identities, and elastic hostnames (stable). It makes you assure about the ordering of scaling and deployments. Before understanding StatefulSets, you must understand Kubernetes Deployment.
Here is an example of a StatefulSet named web:
apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: serviceName: "nginx" replicas: 4 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: registry.k8s.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi
StatefulSets in Kubernetes are ideal for deploying stateful applications that require stable, unique network identifiers, persistent storage, and ordered, graceful deployment and scaling. They are suitable for applications like databases, key-value stores, and messaging queues that require consistent identity and storage.
Consider a node.js application connected to a MongoDB database. When a request comes to the node.js application it handles the request independently and does not depend on previous data to do that. It handles the request based on the payload in the request itself. This node.js application is an example of Stateless application. Now the request will either update some data in the database or query some data from the database. When node.js forwards that request to MongoDB, MongoDB updates the data based on the previous state of the data or query the data from its storage. For each request it needs to handle data and it depends upon the most up-to-date data or state to be available while node.js is just a pass-through for data updates or queries and it just processes code. Hence the node.js application should be a stateless application while the MongoDB application must be a stateful application.
Sometimes stateless applications connect to the stateful application to forward the requests to a database. This is a good example of a stateless application forwarding request to a stateful application.
Here is a step by step tutorial on how to use StatefulSets and some basic operations on StatefulSets.
Step 1. Create a StatefulSet file. you can do that by entering the following command:
apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: serviceName: "nginx" replicas: 4 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: registry.k8s.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi
Step 2. Open this file in a code-editor and write the following code into it:
touch example-statefulset.yaml
Step 3. Now we have to create a service file and a PersistentVolumeClaim file.
apiVersion: apps/v1 kind: StatefulSet metadata: name: gfg-example-statefulset annotations: description: "This is an example statefulset" spec: selector: matchLabels: app: nginx serviceName: "gfg-example-service" replicas: 3 # remember this, we will have 3 identical pods running template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumes: - name: www persistentVolumeClaim: claimName: myclaim
Step 4. Enter the following code into the service file:
touch example-service.yaml touch example-persistentVolumeChain.yaml
Step 5. Enter the following code into the PersistentVolumeClaim file:
apiVersion: v1 kind: Service metadata: name: gfg-example-service annotations: description: "this is an example service" labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx
Now lets apply these changes.
Step 6. Enter the following command in your terminal to create the gfg-example-statefulset:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: myclaim spec: accessModes: - ReadWriteMany resources: requests: storage: 8Gi # This means we are requesting for 8 GB of storage
This will create our gfg-example-statefulset, you will get a similar result:
now if we search our StatefulSets in our terminal by the command
kubectl create -f example-statefulset.yaml
we will find our gfg-example-statefulset in the list.
Step 7. Enter the following command in your terminal to create the gfg-example-service.
apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: serviceName: "nginx" replicas: 4 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: registry.k8s.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi
this will create a service with the name "gfg-example-service"
Step 8. Let's check our pods and services, for getting the list of pods enter the following command in your terminal:
touch example-statefulset.yaml
You will get the list of the three gfg- pods that we create though defining three replicas in the example-stateful-set.yaml file. You will get a similar output:
for checking the list of services, enter the following command in your terminal:
apiVersion: apps/v1 kind: StatefulSet metadata: name: gfg-example-statefulset annotations: description: "This is an example statefulset" spec: selector: matchLabels: app: nginx serviceName: "gfg-example-service" replicas: 3 # remember this, we will have 3 identical pods running template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumes: - name: www persistentVolumeClaim: claimName: myclaim
This will give you similar output:
Adding a StatefulSet: To add a StatefulSet to your Kubernetes cluster, use the command kubectl create -f [StatefulSet file name], replacing [StatefulSet file name] with the name of your StatefulSet manifest file.
touch example-service.yaml touch example-persistentVolumeChain.yaml
Deleting a StatefulSet: To delete a StatefulSet in Kubernetes, you can use the kubectl delete statefulset [name] command, where [name] is the name of the StatefulSet you want to delete.
apiVersion: v1 kind: Service metadata: name: gfg-example-service annotations: description: "this is an example service" labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx
Editing a StatefulSet: The command kubectl edit statefulset [name] allows you to modify the configuration of a StatefulSet directly from the command line by opening an editor.
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: myclaim spec: accessModes: - ReadWriteMany resources: requests: storage: 8Gi # This means we are requesting for 8 GB of storage
Scaling of Replicas: The kubectl scale command scales the number of replicas in a StatefulSet named [StatefulSet name] to the specified [Number of replicas].
kubectl create -f example-statefulset.yaml
Step 9. Now let's scale up our pods and check if it works! for scaling up the pods to 6 pods, enter the following command:
kubectl get statefulsets
This will create 3 more pods and number of pods are now 6, to get list of pods enter the following command:
kubectl apply -f example-service.yaml
You will get a similar output:
Step 10. Now let's scale down pods to 3, for that enter the same command, just change the number of replicas back to 3:
kubectl get pods
now if we check the list of pods by
kubectl get services
you will see only 3 pods running:
In this way we can create StatefulSets, scale them up and then scale them down as well. Make sure to delete the StatefulSet and the service before closing the terminal.To know more commands of of kubectl refer to Kubectl Command Cheat Sheet.
In stateful applications like MySQL, multiple pods cannot simultaneously read and write data to avoid data inconsistency.
One pod is designated as the master pod, responsible for writing and changing data, while others are designated as slave pods, only allowed to read data.
Each pod has its own replica of the data storage, ensuring data isolation and independence.
Synchronization mechanisms are employed to ensure that all pods have the same data state, with slave pods updating their data storage when the master pod changes data.
Continuous synchronization is necessary to maintain data consistency among all pods in the stateful applications.
Example:
Let's say we have one master and two slave pods of MySQL. Now what happens when a new pod replica joins the existing setup? because now that new pod also needs to create its own storage and take care of synchronizing it what happens is that it first clones the data from the previous pod and then it starts continuous synchronization to listen for any updates by master pod. since each pod has its own data storage (persistent volume) that is backed up by its own physical storage which includes the synchronized data and the state of the pod. Each pod has its own state which has information about whether it's a master pod or a slave pod and other individual characteristics. All of this gets stored in the pods own storage. Therefore when a pod dies and gets replaced the persistent pod. Identifiers make sure that the storage volume gets reattached to the replacement pod. In this way even if the cluster crashes, it is made sure that data is not lost.
In this article we discussed about how to use Kubernetes StatefulSets. StatefulSets are Kubenetes components used to deploy stateful applications. Stateful applications are those applications that maintain some form of persistent state or data. A good example would be any application with a database. We discussed about how to deploy an stateful application using StatefulSets. After that we discussed how Stateful applications work? At the end we discussed the difference between StatefulSet and deployment which basically moves around the point that deployment are used to deploy stateless application and StatefulSets are used to deploy statefull applications. We will end this article by addressing some FAQs.
To increase volume size in Kubernetes, you need to modify the PersistentVolumeClaim (PVC) specification by changing the storage size. Then, Kubernetes automatically provisions additional storage to meet the new size requirement, provided the underlying storage class supports dynamic provisioning.
The hostPath volume type in Kubernetes is suitable for scenarios where you need to access files or directories on the node's filesystem directly within a pod. It's commonly used for accessing node-specific resources or for sharing data between containers on the same node.
PersistentVolumeClaims (PVCs) in StatefulSets are used to provide stable, persistent storage for individual pods, ensuring data persistence and identity across pod restarts. In contrast, deployments typically utilize ephemeral volumes, suitable for stateless applications where data persistence is not a requirement.
While technically possible, it's not recommended to deploy stateless applications using StatefulSets. StatefulSets are specifically designed for stateful applications requiring stable, unique identifiers and persistent storage. Deploying stateless applications with StatefulSets can introduce unnecessary complexity and resource overhead.
It depends on the specific requirements of the application. Stateless applications are simpler to manage and scale horizontally, while stateful applications maintain data integrity and are better suited for certain workloads like databases or messaging systems.
The above is the detailed content of Beginners guide to Kubernetes Statefulsets. For more information, please follow other related articles on the PHP Chinese website!