k8s☞12-2有状态服务StatefulSet

阅读量: zyh 2020-09-21 18:30:04
Categories: > Tags:

前言

当我们构建一个有状态的应用的时候, 例如 mysql / ftp / 包含session的管理界面等. 我们可能会有下列预期:

StatefulSet 就是干这个的。不过在实际的项目中,其实我们还是很少会去直接通过 StatefulSet 来部署我们的有状态服务的,除非你自己能够完全能够 hold 住,对于一些特定的服务,我们可能会使用更加高级的 Operator 来部署,比如 etcd-operator、prometheus-operator 等等,这些应用都能够很好的来管理有状态的服务,而不是单纯的使用一个 StatefulSet 来部署一个 Pod 就行,因为对于有状态的应用最重要的还是数据恢复、故障转移等等。

例子

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

特点

你可以通过设置statefulset管理策略, 来改变上述默认行为

https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy

StatefulSet.spec.podManagementPolicy设定为:Parallel 。就可以并发的创建Pod和删除Pod.

扩展/缩放

扩展: kubectl scale sts web --replicas=5

缩放: kubectl patch sts web -p '{"spec":{"replicas":3}}'

当然你也可以通过修改配置文件里 replicas 的值来进行变更.

更新

有状态应用的更新和无状态应用的更新有些差异.

有状态应用的更新策略(spec.updateStrategy)是 RollingUpdate 和 OnDelete. 其中 RollingUpdate 是默认策略, 这个是自动滚动更新. 而OnDelete的意思是只有你手动删除了pod才会更新.

更新是针对pod模板的. 例如:

kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.8"}]'

这里更新了nginx的镜像.

更新遵循以下原则:

🌟需要注意的是, 如果你的更新文件(二进制文件故障或者配置文件)有问题从而导致更新失败, 你可能需要强制回滚. 以下是说明信息:

即你恢复了更新前的模板,却发现statefulset依然不正常, 则你需要手动删除所有由错误模板产出的pod.

在这之后, statefulset将会采用更新前的模板重建pod.

(https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#forced-rollback)

阶段更新(staging an update)

有时候我们可能并不想一次更新所有, 此时可以进行阶段更新.

阶段更新的意思就是通过在索引上设置一个点. 当pod的索引大于等于这个点的时候, 才会更新. (默认点是索引0,即所有Pod都更新)

kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}'

这个意思是设置索引3为阶段分割点.

如果你想回到默认更新, 则只需要调整分割点, 重新执行上述命令即可.

删除

删除分为联级删除和非联级删除.

联级删除就是 statefulset 和 pod 都删除. 这是默认行为.

非联级删除, 只会删除 statefulset. 你可以通过删除的时候附加--cascade=false开启它.