《企业级云原生白皮书项目实战》——第三章 容器——3.2 业务部署——3.2.2 优雅更新(上) https://developer.aliyun.com/article/1229321?groupCode=supportservice
使用场景
•Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。 例如,没有必要仅为了在安装过程中使用类似 sed、awk、python 或 dig 这样的工具而去 FROM 一个镜像来生成一个新的镜像。
•Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。
•应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
•Init 容器能以不同于 Pod 内应用容器的文件系统视图运行。因此,Init 容器可以访问 应用容器不能访问的 Secret 的权限。
•由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器 提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。 一旦前置条件满足,Pod 内的所有的应用容器会并行启动。
•init 容器具有特权权限,应用容器一般情况下是没有此权限的,可以使用init 容器完成一些特权操作。
PostStart
这个回调在容器被创建之后立即被执行。但是,不能保证回调会在容器入口点(ENTRYPOINT)之前执行。 没有参数传递给处理程序。 对于 PostStart 回调,容器入口点和回调异步触发。 但是,如果回调运行或挂起的时间太长,则容器无法达到 running 状态。这个回调函数是在pod被创建后立马执行,可以认为是在pod程序运行前进行一个行为的执行,比如pod的应用程序启动比较慢或者启动时候非常消耗资源等,可以合理的设置poststart,让pod更加温和启动。
PreStop
在容器因 API 请求或者管理事件(诸如存活态探针、启动探针失败、资源抢占、资源竞争等) 而被终止之前,此回调会被调用。 如果容器已经处于已终止或者已完成状态,则对 preStop 回调的调用将失败。 在用来停止容器的 TERM 信号被发出之前,回调必须执行结束。 Pod 的终止宽限周期在 PreStop 回调被执行之前即开始所以无论 回调函数的执行结果如何,容器最终都会在 Pod 的终止宽限期内被终止。 没有参数会被传递给处理程序。
PreStop 回调并不会与停止容器的信号处理程序异步执行;回调必须在 可以发送信号之前完成执行。 如果 PreStop 回调在执行期间停滞不前,Pod 的阶段会变成 Terminating 并且一直处于该状态,直到其 terminationGracePeriodSeconds 耗尽为止, 这时 Pod 会被杀死。 这一宽限期是针对 PreStop 回调的执行时间及容器正常停止时间的总和而言的。 例如,如果 terminationGracePeriodSeconds 是 60,回调函数花了 55 秒钟 完成执行,而容器在收到信号之后花了 10 秒钟来正常结束,那么容器会在其 能够正常结束之前即被杀死,因为 terminationGracePeriodSeconds 的值 小于后面两件事情所花费的总时间(55+10)。
prestop是对于通过svc暴露服务的应用的在业务零中断的滚动更新重要考量之一。当Pod 被删除后,会被设置为 Terminating 状态,并从所有 Service 的 Endpoints 列表中删除。此时,Pod 停止获得新的流量,但依然可以处理老的流量请求,但是存在一种可能就是 Pod 收到 SIGTERM 信号并且停止工作后,但是还未从 Endpoints 或者ipvs的转发规则中移除,这时候就存在新的流量打到了停止的pod或者已经不存在的pod情况,从而造成了访问的5xx。所以建议为 pod 配置 preStop Hook,使 Pod 收到 SIGTERM 时 sleep 一段时间而不是立刻停止工作,而是相关的转发规则和endpoint移除后,pod才被终止工作,从而保证pod在终止前可以平滑的处理相关请求。
需要注意的是k8s对于pod有个参数terminationGracePeriodSeconds,默认是30s,表明pod如果prestop运行达到30s就会被立刻终止,此时如果应用的请求还未被处理完毕,依然会产生请求中断的情况,所以合理考虑和设置prestop是需要考虑的因素之一。一般情况下,我们建议terminationGracePeriodSeconds 时间建议设置为 preStop 的时间再加 30 秒以上,或者提前在镜像中写好了终止脚本,当pod收到term信号后,执行终止脚本,让应用程序优雅的主动关闭相关的连接请求。