关闭k8s的pod时减小对服务的影响
在应用程序的整个生命周期中,正在运行的 pod 会由于多种原因而终止。在某些情况下,Kubernetes 会因用户输入(例如更新或删除 Deployment 时)而终止 pod。在其他情况下,Kubernetes 需要释放给定节点上的资源时会终止 pod。无论哪种情况,Kubernetes 都允许在 pod 中运行的容器在可配置的时间内正常关闭。
请查看下面的图表,以便更好地了解删除 pod 时发生的情况。

以下是 Pod 关闭的 2 个场景。
优雅关机
在这种情况下,pod 中的容器会在宽限期内正常关闭。容器的“正常关闭”状态表示执行可选的 pre-stop hook 和 Pod 响应 SIGTERM 信号。一旦容器成功退出,Kubelet 就会从 API Server 中删除 pod。
强制关机
在这种情况下,容器无法在宽限期内关闭。关闭失败可能是由于多种原因,包括
- 应用程序忽略 SIGTERM 信号,
- pre-stop hook 花费的时间超过宽限期,
- 应用程序清理资源花费的时间超过宽限期
- 以上的组合
当应用程序在宽限期内无法关闭时,Kubelet 会发送一个 SIGKILL 信号来强制关闭 pod 中运行的进程。根据应用程序,这可能会导致数据丢失和面向用户的错误。
在本文中,我们将重点分析优雅关闭部分。
识别问题
在 Kubernetes 中,每次部署都意味着在删除旧 pod 的同时创建新版本的 pod。
如果在此过程中没有正常关闭,可能会出现两个问题:
1.当前正在处理请求的 pod 被移除,如果请求不是幂等的,则会导致状态不一致。
2.Kubernetes 将流量路由到已经被删除的 Pod,导致处理请求失败,用户体验差。
分析问题
在删除 Kubernetes pod 的过程中,有两条平行的时间线,如下图所示。一是改变网络规则的时间线。另一个是 pod 的删除。

当运维人员或部署管道执行kubectl delete pod 命令时,两个过程开始。
网络规则生效
1.kube-apiserver 接收到 pod 删除请求,将 pod 在 Etcd 中的状态更新为 Terminating;
2.Endpoint Controller 从 Endpoint 对象中删除 pod 的 IP;
3.kuber-proxy 根据 Endpoint 对象的变化更新 iptables 的规则,不再将流量路由到被删除的 Pod。
删除 pod
1.kube-apiserver 接收到 Pod 删除请求,将 Pod 的再 Etcd 中的状态更新为 Terminating
2.Kubelet 在节点清理容器相关资源,如存储、网络
3.Kubelet 向容器发送 SIGTERM;如果容器内的进程没有配置,容器将立即退出。
4.如果容器在默认的 30 秒内没有退出,Kubelet 将发送 SIGKILL 并强制它退出。
通过删除 pod 的过程,我们可以看到如果容器内的进程没有配置,容器会立即退出,导致问题 1。
由于更新网络规则和删除 Pod 是同时进行的,因此不能保证在删除 Pod 之前更新网络规则。这就是可能导致问题 2 的原因。
解决方案
以下配置可以解决这些问题:
1.为容器内的进程设置正常关闭。
2.添加 preStopHook。
3.修改终止 GracePeriodSeconds。
下图显示了设置后的时间线

