Kubernetes中的优雅关闭和零停机时间部署( 五 )


Kubernetes中的优雅关闭和零停机时间部署

文章插图
4. 谁会监听Endpoint的更改?kube-proxy、Ingress控制器、CoreDNS等组件会收到关于这一变更的通知 。
Kubernetes中的优雅关闭和零停机时间部署

文章插图
5. 一些组件 , 如kube-proxy , 可能需要额外的时间来进一步传播这些更改 。
Kubernetes中的优雅关闭和零停机时间部署

文章插图
与此同时,etcd中的Pod状态被更改为Terminating(终止中) 。
kubelet收到此变更的通知,并进行以下操作:
  1. 将容器中的任何挂载卷从容器存储接口(CSI)卸载 。
  2. 将容器从网络中分离,并释放IP地址给容器网络接口(CNI) 。
  3. 将容器销毁给容器运行时接口(CRI) 。
换句话说,Kubernetes按照与创建Pod完全相同的步骤来进行反向操作 。
1. 如果你使用kubectl delete pod删除一个Pod,该命令首先会发送到Kubernetes API 。
Kubernetes中的优雅关闭和零停机时间部署

文章插图
2. 当kubelet轮询控制平面以获取更新时,它会注意到Pod已被删除 。
Kubernetes中的优雅关闭和零停机时间部署

文章插图
3. kubelet将销毁Pod的任务委托给容器运行时接口(Container Runtime Interface)、容器网络接口(Container Network Interface)和容器存储接口(Container Storage Interface) 。
Kubernetes中的优雅关闭和零停机时间部署

文章插图
然而 , 这里存在一个微妙但关键的区别 。
当你终止一个Pod时,移除端点和向kubelet发送的信号同时发出 。
当你首次创建一个Pod时,Kubernetes会等待kubelet报告IP地址,然后开始端点传播 。
然而,当你删除一个Pod时,事件会并行发生 。
这可能导致多种竞争条件的出现 。
如果在端点传播之前删除了Pod会怎样呢?
1. 删除端点和删除Pod同时进行 。
Kubernetes中的优雅关闭和零停机时间部署

文章插图
2. 因此,在kube-proxy更新iptables规则之前,你可能会先删除端点 。
Kubernetes中的优雅关闭和零停机时间部署

文章插图
3. 或者你可能更幸运,只有在端点完全传播之后才删除Pod 。
【Kubernetes中的优雅关闭和零停机时间部署】
Kubernetes中的优雅关闭和零停机时间部署

文章插图
优雅关闭当一个Pod在从kube-proxy或Ingress控制器中移除端点之前被终止时,你可能会遇到停机时间 。
如果仔细思考一下,这是有道理的 。
Kubernetes仍然将流量路由到该IP地址,但Pod已经不存在了 。
Ingress控制器、kube-proxy、CoreDNS等组件没有足够的时间将IP地址从其内部状态中移除 。
理想情况下,Kubernetes应该在删除Pod之前等待集群中的所有组件都具有更新的端点列表 。
但是Kubernetes并不是这样工作的 。
Kubernetes提供了强大的原始组件来分发端点(例如Endpoint对象和更高级的抽象,如Endpoint Slices) 。
然而 , Kubernetes并不验证订阅端点变更的组件是否与集群状态保持同步 。
那么,为了避免这种竞争条件并确保在端点传播后删除Pod , 你可以做些什么呢?
你应该等待 。当Pod即将被删除时 , 它会收到一个SIGTERM信号 。
你的应用程序可以捕获该信号并开始关闭 。
由于在Kubernetes中不太可能立即从所有组件中删除端点 , 你可以:
  1. 在退出之前等待更长的时间 。
  2. 尽管收到SIGTERM信号 , 仍然处理传入的流量 。
  3. 最后 , 关闭现有的长连接(例如数据库连接或WebSockets) 。
  4. 关闭进程 。
你应该等待多长时间呢?默认情况下,Kubernetes会发送SIGTERM信号,并在强制终止进程之前等待30秒钟 。
因此,你可以在最初的15秒内继续正常运行 。
希望这个时间间隔足够将端点移除的更改传播到kube-proxy、Ingress控制器、CoreDNS等组件 。
随着时间的推移,越来越少的流量会到达你的Pod,直到最终停止 。
在15秒之后,可以安全地关闭与数据库(或任何持久连接)的连接并终止进程 。
如果你认为需要更多时间,可以在20或25秒时停止进程 。


推荐阅读