OpenKruise原地升级

OpenKruise master

为什么使用原地升级

原地升级含义:更新容器镜像,只升级容器,不触发Pod重建
原地升级优势:节省了调度、CNI和CSI、大部分拉取镜像耗时
针对k8s集群大量Pod升级场景,减小k8s集群压力。
在OpenKruise中支持原地升级的workload/controller是CloneSet、Advanced StatefulSet、Advanced DaemonSet、SidecarSet。

原地升级流程

步骤1:判断是否支持原地升级容器
pkg/controller/daemonset/daemonset_update.go
canPodInPlaceUpdate方法

pkg/controller/daemonset/daemonset_util.go
ContainsReadinessGate方法

1.Pod spec要有ReadinessGates且conditionType是InPlaceUpdateReady
2.Pod上修改的是annotation/lables或者容器镜像或者基于annotation/labels生成的env

pod中spec部分可修改内容很有限。


步骤2:设置conditionType InPlaceUpdateReady false来摘流(SidecarSet除外)
Pod是否Ready除了看容器是否Ready之外,k8s 1.12新增了readinessGates conditionType来自定义控制Pod Ready。
Pod notReady后kube-controller-manager中EndpointController更新endpoints来触发kube-proxy摘流。
步骤3:优雅等待升级
确保摘流完成
pkg/controller/cloneset/sync/cloneset_update.go
Update方法

从Pod注解apps.kruise.io/inplace-update-grace中获取优雅升级等待时间。
步骤4:kruise-manager更新Pod image等字段
步骤5:kubelet或者kruise-daemon停止容器
针对更新镜像场景,kubelet停止容器;针对更新env场景,kruise-daemon停止容器。
kubelet在创建Pod.spec.containers容器时会计算hash值,镜像更新后hash值变化,重拉容器。
步骤6:kubelet拉起新容器
步骤7:kruise-manager根据imageId是否更新来确认原地升级是否已完成
pkg/control/sidecarcontrol/sidecarset_control.go
IsSidecarContainerUpdateCompleted函数

之所以不使用imageName来判断,是因为kubelet通过CRI来获取容器镜像信息,存在不同镜像名字镜像id相同的情况。
步骤8:kruise-manager设置condition InPlaceUpdateReady true后kubelet设置Pod Ready

手动触发原地升级

修改Pod镜像版本(从nginx:1.9改成nginx:1.10)

kubectl edit pod nginx-deployment-74fb98df8b-92r6n

业务容器重建了,pause容器没有重建

确认新容器使用的镜像是nginx:1.10

参考资料

揭秘:如何为 Kubernetes 实现原地升级
OpenKruise-原地升级
OpenKruise 源码剖析之原地升级

posted on 2023-06-12 10:53  王景迁  阅读(338)  评论(0编辑  收藏  举报

导航