k8s控制器之StatefulSet

网友投稿 269 2022-09-09

k8s控制器之StatefulSet

StatefulSet概述

在kubernetes系统中,Pod的管理对象Deployment,DaemonSet和Job都面向无状态的服务,但现实中有很多服务时有状态的,比如一些集群服务,例如mysql集群,集群一般都会有这四个特点:

集群的规模是比较固定的,集群规模不能随意变动; 每个节点都是有固定的身份ID,集群中的成员可以相互发现并通信; 集群中的每个节点都是有状态的,通常会持久化数据到永久存储中; 如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损;

如果你通过Deployment控制Pod副本数量来实现上述有状态的集群,就会发现第二点是无法满足的,因为Pod名称和ip是随机产生的,并且各Pod中的共享存储中的数据不能都动,因此StatefulSet在这种情况下就派上用场了,StatefulSet是有状态的集合,管理有状态的服务,它所管理的Pod的名称不能随意变化。数据持久化的目录也是不一样,每一个Pod都有自己独有的数据持久化存储目录。比如 MySQL主从、redis集群等,StatefulSet由以下几个部分组成:

Headless Service:用来定义pod网路标识,生成可解析的DNS记录,与普通Service的关键区别在于,它没有Cluster IP; volumeClaimTemplates:存储卷申请模板,创建pvc,指定pvc名称大小,自动创建pvc,且pvc由存储类供应; StatefulSet:管理Pod的;

为什么要用headless service?

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

headless service 会为 service 分配一个域名 ..svc.cluster.local StatefulSet会为关联的Pod分配一个dnsName ...svc.cluster.local

为什么需要volumeClaimTemplate?

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

StatefulSet资源清单

kubectl explain sts.spec主要字段解释如下:

replicas :副本数

selector:那个pod是由自己管理的

serviceName:必须关联到一个无头服务商

template:定义pod模板(其中定义关联那个存储卷)

volumeClaimTemplates :生成PVC

StatefulSet应用实践

创建ServiceAccount

#创建服务账户 apiVersion: v1 kind: ServiceAccount metadata: name: nfs-provisioner --- #账户角色绑定 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: nfs-provisioner-clusterrolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: nfs-provisioner namespace: default

创建nfs-provisioner

kind: Deployment apiVersion: apps/v1 metadata: name: nfs-client-provisioner spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-client-provisioner template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-provisioner containers: - name: nfs-client-provisioner image: quay.io/external_storage/nfs-client-provisioner:latest volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: nfs/nginx # 根据自己的名称来修改 - name: NFS_SERVER value: 192.168.58.110 # NFS服务器所在的 ip - name: NFS_PATH value: /data/nginx # 共享存储目录 volumes: - name: nfs-client-root nfs: server: 192.168.58.110 # NFS服务器所在的 ip path: /data/nginx

创建StorageClass

apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-sc provisioner: nfs/nginx

创建PersistentVolumeClaim

kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nfs-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi storageClassName: nfs-sc

创建StatefulSet

apiVersion: v1 kind: Service metadata: name: nginx-svc spec: selector: app: nginx-pod ports: - port: 8000 #Headless Service的port没有用 clusterIP: None --- apiVersion: apps/v1 kind: StatefulSet metadata: name: nginx-sts spec: replicas: 2 template: metadata: labels: app: nginx-pod spec: containers: - name: nginx-c image: nginx:1.21.5 imagePullPolicy: IfNotPresent ports: - containerPort: 80 volumeMounts: - mountPath: /usr/share/nginx/html name: nginx-html restartPolicy: Always volumeClaimTemplates: - metadata: name: nginx-html spec: accessModes: - ReadWriteOnce storageClassName: nfs-sc resources: requests: storage: 1Gi selector: matchLabels: app: nginx-pod serviceName: nginx-svc #根据名称关联Headless Service

创建StatefulSet成功后,可以进入到/data/nginx目录下查看,会看到nginx两个pod对应的数据存储目录,这两个目录分别对应nginx-sts-0和nginx-sts-1的存储目录,说明挂载成功。

default-nginx-html-nginx-sts-0-pvc-c55dace8-d03b-4059-8ff2-40c1603a91ee default-nginx-html-nginx-sts-1-pvc-fff76550-2f40-48c0-810e-fe658c205b6a

StatefulSet管理

扩缩容

kubectl edit sts nginx-sts

修改replicas字段,将2个副本修改为3个,查看pod

NAME READY STATUS RESTARTS AGE nfs-client-provisioner-5bf7797fd8-bdmx9 1/1 Running 0 9m18s nginx-sts-0 1/1 Running 0 8m25s nginx-sts-1 1/1 Running 0 8m23s nginx-sts-2 1/1 Running 0 9s

查看pvc和pv,发现也动态更新了

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE nfs-pvc Bound pvc-8b1f26ea-4ff5-42cd-8f79-4b21b92a4731 1Gi RWX nfs-sc 9m38s nginx-html-nginx-sts-0 Bound pvc-c55dace8-d03b-4059-8ff2-40c1603a91ee 1Gi RWO nfs-sc 27m nginx-html-nginx-sts-1 Bound pvc-fff76550-2f40-48c0-810e-fe658c205b6a 1Gi RWO nfs-sc 27m nginx-html-nginx-sts-2 Bound pvc-d79d3b22-f5c6-4100-b843-9dc7da18d15f 1Gi RWO nfs-sc 38s

NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-8b1f26ea-4ff5-42cd-8f79-4b21b92a4731 1Gi RWX Delete Bound default/nfs-pvc nfs-sc 9m24s pvc-c55dace8-d03b-4059-8ff2-40c1603a91ee 1Gi RWO Delete Bound default/nginx-html-nginx-sts-0 nfs-sc 27m pvc-d79d3b22-f5c6-4100-b843-9dc7da18d15f 1Gi RWO Delete Bound default/nginx-html-nginx-sts-2 nfs-sc 40s pvc-fff76550-2f40-48c0-810e-fe658c205b6a 1Gi RWO Delete Bound default/nginx-html-nginx-sts-1 nfs-sc 27m

更新

kubectl edit sts nginx-sts

修改镜像版本,将现有版本变更为nginx:1.19.2-alpine,保存退出,pod自动更新,查看pod的镜像如下:

kubectl get pod -o yaml | grep image

- image: nginx:1.19.2-alpine imagePullPolicy: IfNotPresent image: nginx:1.19.2-alpine imageID: docker-pullable://nginx@sha256:a97eb9ecc708c8aa715ccfb5e9338f5456e4b65575daf304f108301f3b497314 - image: nginx:1.19.2-alpine imagePullPolicy: IfNotPresent image: nginx:1.19.2-alpine imageID: docker-pullable://nginx@sha256:a97eb9ecc708c8aa715ccfb5e9338f5456e4b65575daf304f108301f3b497314 - image: nginx:1.19.2-alpine imagePullPolicy: IfNotPresent image: nginx:1.19.2-alpine imageID: docker-pullable://nginx@sha256:a97eb9ecc708c8aa715ccfb5e9338f5456e4b65575daf304f108301f3b497314

回滚

更新后,查看更新记录

kubectl rollout history sts nginx-sts

根据版本号可以回滚到指定版本:

kubectl rollout undo sts nginx-sts --to-revision=1

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:《网络直播营销管理办法(试行)》今起施行,提出数据流量造假等8条红线!
下一篇:k8s控制器之DaemonSet
相关文章

 发表评论

暂时没有评论,来抢沙发吧~