Stateful and stateless services in Kubernetes

k8s-LAB

Author:rab

Directory

    • Preface
    • 1. Stateless service case
      • 1.1 yml case
      • 1.2 Expansion and reduction
        • 1.2.1 Expansion
        • 1.2.2 Shrinking
      • 1.3 Pause and resume
        • 1.3.1 Pause
        • 1.3.2 Recovery
      • 1.4 Rollback
    • 2. Stateful service cases
      • 2.1 yml case
      • 2.2 Expansion and reduction
        • 2.2.1 Capacity expansion
        • 2.2.2 Shrinking
    • Summarize

Foreword

In Kubernetes (k8s), stateful services and stateless services are two different types of application deployments, and they have some key differences in container orchestration and management.

1. Stateless Services

  • A stateless service means that the application does not rely on local state and handles every request in the same way. This means that any instance of a stateless service can handle requests from clients, and there is no correlation between the requests.
  • Typical examples of stateless services include web servers, API services, load balancers, etc. These services can scale horizontally, that is, they can handle more request traffic by adding more replicas.
  • Stateless services are usually suitable for deployment using Deployment in Kubernetes. Because their instances can be started and stopped at will without affecting the application’s state or data.

2. Stateful Services

  • Stateful services are applications that rely on local state, often requiring stable identities and data. This means that each instance has a unique identity, such as a database server or message queue, and they need to preserve their data and state when started, stopped, or failed over.
  • Typical examples of stateful services include database systems (such as MySQL, PostgreSQL), message queues (such as RabbitMQ, Kafka), etc. These services often require the stability of persistent storage and network identity.
  • Kubernetes provides StatefulSet to deploy stateful services. StatefulSet has the ability to manage stateful applications, providing a unique identity for each Pod and a stable network identity, thereby supporting the stability of stateful services.

1. Stateless service case

1.1 yml case

For example, we can give an example of Nginx load balancing. At this time, this load balancing can be classified as a stateless service. Any Nginx instance can handle requests from clients. Therefore, we can use Deployment in Kubernetes for deployment.

vim Stateless.yml
apiVersion: v1
kind: Namespace
metadata:
  name:myweb
  labels:
    name: ops
---
apiVersion: apps/v1
Kind: Deployment
metadata:
  name: nginx
  namespace:myweb
  labels:
    app: stateless
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.4
        ports:
        - containerPort: 80
---
apiVersion: v1
Kind: Service
metadata:
  name: nginx-srv
  namespace:myweb
spec:
  selector:
    app: demo
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30333
  type: NodePort

Note: The value of the selector label selector of the Service must be consistent with the value of the selector label selector of the Deployment, otherwise the external Client’s request cannot be routed to the Pod resource.

kubectl apply -f Stateless.yml

Local browser access:

http://192.168.56.160:30333/

image-20231025153300073

1.2 Expansion and reduction

1.2.1 Capacity expansion

There are many ways to expand capacity. The following are common expansion methods.

1. Modify the yml file method

vim Stateless.yml # Just modify the replicas value
...
spec:
  replicas: 5
  ...

Execute extension (update) after modification is completed

kubectl apply -f Stateless.yml

2. Shell command line method

  • Method 1

    kubectl scale --replicas=5 deploy nginx -n myweb
    
    # Note: deploy is the abbreviation of deployment. It is okay to write deployment.
    
  • Method 2

    kubectl edit deployment nginx -n myweb
    
    # This will interactively enter the yml configuration file. After entering, modify the value of replicas and then save and exit to achieve expansion.
    

Note: Different from directly modifying the yml file, you can upgrade after executing this command without executing kubectl apply -f Stateless.yml

1.2.2 Shrinking

There is no difference from expansion. The operation is exactly the same. The so-called shrinkage is the concept of shrinking when the replicas value you set is smaller than the current replicas value.

Note:But it should be noted that we say that dynamic expansion and shrinkage will not trigger online (that is, a new replicaset will not be generated).

1.3 Pause and Resume

Note that this pause and resume does not mean that my program will not provide services to the outside world after it is paused, but is used when you use the kubectl set... command to update. The general process is: after you pause, you are allowed to execute multiple kubectl set... update commands, but each command does not take effect immediately after execution, but is executed when you resume the deployment. Those kubectl set ... will take effect.

1.3.1 Pause

