最近在拿到一个task是在Jenkins pipeline里做Integration Test,测试执行的环境是K8S。这就必不可少会用到Deployment的rolling update,而在部署更新之后需要在pipeline中等待rollout完成,我在网上查到可以通过以下命令实现:
> kubectl rollout status deployment xxx --watch --timeout=5m
Waiting for deployment "xxx" rollout to finish: 1 old replicas are pending termination...
deployment "xxx" successfully rolled out
一开始我以为看到“successfully rolled out”就意味着这个service可以开始接收我对它的HTTP request了,但是在测试的过程中会发现,偶尔会得到"ECONNREFUSED"的错误,说明request并没有被接收,可能的一个原因就是Service通过selector选择的Pod不是available的。但前面明明已经successfully了啊,看来这个成功并不能保证Pod也成功地从Service中被移出了。后来Google了一下,发现果然有人遇到了类似的问题。要解决这个问题得先搞清楚当删除一个Pod的时候,K8S就究竟干了些什么。下面的流程是我参考文档后按照自己的理解梳理的,后面我会把参考文档贴出来。
当删除Pod时发生了什么?
- 删除Pod,这里可以通过kubectl delete pod xxx或Deployment的rolling upate手动触发
- API server会把这个Pod的Status标注为Terminating,并且这里会有一个叫grace period的计时,它的默认值是30s,可以通过配置延长。
- 当Kubelet发现一个Pod被标注为Terminating时,就会开始执行Pod shutdown的流程
- 首先检查Pod里的containers是否有preStop hook,如果有就会在对应的container里执行。如果preStop执行的时间超过了grace period的时间,K8S只会做一次2s的临时加时。这种情况下,我们最好是通过配置 terminationGracePeriodSeconds 来保证preHook里的内容能够完全执行。
- 执行完preStop hook,K8S会发送一个SIGTERM信号给这个container,告知它马上要被shut down了,此时Pod就会开始停止接收新的traffic
- 在做第3步的同时,Pod会从endpoints(它是和Service对应的)里被删除
- 如果到这里还没结束,并且时间超过了grace period,Pod里所有正在运行的进程都会被SIGKILL所杀掉
- Kubelet会在API server上通过设置grace period为0(立即删除)来完成Pod的删除。至此,Pod彻底被干掉了
在上面的流程中,要注意第3步和第4步是同时发生的,并且这两步都是异步执行的。重点就是在第3步container已经收到SIGTERM信号了,但是这个时候第4步还没执行完,也就是说不在接受traffic的Pod此时还是可以通过service name访问到的,所以就产生了前面提到的connection refused的问题。这其实是一个race的问题,如果第4步比第3步先做完,那在前面提到的case中就不会有问题了。
这里加个后面画的图,下图中的1,2,3是同时发生并且异步执行的,第2点下的1和2是按顺序同步执行的。
解决上述问题的一个方案是就是在preStop hook中sleep一下,让SIGTERM信号晚一点达到,给够把Pod从Service中删除的时间,在Github上看到有人建议sleep 20,也有人说sleep 3就足以把Pod从Service中删除了。在Deployment的container中添加如下配置,
containers:
- name: xxxC1
lifecycle:
preStop: exec: command: ["sleep, "3"]
不过尴尬的是我们用的base image里为了security并没有bash或者sh,所以这个方案还是没办法解决我面临的情况。但是总归还是有所收获^^
References
https://github.com/kubernetes/kubernetes/issues/86280
https://github.com/kubernetes/kubernetes/issues/43576
https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods
https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-terminating-with-grace
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)