对于问题 1:为容器内的进程设置正常关闭
以 SpringBoot 为例,启用优雅关闭可以 Spring Boot 配置文件中添加下面设置:
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
通过使用上述配置,Spring Boot 保证在收到 SIGTERM 后不再接受新请求,并在超时内完成所有正在进行的请求的处理。即使无法及时完成,也会记录相关信息,然后强制退出。
对于 timeout 的值,应参考处理请求的最大允许持续时间。根据我们的经验,除特殊情况外,所有请求通常在 30 秒内完成处理。对于未在定义的超时时间内完成的,我们将在日志监控中捕获超时并发送警报,然后解决超时的根本原因并采取相应的措施。
这就是可以解决问题 1 的方法。其他语言和框架应该有类似的配置。
对于问题 2:添加 preStopHook
要处理问题 2,我们必须在不再将新流量路由到该 pod 后开始删除该 pod。因此,应该将 preStopHook 添加到 Kubernetes yaml 文件中,让 Kubelet 在收到删除 pod 事件时“sleep 一下”,并在开始删除 pod 之前留出足够的时间来更新网络规则。
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"] # set prestop hook
上述配置将导致 Kubelet 等待设定的时间。
修改终止 GracePeriodSeconds
参考之前删除 Pod 的分析,Kubernetes 为容器删除留下了 30 秒的最大时间尺度。如果 Spring 的优雅关闭超时时间和 Kubernetes 的 preStopHooks 之和超过 30 秒,可能会导致 Kubernetes 在 Spring Boot 处理完请求之前强行删除容器。因此,如果过程超过 30 秒,则应将 timerminationGracePeriodSeconds 调整为超出 Spring 加 preStopHook 的优雅关闭超时。
terminationGracePeriodSeconds: 45
最后,完整的 Kubernetes yaml 文件如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: gracefulshutdown-app
spec:
replicas: 3
selector:
matchLabels:
app: gracefulshutdown-app
template:
metadata:
labels:
app: gracefulshutdown-app
spec:
containers:
- name: graceful-shutdown-test
image: gracefulshutdown-app:latest
ports:
- containerPort: 8080
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"] #set prestop hook
terminationGracePeriodSeconds: 45 # terminationGracePeriodSeconds
1.在Spring Boot中设置正常关闭可确保在容器终止之前完成处理正在进行的请求。
2.设置 preStopHook 确认删除 pod 和更新网络规则之间的顺序关系。3. 最后,为了给进程留出充裕的时间来处理所有请求,设置 terminationGracePeriodSeconds。
通过这三个步骤,我们可以充分解决这两个问题。本文描述了一种解决方案,用于确保假设服务将正确处理零停机部署所需的所有请求。因此,构建此功能将丰富用户体验并减少将缺陷引入服务的影响。
最后,推荐一个部署应用的平台: https://github.com/512team/dhorse
演示地址:http://dhorse-demo2.512.team
关闭k8s的pod时减小对服务的影响的更多相关文章
- k8s删除pod时,docker服务出现挂载点泄漏问题的解决
k8s更新版本后,老的POD一直出现Terminating,多久都不能删除. 然后,进入具体的节点机器之后,查看日志输出如下类似: ERROR: driver "overlay" ...
- K8s QoS Pod资源服务质量控制
Kubernetes 中如果一个 Node 节点上的 Pod 占用资源过多并且不断飙升导致 Node 节点资源不足,可能会导致为了保证节点可用,将容器被杀掉.在遇见这种情况时候,我们希望先杀掉那些不太 ...
- 使用kuboard界面管理k8s集群时使用ConfigMap挂载挂载到pod容器中,映射成一个文件夹
将 ConfigMap 作为一个数据卷(在挂载时不指定数据卷内子路径,需要指定ConfigMap的子路径)挂载到容器,此时 ConfigMap 将映射成一个文件夹,每一个 KEY 是文件夹下的文件名, ...
- k8s的Pod状态和生命周期管理
Pod状态和生命周期管理 一.什么是Pod? 二.Pod中如何管理多个容器? 三.使用Pod 四.Pod的持久性和终止 五.Pause容器 六.init容器 七.Pod的生命周期 (1)Pod p ...
- 延申三大问题中的第三个问题处理---发布更新时先把服务从注册中心给down下来,等待一段时间后再能更新模块
一开始采取的思路大致如下: 在preStop中使用/bin/sh命令,先down 然后sleep一段时间, 这种思路的执行情况如下: 假若升级容器使用的镜像版本的话,先执行preStop中的命令,sl ...
- k8s 中 Pod 的控制器
k8s 中 Pod 的控制器 前言 Replication Controller ReplicaSet Deployment 更新 Deployment 回滚 deployment StatefulS ...
- k8s管理pod资源对象(上)
一.容器于pod资源对象 现代的容器技术被设计用来运行单个进程时,该进程在容器中pid名称空间中的进程号为1,可直接接收并处理信号,于是,在此进程终止时,容器即终止退出.若要在一个容器中运行多个进程, ...
- k8s家族Pod辅助小能手Init容器认知答疑?
k8s家族Pod辅助小能手Init容器认知答疑? k8s集群Init 容器是一种特殊容器,职责是在Pod的生命周期中作为应用容器的前置启动容器. 在很多应用场景中,在 Pod 内的应用容器正式启动之前 ...
- K8S中如何跨namespace 访问服务?为什么ping不通ClusterIP?
1.K8S中如何跨namespace 访问服务? 2.在Pod中为什么ping不通ClusterIP? 简述: Rancher2.0中的一个用户,在K8S环境中,创建两个namespace,对应用进行 ...
- K8s的POD连接数据库时报错
[root@cccc xxxx]# ./showlog.sh dr iff-dr-1128668949-lb90g 2017-09-29 03:21:57,575 INFO [org.wildfly. ...
随机推荐
- docker部署gitlab CI/CD (二)终篇:部署gitlab runner和添加gitlab-ci.yml文件 终极踩坑版
关于gitlab部署的教程还好,有的看,但到了cicd环节,简直痛苦面具,教程虽多,但断断续续,先不说大部分都是只截取片段,让人云里雾里,不会的看不懂,懂的不需要看,根据步骤跑不起来不说,改了一堆,完 ...
- 代码随想录算法训练营Day36 贪心算法
代码随想录算法训练营 代码随想录算法训练营Day36 贪心算法| 435. 无重叠区间 763.划分字母区间 56. 合并区间 435. 无重叠区间 题目链接:435. 无重叠区间 给定一个区间的集合 ...
- C++面试八股文:static和const的关键字有哪些用法?
某日二师兄参加XXX科技公司的C++工程师开发岗位第7面: 面试官:C++中,static和const的关键字有哪些用法? 二师兄:satic关键字主要用在以下三个方面:1.用在全局作用域,修饰的变量 ...
- 让ChatGPT来写今年的高考作文,能得几分?
使用最新的ChatGPT4模型,做2023年全国甲卷的高考作文. 作文考试题目如下 人们因技术发展得以更好地掌控时间,但也有人因此成了时间的仆人.这句话引发了你怎样的联想与思考?请写一篇文章. 要求: ...
- 混沌演练状态下,如何降低应用的 MTTR(平均恢复时间)
在企业业务领域,锦礼是针对福利.营销.激励等员工采购场景的一站式解决方案,包含面向员工.会员等弹性激励SAAS平台.由于其直接面向公司全体员工,其服务的高可用尤其重要,本文将介绍锦礼商城大促前夕,通过 ...
- Linux系统基础知识与自学方法
Linux系统基础知识与自学方法 大部分非计算机相关的朋友也经常使用电脑,所以我们频繁接触的是Windows系统.关于这个系统的评价不一,一部分人觉得简洁快捷,一部分人觉得问题(病毒.弹窗)多多,总之 ...
- JUC同步锁原理源码解析四----Semaphore
JUC同步锁原理源码解析四----Semaphore Semaphore 1.Semaphore的来源 A counting semaphore. Conceptually, a semaphore ...
- 前端基于 radio 增强单选框组件
前端基于radio增强单选框组件, 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=12977 效果图如下: # ## ...
- 简约版八股文(day2)
Redis(内存中->非关系型数据库) redis是什么,为什么要用redis redis是基于键值对的NoSQL数据库,经常用来做缓存用户直接读取数据库中的数据效率是相对比较慢的,如果把数据读 ...
- 了解web网络基础
TCP/IP 协议:一种规则,规定不同计算机操作系统,硬件之间怎么通信的一种规则 像这样把互联网相关联的协议集合起来总称为TCP/IP协议. TCP/IP分层管理 按照组层次分为以下四层: 应用层:决 ...