0
点赞
收藏
分享

微信扫一扫

k8s控制器之StatefulSet

J简文 2022-07-13 阅读 50

StatefulSet概述

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

  1. 集群的规模是比较固定的,集群规模不能随意变动;

  2. 每个节点都是有固定的身份ID,集群中的成员可以相互发现并通信;

  3. 集群中的每个节点都是有状态的,通常会持久化数据到永久存储中;

  4. 如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损;

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

  1. Headless Service:用来定义pod网路标识,生成可解析的DNS记录,与普通Service的关键区别在于,它没有Cluster IP;

  2. volumeClaimTemplates:存储卷申请模板,创建pvc,指定pvc名称大小,自动创建pvc,且pvc由存储类供应;

  3. StatefulSet:管理Pod的;

为什么要用headless service?

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

  • headless service 会为 service 分配一个域名

    <service-name>.<namespace-name>.svc.cluster.local

  • StatefulSet会为关联的Pod分配一个dnsName

    <pod-name>.<service-name>.<namespace-name>.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-0nginx-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
举报

相关推荐

0 条评论