1. Service suspension

kubectl rollout pause deployment nginx -n myweb

2. Execute the first update command

kubectl set image deploy nginx nginx=nginx:1.20.0 -n myweb

3. Execute the second update command

kubectl set resources deploy nginx -c nginx --limits=cpu=200m,memory=128Mi --requests=cpu=10m,memory=16Mi -n myweb

As shown in the figure below, the above two update instructions are not effective, which can be proved by the fact that the nginx image version has not changed.

image-20231025170727008

1.3.2 Recovery

So how do we make the kubectl set ... command we executed take effect? Just restore.

kubectl rollout resume deploy nginx -n myweb

As shown in the figure below, the kubectl set... command we executed during the pause will take effect after recovery.

image-20231025171200713

Of course, if you want to use kubectl set to update the service but don’t want to pause it, you can directly execute the kubectl set command. After execution, it will be updated immediately.

kubectl set image deploy nginx nginx=nginx:1.18.0 -n myweb

image-20231025171428065

1.4 Rollback

If there is a problem in the final test verification of our above series of updates and we need to roll back to the original (or pre-update) state or an intermediate version state, then we need to use the rollback function of K8s. Specifically Here’s how to do it.

1. Check the updated version first

By default, K8s will only retain nearly 10 revision. We can use the revisionHistoryLimit field in the Deployment configuration file to specify the number of revisions to retain.

kubectl rollout history deploy nginx -n myweb

# Among the three version numbers in the figure below, 1 represents the initial version status and 3 represents the current version status.

image-20231025172113126

2. Check the details corresponding to each version (because you can’t see it in the picture above)

kubectl rollout history deployment nginx --revision=1 -n myweb

# Let’s take a look at the first version details

image-20231025172640153

3. Roll back to the version state we specified

kubectl rollout undo deployment nginx --to-revision=1 -n myweb

image-20231025172836324

4. Finally, verify whether the rollback is successful

kubectl get deployment nginx -o wide -n myweb

image-20231025173029086

At this time, let’s take a look at the historical version numbers:

image-20231025173140455

You will find that the historical version number 1 has disappeared. Why? Because it has been rolled back by us (you have to remember at this time that if you want to go back to the original state after performing multiple update operations, you can only go back to version 4, because 4 is only available at this time. is our initial state, while 2 is not).

2. Stateful service cases

2.1 yml case

As mentioned above, services such as MySQL, RabbitMQ, etc. are actually stateful services. For such services, we generally require each Pod to have a unique identifier and a stable network identifier. MySQL, for example, is a typical stateful application because each MySQL instance requires a unique identity and usually relies on a stable network identity.

vim Stateful.yml
apiVersion: v1
kind: Namespace
metadata:
  name:myweb-2
  labels:
    name: ops
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
  namespace: myweb-2
  labels:
    app: stateful
spec:
  serviceName: myweb-2
  replicas: 3
  selector:
    matchLabels:
      app: demo-2
  template:
    metadata:
      labels:
        app: demo-2
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.4
        ports:
        - containerPort: 80
---
apiVersion: v1
Kind: Service
metadata:
  name: nginx-srv
  namespace: myweb-2
spec:
  selector:
    app: demo-2
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30334
  type: NodePort
kubectl apply -f Stateful.yml

I think you already know how to view deployment resources, but how to view statefulset resources? In fact, it’s all the same routine:

kubectl get statefulset -n myweb-2

# or
kubectl get sts -n myweb-2

image-20231025175454025

Local browser access:

http://192.168.56.160:30334/

image-20231025175657501

2.2 Expansion and reduction

2.2.1 Capacity expansion
kubectl scale --replicas=5 sts nginx -n myweb-2
2.2.2 Shrinking
kubectl scale --replicas=2 sts nginx -n myweb-2

Note:The pause, resume, and rollback routines are consistent with deployment, so we won’t reinvent the wheel here.

Summary

  • Stateless services are suitable for applications that can scale at will and handle requests without relying on local state, while stateful services are suitable for applications that require stable identity and data.

  • In Kubernetes, we can use different controllers (such as Deployment and StatefulSet) to accommodate these two different types of services.

  • Stateful services often require consideration of persistent storage and data backup strategies to ensure data reliability and availability.

Note: None of the above cases are configured with persistent storage, which will be mentioned later.

-END