StatefulSet

简介: StatefulSet

屏幕截图 2023-08-28 163846.png

StatefulSet

生产中常用的副本控制器如Deployment、DaemonSet、RS都是适用于无状态服务,其所管理的Pod

的启停顺序、IP、Podname等都是随机的,被管理的Pod被更新掉时,都会变化。

Kubernetes中StatefulSet是专为有状态服务如redis、kafka、consul等集群准备的集合,管理

所有有状态服务。

什么是有状态服务?有状态服务与无状态服务主要有如下区别:

1) 判断服务是否有状态,是指两个来自相同发起者(客户端)的请求在服务器端是否具备上下文关

系;

2) 有状态服务,一般服务器端都要保存与请求的相关信息,每个请求可以默认地使用之前的请求

信息;

3) 相反,无状态服务一般服务器端所能够处理的过程全部来自于请求所携带的信息或者其他服务

器端自身所保存的、并且可以被所有请求所使用的公共信息。

StatefulSet管理的Pod拥有固定的Pod名称(一般是pod.name-0/-1/-2顺延)、启停顺序(从-0开始

依次重启);在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。

与Deployment对应的网络映射为service,而在StatefulSet中与之对应的headless service(无头

服务),相较于services,headless service没有ClusterIP,解析它的名称时将返回该Headless

Service对应的全部Pod的Endpoint列表。

一个完整的StatefulSet应用由三个部分组成: headless service、StatefulSet controller、

volumeClaimTemplate。

kubernetes中选择使用statefullSet的服务所具有如下特点:

1) 稳定且唯一的网络标识符(如kfaka集群zookeeper的myid);

2) 稳定且持久的存储(如redis cluster模式下每个节点的shard);

3) 有序、平滑地部署扩展、终止和删除;

4) 有序的滚动更新;

------------------------------------------------

运行有状态的服务,前提:创建好storageclass。

示例:

```yaml
[root@master statefulSet]# vim statefulSet.yaml
apiVersion: v1
kind: Service
metadata:
  name: headless-svc
  labels:
    app: headless-svc
spec:
  ports:
  - name: myweb
    port: 80
  selector:
    app: headless-pod
  clusterIP: None
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: statefulset
spec:
  serviceName: headless-svc
  replicas: 3
  selector:
    matchLabels:
      app: headless-pod
  template:
    metadata:
      labels:
        app: headless-pod
    spec:
      containers:
      - name: myweb
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: test-storage
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: test-storage
      annotations:
        volume.beta.kubernetes.io/storage-class: storageclass
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 100Mi

为什么用 headless service 无头服务?

在用Deployment时,每一个Pod名称是没有顺序的,是随机字符串,因此是Pod名称是无序的,但是在statefulset中要求必须是有序 ,每一个pod不能被随意取代,pod重建后pod名称还是一样的。而pod IP是变化的,所以是以Pod名称来识别。pod名称是pod唯一性的标识符,必须持久稳定有效。这时候要用到无头服务,它可以给每个Pod一个唯一的名称 。

为什么用 volumeClaimTemplate?

对于有状态的副本集都会用到持久存储,对于分布式系统来讲,它的最大特点是数据是不一样的,所以各个节点不能使用同一存储卷,每个节点有自已的专用存储,但是如果在Deployment中的Pod template里定义的存储卷,是所有副本集共用一个存储卷,数据是相同的,因为是基于模板来的 ,而statefulset中每个Pod都要自已的专有存储卷,所以statefulset的存储卷就不能再用Pod模板来创建了,于是statefulSet使用volumeClaimTemplate,称为卷申请模板,它会为每个Pod生成不同的pvc,并绑定pv,从而实现各pod有专用存储。这就是为什么要用volumeClaimTemplate的原因。

//写完之后,直接运行,并且,在此之前,我们并没有创建PV,PVC,现在查看集群中的资源,是否有这两种资源?

[root@master statefulSet]# kubectl get pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                STORAGECLASS   REASON   AGE
persistentvolume/pvc-582374f3-263c-403d-8811-e7043837bae9   100Mi      RWO            Delete           Bound    default/test-storage-statefulset-1   storageclass            2m47s
persistentvolume/pvc-83b7e7a4-2d57-477b-a79f-7ec6a572cd11   100Mi      RWO            Delete           Bound    default/test-storage-statefulset-0   storageclass            3m42s
persistentvolume/pvc-dc481cc2-2e28-441c-a4da-4145b7746670   100Mi      RWO            Delete           Bound    default/test-storage-statefulset-2   storageclass            113s
NAME                                               STATUS        VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/test-storage-statefulset-0   Bound         pvc-83b7e7a4-2d57-477b-a79f-7ec6a572cd11   100Mi      RWO            storageclass   3m42s
persistentvolumeclaim/test-storage-statefulset-1   Bound         pvc-582374f3-263c-403d-8811-e7043837bae9   100Mi      RWO            storageclass   2m47s
persistentvolumeclaim/test-storage-statefulset-2   Bound         pvc-dc481cc2-2e28-441c-a4da-4145b7746670   100Mi      RWO            storageclass   113s
```

