D24 kubernetes 通过钩子如果优雅的停机{PreStop}

news/2024/9/24 16:55:14

1、背景

	在 Kubernetes 中,每次微服务的代码发布都意味着创建新版本的 pod 并删除旧 pod,如果部署不够优雅的话,可能出现如下两个问题:
  1. 正在处理请求的pod被删除,在请求没有做幂等处理的情况下,就会出现数据重复、数据错误,亦或导致分布式系统数据不一致;
  2. Kubernetes 将流量路由到已被删除的 pod,导致处理请求失败造成用户体验不佳。
    所以,为了让代码发布的部署过程不影响业务的正常运行和用户无感知,我们需要实现容器的优雅停机。

2、容器的生命周期钩子

	在介绍优雅停机之前,我们先来了解下k8s的容器都有哪些生命周期钩子?作用是什么?要怎么使用?
  • Kubernetes的容器有两种生命周期钩子(Lifecycle Hooks):
**PostStart**
这个钩子会在容器被创建后立即执行,但无法保证会在容器的起始点 ENTRYPOINT之前执行,如果执行时间太长,将会阻止Pod状态进入running,可用于数据初始化、容器启动回调等场景。如果需要保证在应用程序启动前就要执行完的任务,可以考虑放在初始化容器( Init Containers)中去实现。
**PreStop**
这个钩子会在容器被结束前执行,执行期间Pod状态为 Terminating,运行时间受终止宽限期( terminationGracePeriodSeconds)约束,超出宽限期Pod将被强制杀死,可用于容器回收前的数据清理、优雅停机等场景。
	上述的两个钩子(PostStart 和 PreStop)都有四种类型,分别为:exec、httpGet、tcpSocket 和 sleep。由于这四种钩子类型在 PostStart 和 PreStop 中的使用方法一致,下面以 PreStop 为例介绍这四种钩子类型的使用方法:
  • exec(执行shell指令,可以是指令或shell脚本, 退出状态码为 0则为成功)
# shell指令模式
lifecycle:preStop:exec:command: ["/bin/sh", "-c", "echo 'Container is stopping'"]# shell脚本模式
lifecycle:preStop:exec:command: ["/bin/sh", "-c", "/data/scripts/preStop.sh"]
  • httpGet(执行http get请求,响应状态码在[200,400)区间则为成功
lifecycle:preStop:httpGet:path: /shutdown  # 请求的uriport: 8080       # 端口host: api.yilingyi.com  # 主机域名,不加该字段将请求Pod本身scheme: HTTP     # http协议,默认值HTTP,支持HTTP、HTTPS
  • tcpSocket(执行tcp socket请求, TCP连接成功建立则为成功)
lifecycle:preStop:tcpSocket:port: 8080
  • sleep(将容器暂停5秒,Kubernetes 1.30的新特性 PodLifecycleSleepAction,待验证)
lifecycle:preStop:sleep:seconds: 5

请注意,如果 PostStart 或 PreStop 回调失败,容器将被杀死,所以回调处理的程序应尽量轻量级及把控好执行的时间。

3、微服务优雅停机实现

	本文将以k8s + SpringBoot + Nacos作为案例,介绍在实际业务场景中如何实现微服务的优雅停机,从而实现代码发布时的零宕机。
  • 首先,先看看pod的默认删除过程:
1. Kube-apiserver接收到pod的删除请求,在Etcd上更新pod的状态为Terminating;
2. Kubelet 清理节点上容器相关的资源,如存储、网络;
3. Kubelet向容器发送SIGTERM,如果容器内进程没有任何配置,则容器立即退出。
4. 如果容器在默认的 30 秒内没有退出,Kubelet 将发送 SIGKILL 并强制其退出。
	可以看出,在没有配置优雅停机之前,pod的删除相当暴力,所以为了更加优雅,我们加入了preStop hook,和将终止宽限期延长,具体实现如下:
1.  preStop hook做了两件事情:1)nacos反注册(也称 实例注销),确保在实例关闭期间不会再有新的请求被路由到该实例。2)  sleep 35s,nacos客户端的实例缓存为30s,30s后会重新拉取实例信息,超时为10s,一般不用10s这么长,所以我们设置为35s。
2.  springboot开启优雅停机后,最大等待时间为30s。
3.  terminationGracePeriodSeconds默认为30s,远小于preStop和springboot的时间之和,所以我们需要将其调大,我这里设置的是60s。
4.  其实在terminationGracePeriodSeconds耗尽后,k8s还给了一个2s的额外宽限期,最后才执行SIGKILL。

