最近在拿到一个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时发生了什么?

  1. 删除Pod,这里可以通过kubectl delete pod xxx或Deployment的rolling upate手动触发
  2. API server会把这个Pod的Status标注为Terminating,并且这里会有一个叫grace period的计时,它的默认值是30s,可以通过配置延长。
  3. 当Kubelet发现一个Pod被标注为Terminating时,就会开始执行Pod shutdown的流程
    1. 首先检查Pod里的containers是否有preStop hook,如果有就会在对应的container里执行。如果preStop执行的时间超过了grace period的时间,K8S只会做一次2s的临时加时。这种情况下,我们最好是通过配置 terminationGracePeriodSeconds 来保证preHook里的内容能够完全执行。
    2. 执行完preStop hook,K8S会发送一个SIGTERM信号给这个container,告知它马上要被shut down了,此时Pod就会开始停止接收新的traffic
  4. 在做第3步的同时,Pod会从endpoints(它是和Service对应的)里被删除
  5. 如果到这里还没结束,并且时间超过了grace period,Pod里所有正在运行的进程都会被SIGKILL所杀掉
  6. 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

 

Posted on 2020-05-22 23:20  單筱寒  阅读(1050)  评论(1编辑  收藏  举报