//从上述结果中,我们知道,storageclass为我们自动创建了PV,volumeClaimTemplate为我们自动创建PVC,但是否能够满足我们所说的,每一个Pod都有自己独有的数据持久化目录,也就是说,每一个Pod内的数据都是不一样的。

//分别在对应的PV下,模拟创建不同的数据。

cd /nfsdata/
echo "0000000000000000" > default-test-storage-statefulset-0-pvc-4d7a43ed-bbee-48bd-86fa-a7e744613e80/index.html
echo "1111111111111111" > default-test-storage-statefulset-1-pvc-7049d6a2-949c-4ea5-97da-c655a77ad8e3/index.html
echo "2222222222222222" > default-test-storage-statefulset-2-pvc-9da968ba-8b49-4f10-bc97-ba4c79c87c6f/index.html
//查看对应Pod的数据持久化目录,可以看出,每个Pod的内容都不一样。
kubectl exec statefulset-0 cat /usr/share/nginx/html/index.html
000000000000000
kubectl exec statefulset-1 cat /usr/share/nginx/html/index.html
111111111111111
kubectl exec statefulset-2 cat /usr/share/nginx/html/index.html
222222222222222

//即使删除Pod,然后statefulSet这个Pod控制器会生成一个新的Pod,这里不看Pod的IP,名称肯定和之前的一致,而且,最主要是持久化的数据仍然存在。

[root@master ~]# kubectl delete pod statefulset-2 
pod "statefulset-2" deleted
[root@master ~]# kubectl get pod
NAME                     READY   STATUS              RESTARTS   AGE
mysql-6fccccd487-5q2dt   1/1     Running             0          45h
statefulset-0            1/1     Running             0          12m
statefulset-1            1/1     Running             0          11m
statefulset-2            0/1     ContainerCreating   0          5s
[root@master ~]# kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
mysql-6fccccd487-5q2dt   1/1     Running   0          45h
statefulset-0            1/1     Running   0          12m
statefulset-1            1/1     Running   0          11m
statefulset-2            1/1     Running   0          11s
kubectl exec statefulset-2 cat /usr/share/nginx/html/index.html
222222222222222

规律总结

匹配Pod name(网络标识)的模式为: (statefulset名称)−(statefulset名称)-(序号)

StatefulSet为每个Pod副本创建了一个DNS域名,这个域名的格式为: $(podname).(headless server name),也就意味着服务间是通过Pod域名来通信而非Pod IP,因为当Pod所在Node发生故障时,Pod会被飘移到其它Node上,Pod IP会发生变化,但是Pod域名不会有变化。

StatefulSet使用Headless服务来控制Pod的域名,这个域名的FQDN为: (servicename).(service name).(namespace).svc.cluster.local,其中,“cluster.local”指的是集群的域名。

根据volumeClaimTemplates,为每个Pod创建一个pvc,pvc的命名规则匹配模式:(volumeClaimTemplates.name)-(pod_name)

删除Pod不会删除其pvc,手动删除pvc将自动释放pv。

相关实践学习
基于函数计算快速搭建Hexo博客系统
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
8月前
|
存储 Kubernetes 网络协议
【K8S系列】深入解析StatefulSet(一)
【K8S系列】深入解析StatefulSet(一)
186 1
|
8月前
|
存储 应用服务中间件 nginx
kubernetes Statefulset控制器
kubernetes Statefulset控制器
|
存储 应用服务中间件 调度
在StatefulSet中使用LocalVolume存储卷保持节点一致
StatefulSet是一种有状态服务,其存储卷的使用有多种方式: 使用共享存储,这时在模板中定义一个volume卷,可以给多个pod共享; 每个pod配置独立的存储卷,使用非共享存储(块存储)时需要这样配置,通过配置volumeClaimTemplates实现; 对于StatefulSet使...
4542 0
|
Web App开发 应用服务中间件 nginx
|
6月前
|
存储 Kubernetes 索引
Statefulset部署应用
Statefulset部署应用
|
6月前
|
Cloud Native Go Docker
Statefulset 实战 1
Statefulset 实战 1
|
6月前
|
Kubernetes API 索引
Statefulset实战 2
Statefulset实战 2
|
6月前
|
Kubernetes Cloud Native 索引
Statefulset 实战 3
Statefulset 实战 3
|
8月前
|
存储 Kubernetes 网络协议
【K8S系列】深入解析StatefulSet(二)
【K8S系列】深入解析StatefulSet(二)
32 0
|
9月前
|
弹性计算 Kubernetes 固态存储
StatefulSet应用部署
本场景带您体验如何使用k8s的原生命令kubectl部署一个StatefulSet应用的镜像到k8s集群中,并对该StatefulSet应用进行伸缩操作。
71 0