image

4、操作步骤

	在SpringBoot > 2.3.0的版本后支持应用程序优雅停机,需要在java微服务的配置中设置如下两个属性,这一步很重要!!!
server:# 默认值immediate:即立即关闭,graceful:即优雅停机shutdown: graceful
spring:lifecycle:# 优雅停机最大等待时间,默认30stimeout-per-shutdown-phase: 30s
  • 在微服务的yaml文件加上优雅停机的配置:通过env定义POD_IP获取当前Pod的ip,传递给preStop进行nacos反注册。
apiVersion: v1
kind: Pod
metadata:name: sre-yilingyi
spec:containers:- name: sre-yilingyiimage: 'sre/yilingyi:1.0.0'env:- name: POD_IPvalueFrom:fieldRef:apiVersion: v1fieldPath: status.podIPlifecycle:preStop:exec:command:- /bin/sh- '-c'- >curl -s --connect-timeout 10 -m 20 -X POST "http://nacos.yilingyi.com:8848/nacos/v1/ns/instance?port=8080&healthy=true&ip=${POD_IP}&weight=1&enabled=false&serviceName=sre-yilingyi&encoding=GBK&namespaceId=production" && sleep 35terminationGracePeriodSeconds: 60

至此,完成微服务的优雅停机配置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/64232.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

阿里云函数计算 x NVIDIA 加速企业 AI 应用落地

阿里云函数计算与 NVIDIA TensorRT/TensorRT-LLM 的合作基于双方在提效降本方面的共同目标。阿里云函数计算作为无服务器架构,凭借其高灵活性、弹性扩展能力以及对 GPU 算力的支持,为 AI 任务如模型推理和图像生成提供了高效的计算平台。作者:付宇轩 前言 阿里云函数计算(F…

谷歌地图 | Navigation SDK 重磅发布!为你的 App 注入导航新体验

随着移动互联网的快速发展,导航功能已经成为众多 App 的标配,凭借 Google 地图的强大技术支持和本地化服务,您可以为全球用户提供无缝的导航体验,快速拓展海外市场。无论是欧美发达国家还是新兴市场,Navigation SDK都能助您一臂之力。9月17日,Google 地图正式发布 Naviga…

pom.xml中引入项目中的jar包(通过<scope>system</scope>依赖本地jar包)

<dependency><groupId>com.hbis.infmgr</groupId><artifactId>sign-utils</artifactId><version>0.0.1</version><!--此处忽略sonar警告,因报表组件是定制化的本地包,放到了项目目录内,所以需要通过system-scope引入--><…

《NET CLR via C#》---第十二章(泛型)

泛型(generic)是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用,即“算法重用”。 简单来说,开发人员先定义好算法,必然排序、搜索、交换、比较或者转换等。但是,定义算法的开发人员并不设定该算法要操作什么数据类型;该算法可广泛地应用于不同类型的对象…

Java对接企业微信审批回调

一、需求说明用Java程序对接企业微信的审批流程,获取审批数据数据,例如:报销费用金额二、操作步骤 2.1、分析需求根据需求分析其实也不知道该怎么去做对接,通过不断试错,发现不需要对接第三方应用,也就是不需要进入服务商后台页面,只需要在自建应用是做好配置即可。 具体…

Vuex 和 Vue-router 知识点

Vuexactions里面才能做异步操作(访问后端API ajax请求 访问数据库中的数据) mutations原子操作,同步操作Vue-routermode:history 路由配置该怎么配置就怎么配置 route: [...]配置:path 和 component懒加载:component:对应一个函数,import导入这个组件。前面说过用impor…