Kubernetes运维:容器滚动升级
文章目录
1. 探针机制
Kubernetes 中客户端通过 Service 访问容器服务时,kube-proxy 根据同名 Endpoints 中 subsets 列表随机选择一个后端 Pod 进行流量转发。
下图展示了 Service 到 Pod IP 的映射关系:
当 Pod 副本异常退出时,可以看到 Endpoints 的 subsets 列表被 Kubernetes 的管理服务更新。此时外部通过 ClusterIP 或 NodePort 访问容器服务时,流量不会路由到发生异常的容器:
Kubernetes 还通过探针机制检查 Pod 的运行状况检查,动态更新 Endpoints 的 subsets 列表,因此用户需要小心设置 Pod 中探针的相关配置,才能保证在部署、升级等过程中服务持续可用。
Kubernetes 中可以配置以下三种类型的探针:
- Liveness Probe: 用于检测容器是否存活,如果探测失败,kubelet 会重启容器(PS:重启不会触发重新调度)。
- Readiness Probe: 用于检测容器是否准备好接收流量,如果探测失败,端点控制器会从与 Pod 匹配的 Service 的 Endpoints 列表中移除该 Pod。
- Startup Probe: 用于检测容器是否启动成功,在容器启动成功之前,其他的探针不会生效,如果探测失败,kubelet 会重启容器。
每种探针都支持三种方式进行探测:
- HTTP GET Probe: 向容器的 IP 地址、端口和路径发送一个 HTTP GET 请求,如果响应的状态码在 200 到 399 之间,就认为探测成功。
- TCP Socket Probe: 尝试建立一个 TCP 连接到容器的指定端口,如果连接成功,就认为探测成功。
- Exec Probe: 在容器内执行一个指定的命令,如果命令返回 0,就认为探测成功。
- gRPC Probe:在容器中通过 gRPC 命令进行健康检查(PS:要求 Kubernetes 1.24 以上版本)。
通常用户需要配置 Readiness Probe 和 Liveness Probe 探针以提高应用程序的可靠性和可用性,下图仅有一个容器的 readinessProbe 正常工作,因此 Service 后端仅指向一个 PodIP。
参考资料
-
Kubernetes 探针 官方文档
-
Kubernetes 相关源码目录:
-
Probe 探针控制器:pkg/kubelet/prober
-
Probe 探针实现类:pkg/probe
-
EndPoint 控制器:pkg/controller/endpoint
-
2. 控制器升级策略
Kubernetes 主要负载控制器 Deployment、DaemonSet、Statefulset 都支持配置滚动更新。
在满足以下条件后,可以不中断业务的情况下对容器进行平滑更新。
-
业务部署为多副本
-
业务容器合理设置了 readinessProbe
-
合理设置了这些控制器的更新策略
Deployment
Deployment 支持以下两种方式更新容器:
- Recreate:同时终止所有容器副本,当旧副本完全结束后,同时拉起新的副本。
- RollingUpdate:滚动升级副本容器,用户可以通过额外的参数控制滚动的过程。
默认情况下 Deployment 通过 RollingUpdate 的方式,用户可以控制参数包含以下两个:
- maxSurge(默认配置 25%):可以创建的最大Pod数,即新旧 Pod 之和不能超过 replicas + maxSure,该值可以是绝对数或百分比。
- maxUnavailable(默认配置 25%):在更新过程中可能不可用的最大Pod数,该值可以是绝对数或百分比。
下面配置中,maxSurge 和 maxUnavailable 均被设置为 1,此时 Kubernetes 将逐个更新 Pod 副本。
|
|
DaemonSet
DaemonSet 支持以下两种方式更新容器:
- OnDelete:在更新 DaemonSet 后,只有在手动删除旧的 DaemonSet Pod 时才会创建新的DaemonSet Pod。
- RollingUpdate:滚动升级每个节点上的容器,用户可以通过额外的参数控制滚动的过程。
默认情况下 DaemonSet 通过 RollingUpdate 的方式更新,用户可以调整的参数和 Deployment 相同,但对应的默认值不同。
- maxSurge(默认配置 0):maxSurge 配置为 0 时,可以保证任意时刻、任意节点上只有 Pod 在运行。
- maxUnavailable(默认配置 1): maxUnavailable 配置为 1 时,可以保证任意时刻只有一个节点在更新容器。
Statefulset
Statefulset 支持以下两种方式更新容器:
- OnDelete:含义和 DaemonSet 一致。
- RollingUpdate:滚动升级每个节点上的容器,用户可以通过额外的参数控制滚动的过程。
Statefulset 的滚动升级比较复杂,以下先说明默认配置下 Statefulset 的更新策略。
默认配置
默认配置下 Statefulset 通过 RollingUpdate 的方式更新,此时 kubernetes 如何更新 Pod 取决于用户在 Statefulset 中定义的 spec.podManagementPolicy 参数。该参数有以下两种取值:
- OrderedReady(默认):从编号最大的 Pod 开始,逐个滚动更新 Pod
- Parallel:同时更新所有 Pod,等价于 Deployment 的 ReCreate。
默认配置下,Statefulset 更新策略实际上和 Deployment 一致。
分区滚动
Statefulset 中我们可以配置以下参数,实现分区滚动升级:
- partition(默认值 0):在更新 StatefulSet 时,序号大于或等于该 partition 的所有Pod都将被更新。序号小于 partition 的所有 Pod 将不会被更新,即使它们被删除,它们也将在以前的版本中重新创建。
v1.24 以上版本,Statefulset 还支持 maxUnavailable 参数,其含义和 Deployment 一致。
以下 Statefulset 定义了一个 5 副本的容器服务,并且将分区参数设置为 3 :
|
|
Statefulset 控制器将创建以下容器:
此时手工编辑 Statefulset 变更容器使用的镜像,由于我们定义了分区更新此时只用 whoami-3 和 whoami-4 发生更新,如下图:
总结:基于 Statefulset 的分区更新机制,业务可以自行设计金丝雀部署、蓝绿部署、灰度发布等策略。
文章作者 yoaz
上次更新 2023-05-16
许可协议 MIT