StatefulSet 更新策略

StatefulSet 和 Deployment 一样,也提供了多种更新策略,可以在 .spec.updateStrategy 字段中指定StatefulSet 的更新策略。

  • OnDelete 策略

    • OnDelete 更新策略实现了传统的更新行为。

    • 当选择这个更新策略并修改 StatefulSet 的 .spec.template 字段时,StatefulSet 控制器不会自动更新 Pod,必须手动删除 Pod 才能使控制器创建新的 Pod

  • RollingUpdate 策略(默认策略)

    • RollingUpdate(滚动更新)策略会自动更新一个 StatefulSet 中所有的 Pod,采用与序号索引相反的顺序进行滚动更新

滚动更新示例

$ kubectl set image sts web nginx=nginx:1.25.3
statefulset.apps/web image updated

如上所述,StatefulSet 中的 Pod 采用和序号相反的顺序更新。

  • 在更新下一个 Pod 前,StatefulSet 控制器会终止每一个 Pod 并等待它们变成 Running 和 Ready 状态。

  • 在当前顺序变成 Running 和 Ready 状态之前,StatefulSet 控制器不会更新下一个 Pod,但它仍然会重建任何在更新过程中发生故障的 Pod,使用它们当前的版本。

  • 已经接收到请求的 Pod 将会被恢复为更新的版本,没有收到请求的 Pod 则会被恢复为之前的版本。

$ kubectl get pod -w -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          3m21s
web-1   1/1     Running   0          3m19s
web-1   1/1     Terminating   0          3m52s
web-1   1/1     Terminating   0          3m52s
web-1   0/1     Terminating   0          3m52s
web-1   0/1     Terminating   0          3m53s
web-1   0/1     Terminating   0          3m53s
web-1   0/1     Terminating   0          3m53s
web-1   0/1     Pending       0          0s
web-1   0/1     Pending       0          0s
web-1   0/1     ContainerCreating   0          0s
web-1   0/1     ContainerCreating   0          1s
web-1   1/1     Running             0          2s
web-0   1/1     Terminating         0          3m57s
web-0   1/1     Terminating         0          3m58s
web-0   0/1     Terminating         0          3m58s
web-0   0/1     Terminating         0          3m58s
web-0   0/1     Terminating         0          3m58s
web-0   0/1     Terminating         0          3m58s
web-0   0/1     Pending             0          0s
web-0   0/1     Pending             0          0s
web-0   0/1     ContainerCreating   0          0s
web-0   0/1     ContainerCreating   0          1s
web-0   1/1     Running             0          2s

获取 Pod 来查看它们的容器镜像:

$ for p in 0 1; do kubectl get pod "web-$p" --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'; echo; done
nginx:1.25.3
nginx:1.25.3

分段更新

可以使用 RollingUpdate 更新策略的 partition 参数来分段更新一个 StatefulSet。

分段更新将会只更新序号大于等于分区的 Pod其余的所有 Pod(序号小于分区)保持当前版本,利用此特性可以简单实现金丝雀发布(灰度发布)或者分阶段推出新功能等。

比如我们定义一个分区"partition":3,可以使用 patch edit 直接对 StatefulSet 进行设置:

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

使用 patch 改变容器的镜像:

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

测试小于分区的Pod将保持当前版本

删除Pod触发更新:

$ kubectl delete pod web-2
pod "web-2" deleted

此时,因为 Pod web-2 的序号小于分区 3,所以 Pod 不会被更新,还是会使用以前的容器恢复 Pod。

$ kubectl get pod web-2 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
nginx:1.25.3

测试序号大于等于分区的Pod会被更新

将分区改为 2,此时会自动更新 web-2,但是不会更新 web-0 和 web-1:

kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":2}}}}'
kubectl get pod web-2 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'
registry.k8s.io/nginx-slim:0.7

最后更新于