0
点赞
收藏
分享

微信扫一扫

k8s如何优雅地关闭Pod


文章目录

  • ​​一、k8s删除Pod的过程​​
  • ​​`网络规则生效`​​
  • ​​`删除 pod`​​
  • ​​二、可能遇到的问题​​
  • ​​`502`​​
  • ​​`504`​​
  • ​​三、如何避免上述问题​​
  • ​​`为容器内的进程设置正常关闭`​​
  • ​​`添加 preStopHook`​​
  • ​​`修改终止 GracePeriodSeconds`​​
  • ​​四、制作一个可以优雅关闭的镜像​​
  • ​​五、参考文章​​

一、k8s删除Pod的过程

在删除pod 的过程中,有两条平行的时间线。一是改变网络规则的时间线,另一个是 pod 的删除。

k8s如何优雅地关闭Pod_docker

网络规则生效

  • kube-apiserver 接收到 pod 删除请求,将 pod 在 Etcd 中的状态更新为 Terminating;
  • Endpoint Controller 从 Endpoint 对象中删除 pod 的 IP;
  • kuber-proxy 根据 Endpoint 对象的变化更新 iptables 的规则,不再将流量路由到被删除的 Pod。

删除 pod

  • kube-apiserver 接收到 Pod 删除请求,将 Pod 的在 Etcd 中的状态更新为 Terminating
  • preStop 钩子被执行
  • Kubelet 向容器发送 SIGTERM
  • 继续等待,直到容器停止,或者超时 spec.terminationGracePeriodSeconds,这个值默认为 30s
  • 如果超过了 spec.terminationGracePeriodSeconds 容器仍然没有停止,k8s 将会发送 SIGKILL 信号给容器
  • 进程全部终止后,整个 Pod 完全被清理掉

注意:这个优雅退出的等待计时spec.terminationGracePeriodSeconds是与 preStop 同步开始的,而且它也不会等待 preStop 结束

二、可能遇到的问题

502

应用程序在收到 ​​SIGTERM​​ 信号后直接终止了运行,导致部分还没有被处理完的请求直接中断,代理层返回 502

504

Service Endpoints 移除不够及时,在 Pod 已经被终止后,仍然有个别请求被路由到了该 Pod,得不到响应导致 504

三、如何避免上述问题

为容器内的进程设置正常关闭

以 SpringBoot 为例,启用优雅关闭可以 Spring Boot 配置文件中添加下面设置

server:
shutdown: graceful

spring:
lifecycle:
timeout-per-shutdown-phase:

可以解决502的问题

添加 preStopHook

当kube-apiserver 接收到 pod 删除请求后,必须要预留一段时间,来等待网络规则的更新,避免新的流量路由到一个不可用的pod上 。

因此,应该让 Kubelet 在收到删除 pod 事件时“sleep 一下”,并在给Pod发送SIGTERM之前留出足够的时间来更新网络规则。

containers:
- name: my-app
# 添加下面这部分
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- "sleep 10"

可以解决504的问题

修改终止 GracePeriodSeconds

Kubernetes 为容器删除留下了 30 秒的最大时间尺度。如果 Spring 的优雅关闭超时时间和 Kubernetes 的 preStopHooks 之和超过 30 秒,可能会导致 Kubernetes 在 Spring Boot 处理完请求之前强行删除容器。因此,如果过程超过 30 秒,则应将 timerminationGracePeriodSeconds 调整为大于30秒

下图显示了设置后的时间线:

k8s如何优雅地关闭Pod_spring_02

四、制作一个可以优雅关闭的镜像

参考文章:​​docker制作java镜像​​

k8s如何优雅地关闭Pod_docker_03

五、参考文章

​​K8s里Spring 微服务项目,Pod 关闭对用户的影响比较大!​​​​在 Kubernetes 容器集群,微服务项目最佳实践​​


举报

相关推荐

0 条评论