欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

kubernetes有状态集合之statefulset

程序员文章站 2024-03-11 16:01:37
...
   生产中常用的副本控制器如Deployment、DaemonSet、RS都是适用于无状态服务,其所管理的Pod的启停顺序、IP、Podname等都是随机的,被管理的Pod被更新掉时,都会变化。
   Kubernetes中StatefulSet是专为有状态服务如redis、kafka、consul等集群准备的集合,管理所有有状态服务。
   **PS:什么是有状态服务?**
   简单来说,有状态服务与无状态服务主要有如下区别:
   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)、有序、平滑地部署扩展、终止和删除;
   5)、有序的滚动更新;

首选创建pv,如下:
```bash
[[email protected] statefulset-test]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-01 5Gi RWO,RWX Retain Available 1h
pv-02 10Gi RWO,RWX Retain Available 1h
pv-03 15Gi RWO,RWX Retain Available 1h

然后定义statefulset 应用,如下:
```bash
[[email protected] statefulset-test]# cat statefulset.yaml
apiVersion: v1
kind: Service
metadata:
  name: ngx-svc
  labels:
    app: ngx-svc
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: ngx-sts
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: ngx-sts
spec:
  serviceName: ngx-svc #声明它属于哪个Headless Service
  replicas: 2
  selector:
    matchLabels:
      app: ngx-sts  #has to match .spec.template.metadata.labels
  template:
    metadata:
      labels:
        app: ngx-sts #has to match .spec.selector.matchLabels
    spec:
      containers:
      - name: ngx-sts
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: ngxvol
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: ngx-volumes
    spec:
      accessModes: ["ReadWriteMany"]
      resources:
        requests:
          storage: 5Gi
 
[[email protected] statefulset-test]# kubectl apply -f statefulset.yaml
[[email protected] statefulset-test]# kubectl get service |grep nginx-svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
ngx-svc      ClusterIP   None         <none>        80/TCP    56s
[[email protected] statefulset-test]# kubectl get statefulset
NAME      DESIRED   CURRENT   AGE
ngx-sts       2         2         5m
[[email protected] statefulset-test]# kubectl get pods
NAME          READY     STATUS    RESTARTS   AGE
ngx-sts-0     1/1       Running     0        2m
ngx-sts-1     1/1       Running     0        2m
[[email protected] statefulset-test]# kubectl get pvc
NAME                       STATUS     VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ngx-volumes-ngx-sts-0      Bound      pv01      5Gi        RWO,RWX                       12m
ngx-volumes-ngx-sts-1      Bound      pv02      10Gi       RWO,RWX                       12m
#每个pod的FQDN(完全现定域名)被定义为:$(pod.name).(headless server name).namespace.svc.cluster.local
#每个PVC 的名称又由两个部分组成:$(volumeClaimTemplates.name)-(pod.name) ,代表该PVC由哪个volumeClaimTemplates申请创建,且永远被挂载到$(pod.name)上。当原Pod被删除之后,PVC保持不变,数据不会丢失(手动删除pvc将自动释放pv)。当新Pod被创建之后,原podname会被继承,也会再次挂载到原Volume之上。

pod的扩展、收缩都是按照顺序执行

[[email protected] statefulset-test]# kubectl scale statefulset ngx-sts --replicas=3
statefulset.apps/ngx-sts scaled
[[email protected] statefulset-test]# kubectl get pods
NAME          READY     STATUS    RESTARTS   AGE
ngx-sts-0     1/1       Running   0          1h
ngx-sts-1     1/1       Running   0          1h
ngx-sts-2     1/1       Running   0          1m
[[email protected] statefulset-test]# kubectl get pvc
NAME                       STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ngx-volumes-ngx-sts-0      Bound     pv01      5Gi        RWO,RWX                       30m
ngx-volumes-ngx-sts-1      Bound     pv02      10Gi       RWO,RWX                       30m
ngx-volumes-ngx-sts-2      Bound     pv03      15Gi       RWO,RWX                       1ms
[[email protected] statefulset-test]# kubectl patch statefulset ngx-sts -p '{"spec":{"replicas":2}}'
statefulset.apps/ngx-sts patched
[[email protected] statefulset-test]# kubectl get pods
NAME          READY     STATUS    RESTARTS   AGE
ngx-sts-0     1/1       Running   0          5m
ngx-sts-1     1/1       Running   0          6m

更新策略
在Kubernetes 1.7及更高版本中,通过.spec.updateStrategy字段允许配置或禁用Pod、labels、source request/limits、annotations自动滚动更新功能。
OnDelete(默认方式):通过.spec.updateStrategy.type 字段设置为OnDelete,StatefulSet控制器不会自动更新StatefulSet中的Pod。用户必须手动删除Pod,以使控制器创建新的Pod。
RollingUpdate:通过.spec.updateStrategy.type 字段设置为RollingUpdate,实现了Pod的自动滚动更新,如果.spec.updateStrategy未指定,则此为默认策略。
StatefulSet控制器将删除并重新创建StatefulSet中的每个Pod。它将以Pod终止(从最大序数到最小序数)的顺序进行,一次更新每个Pod。在更新下一个Pod之前,必须等待这个Pod Running and Ready。
Partitions:通过指定 .spec.updateStrategy.rollingUpdate.partition 来对 RollingUpdate 更新策略进行分区,如果指定了分区,则当 StatefulSet 的 .spec.template 更新时,具有大于或等于分区序数的所有 Pod 将被更新。
具有小于分区的序数的所有 Pod 将不会被更新,即使删除它们也将被重新创建。如果 StatefulSet 的 .spec.updateStrategy.rollingUpdate.partition 大于其 .spec.replicas,则其 .spec.template 的更新将不会传播到 Pod。在大多数情况下,不需要使用分区。