k8s之statefulset控制器

k8s之statefulset控制器

statefulset概述

stateful和stateless

”状态“

​ 进程的时间属性,即随之时间的推进,进程处理的前后请求有无相关性,前面的请求处理对后续的请求处理有无影响,有影响的叫有状态应用;没有影响的前后的请求处理都是独立的叫无状态应用;

对于有状态的应用,k8s用statefulset控制器进行管理:保证了每个pod都由一个专用索引、有序部署、有序停止、固定的标识符、固定的存储卷,即便pod被重构后,各种特性也和之前保持一致;

statefulset的特性

statefulset的基础构成:

  • headless service:用于解析各个pod的地址;
  • statefulset:管理pod的生命周期;
  • volumeClaimTemplate:基于静态或动态pv供给的方式绑定pv,给每一个pod

如图所示:

  • 每个pod都有固定且唯一的标号
  • 都有一个pvc并绑定一个pv,重构后也不变
  • pod编号为数字结尾,pod启动是由小到大依次启动,停止则是反过来

image-20201122154841425

statefulset基础应用

创建statefulset对象

1、创建pv对象

​ 创建2个pv对象,后端存储是nfs,没有动态pv供给能力,但都定义在state存储类中,由后面statefulset的volumeClaimTemplates引用;

[root@client statefulset]# cat 1pv.yaml 2pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
 name: state-pv1
spec:
 capacity: 
  storage: 1Gi
 accessModes:
 - ReadWriteMany
 storageClassName: state
 nfs:
  path: /pv1
  server: 192.168.80.101
apiVersion: v1
kind: PersistentVolume
metadata:
 name: state-pv2
spec:
 capacity: 
  storage: 1Gi
 accessModes:
 - ReadWriteMany
 storageClassName: state
 nfs:
  path: /pv2
  server: 192.168.80.101
  
  [root@client statefulset]# kubectl get pv
NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
state-pv1   1Gi        RWX            Retain           Available           state                   8s
state-pv2   1Gi        RWX            Retain           Available           state                   34s

2、定义statefulset对象并创建

​ 定义了headless的service,然后定义了statefulset控制器对象,在volumeClaimTemplates中引用了名为state的存储类,该类为上步定义的2个nfs的pv

[root@client statefulset]# cat statefulset-demo.yaml 
apiVersion: v1
kind: Service
metadata:
 name: svc-state
spec:
 ports:
 - port: 80
   name: web
 clusterIP: None
 selector:
  app: app-state
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: state-stateset
spec:
 serviceName: svc-state
 replicas: 2
 selector:
  matchLabels:
   app: app-state
 template:
  metadata:
   labels:
    app: app-state
  spec:
   containers:
   - name: myapp
     image: ikubernetes/myapp:v5
     ports:
     - containerPort: 80
       name: web
     volumeMounts:
     - name: myappdata
       mountPath: /usr/share/nginx/html
 volumeClaimTemplates:
  - metadata:
     name: myappdata
    spec:
     accessModes: 
     - ReadWriteMany
     storageClassName: "state"
     resources:
      requests:
       storage: 1Gi

3、查看

​ 查看statefulset控制器的events事件,

Events:
  Type    Reason            Age   From                    Message
  ----    ------            ----  ----                    -------
  Normal  SuccessfulCreate  3s    statefulset-controller  create Claim myappdata-state-stateset-0 Pod state-stateset-0 in StatefulSet state-stateset success
  Normal  SuccessfulCreate  3s    statefulset-controller  create Pod state-stateset-0 in StatefulSet state-stateset successful

4、问题?

 Warning  FailedMount  22s  kubelet, node1  MountVolume.SetUp failed for volume "state-pv2" : mount failed: exit status 32
创建pod时卡住,查看pod事件为绑定卷阶段出错了,

固定的pod标识符和存储卷

​ 若statefulset创建成功,观察到的现象应该是:依次启动或停止;重建pod后,其主机名、存储卷pv、dns的解析记录cname都不变,其中dns解析的是cname保持不变,但具体到pod的ip还是会变;

statefulset资源扩缩容

​ statefulset扩容pod时,和deployment控制器类似,采用kubectl scale 加 --replicas=数量N即可,或者修改yaml文件再重新apply也可以;

​ statefulset的扩缩容,也都是按照顺序,串行执行的;

statefulset资源更新

滚动更新

kubectl set image statefulset state_name image_name=image_new_version

滚动更新也是按照顺序来的

设置字段:[root@client k8s_yaml]# kubectl explain statefulset.spec.updateStrategy

暂存更新

​ 假设statefulset设置的副本数为3,那么其pod编号就是xx-0,xx-1,xx-2,所谓暂存更新就是将paritions数值设置为和副本数相等,即比pod编号大1,partions分区的意义为大于及等级该数值的pod会被更新;(需要先set image或直接修改yaml文件修改镜像的版本号)

​ 默认partition数值是0,即更新了镜像版本后,pod会立刻开始逐个按照次序更新

​ 如果将partition数值设置的一开始就和副本数一样大,那么即便更改了镜像版本,pod也不会开始更新,即暂存更新

语法:

[root@client k8s_yaml]# kubectl explain statefulset.spec.updateStrategy.rollingUpdate
KIND:     StatefulSet
VERSION:  apps/v1

RESOURCE: rollingUpdate <Object>

DESCRIPTION:
     RollingUpdate is used to communicate parameters when Type is
     RollingUpdateStatefulSetStrategyType.

     RollingUpdateStatefulSetStrategy is used to communicate parameter for
     RollingUpdateStatefulSetStrategyType.

FIELDS:
   partition	<integer>
     Partition indicates the ordinal at which the StatefulSet should be
     partitioned. Default value is 0.

金丝雀部署

​ 在上一步设置了partition分区数值的基础之上,逐步调小分区数的值,假设调整到了2,那么编码为xx-2的pod会开始进行更新;

分阶段更新

​ 和金丝雀部署更新类似,即分阶段修改分区数的值,直到0,假设pod有6个,编码分别从0-5,可以分3次将分区数设置为5、3、0,那么statefulset控制器会控制pod,进行3次更新,更新编码5、更新编码4,3、更新剩下的2,1,0;直到全部pod更新完毕;

ps:通常statefulset无法真正实现有状态应用pod的管理,因为不同类型的应用所需的运维操作不同,一般需要为不同的应用创建不同的operator,operator是对statefulset的进一步封装;一种operator只能管理一种有状态应用,如mysql、redis

红帽对operator介绍:https://www.redhat.com/en/topics/containers/what-is-a-kubernetes-operator

updatedupdated2020-12-012020-12-01
加载评论