k8s 经典面试:如何保障滚动升级的时候,流量不中断 - 今日头条

本文由 简悦 SimpRead 转码, 原文地址 www.toutiao.com

这个问题比较容易解决,k8s 为了避免 Pod 没有启动就导入流量引入了健康检查机制,只有在 readiness probe 检测成功后,pod 的

我们在 k8s 里面更新镜像 image 字段后就会触发一次滚动升级,杀掉老的 Pod,创建新的 Pod,从而完成服务版本的升级。但升级的过程其实并非是平滑的,因为 pod 的启动关闭都并非瞬时的。

这里会存在两个问题,第一是将流量打到正在关闭的 Pod,第二是将流量打到还未启动成功的 Pod 上。

https://p3.toutiaoimg.com/origin/pgc-image/437f28b181664f68a5a1818e2ebf1c5d?from=pc

这个问题比较容易解决,k8s 为了避免 Pod 没有启动就导入流量引入了健康检查机制,只有在 readiness probe 检测成功后,pod 的状态才是 ready。这样 k8s 才会把这个 pod 加入到 service 里面。

这个问题稍微复杂一些,因为 pod 停止和 从 service 里面把 pod 摘除这两个动作完全是同步进行的,很有可能,pod 里面的服务已经正在停止了,而 service 还没有摘掉,流量还是会打到这个 Pod 上面。

这时很多童鞋会想到我之前发的 k8s 里面应用如何优雅退出的文章,是不是可以通过优雅退出解决这个问题。其实,k8s 提供的优雅退出是为了让程序能够在结束之前回收资源,处理完未执行的事务。但并不能严格保证服务已经从 service 上摘除。

其实 k8s 还有一个小技巧:prestop hook,从名字就可以看出,它是在容器执行优雅关闭之前执行的。那么我们可以在执行关闭前,先 sleep 5 秒,这样确保 pod 可以从 service 里面拆除,如果你的集群延迟比较大,也可以改成 10 秒。

1
2
3
4
lifecycle:
        preStop:
          exec:
            command: ["sleep", "5"]

这样无论是新启动 pod 还是 pod 停止,都可以很流畅的进行,中间不会出现流量的中断了。