原文标题:Gracefully Shutting Down Pods in a Kubernetes Cluster

发布时间:Jan 26, 2019

原文链接:https://blog.gruntwork.io/zero-downtime-server-updates-for-your-kubernetes-cluster-902009df5b33

文章作者:yorinasub17

这是我们实现 Kubernetes 集群零停机时间更新的第二部分。在本系列的第一部分中,我们列举出了简单粗暴地使用kubectl drain 命令清除集群节点上的 Pod 的问题和挑战。在这篇文章中,我们将介绍解决这些问题和挑战的手段之一:优雅地关闭 Pod。

Pod驱逐的生命周期

默认情况下,kubectl drain命令驱逐节点上的 Pod 时会遵循 Pod 的生命周期,这意味着整个过程会遵守以下规则:

  • kubectl drain将向控制中心发出删除目标节点上的 Pod 的请求。随后,请求将通知目标节点上的 kubelet 开始关闭 Pod。

  • 节点上的kubelet 将会调用 Pod 里的 preStop 钩子。

  • preStop 钩子执行完成后,节点上的kubelet 会向Pod容器中运行的程序发送 TERM信号 (SIGTERM)。

  • 节点上的kubelet将最多等待指定的宽限期(在pod上指定,或从命令行传入;默认为30秒)然后关闭容器,然后强行终止进程(使用SIGKILL)。注意,这个宽限期包括执行 preStop钩子的时间。

译注:Kubelet 终止Pod前的等待宽限期有两种方式指定

  1. 在Pod定义里通过Pod模板的spec.terminationGracePeriodSeconds 设定

  2. kubectl delete pod {podName} --grace-period=60

基于此流程,我们可以利用应用程序 Pod 中的preStop钩子和信号处理来正常关闭应用程序,以便在最终终止应用程序之前对其进行“清理”。例如,假如有一个工作进程从队列中读取信息然后处理任务,我们可以让应用程序捕获 TERM 系统信号,以指示该应用程序应停止接受新任务,并在所有当前任务完成后停止运行。或者,如果运行的应用程序无法修改以捕获 TERM 信号(例如第三方应用程序),则可以使用preStop钩子来实现该服务提供的自定义API,来正常关闭应用。

在我们的示例中,Nginx 默认情况下不能处理 TERM 信号,因此,我们将改为依靠 Pod 的 preStop钩子实现正常停止Nginx。我们将修改资源定义,将生命周期钩子添加到容器的spec定义中,如下所示:

lifecycle:preStop:exec:command: [# Gracefully shutdown nginx"/usr/sbin/nginx", "-s", "quit"]

应用此配置后,在将 TERM 信号发送给容器中的Nginx进程之前,kebulet 调用 Pod 的生命周期钩子发出命令 / usr / sbin / nginx -s quit。请注意,由于该命令将会正常停止 Nginx 进程和 Pod,因此 TERM 信号实际上在这个例子中是一个空操作。

在定义文件添加了生命周期钩子后,整个 Deployment 资源的定义变成了下面这样

---
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deploymentlabels:app: nginx
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.15ports:- containerPort: 80lifecycle:preStop:exec:command: [# Gracefully shutdown nginx"/usr/sbin/nginx", "-s", "quit"]

停机后的后续流量

使用上面的preStop钩子正常关闭 Pod 可以确保 Nginx 在处理完现存流量有才会停止。但是,你可能会发现,Nginx 容器在关闭后仍会继续接收到流量,从而导致服务出现停机时间。

为了了解造成这个问题的原因,让我们来看一个示例图。假定该节点已接收到来自客户端的流量。应用程序会产生一个工作线程来处理请求。我们用在 Nginx Pod 示例图内的圆圈表示该工作线程。

正在处理请求的Nginx

假设在工作线程处理请求的同时,集群的运维人员决定对 Node1 进行维护。运维运行了kubectl drain node-1 后,节点上的kubelet 会执行 Pod 设置的preStop钩子,开始进入Nginx进程正常关闭的流程。

对节点进行维护,清出节点上的Pod时会先执行preStop钩子

由于 Nginx 仍要处理已存流量的请求,所以进入正常关闭流程后 Nginx 不会马上终止进程,但是会拒绝处理后续到达的流量,向新请求返回错误。

在这个时间点,假设一个新的服务请求到达了 Pod 上层的 Service,因为此时 Pod 仍然是上层 Service 的Endpoint,所以这个即将关闭的 Pod 仍然可能会接收到 Service 分发过来的请求。如果 Pod 真的接收到了分发过来的新请求 Nginx 就会拒绝处理并返回错误。

译注:推荐阅读学练结合快速掌握K8s Service控制器

Nginx处于关闭流程时会拒绝新来的请求

最终 Nginx 将完成对原始已存请求的处理,随后kubelet会删除 Pod,节点完成排空。

Nginx 处理完已存请求后终止进程

Pod停止运行,kubelet删除Pod

为什么会这样呢?如何避免在Pod执行关闭期间接受到来自客户端的请求呢?在本系列的下一部分中,我们会更详细地介绍 Pod 的生命周期,并给出如何在 preStop 钩子中引入延迟为 Pod 进行摘流,以减轻来自 Service 的后续流量的影响。

如何优雅地关闭Kubernetes集群中的Pod相关推荐

  1. 想提高运维效率,那就把MySQL数据库部署到Kubernetes 集群中

    摘要:Kubernetes 很多看起来比较"繁琐"的设计的主要目的,都是希望为开发者提供更多的"可扩展性",给使用者带来更多的"稳定性"和& ...

  2. 如何调试Kubernetes集群中的网络延迟问题

    本文深入研究和解决了 Kubernetes 平台上的服务零星延迟问题,就在不久前我也遇到了类似的问题,看似是玄学事件,刚开始归结于网络链路抖动,一段时间后依然存在,虽然影响都是 P99.99 以后的数 ...

  3. 调试Kubernetes集群中的网络停顿问题

    调试Kubernetes集群中的网络停顿问题 在过去几年,Kubernetes在GitHub已经成为标准的部署模式.目前在GitHub,我们在Kubernetes上运行着海量的面向内部团队以及面向C端 ...

  4. Kubernetes集群中部署Node节点

    Kubernetes集群中的Node节点部署 kubernetes的Node节点包含如下组件: flanneld docker kubelet kube-proxy 环境变量 需要的变量. $ # 替 ...

  5. 在Serverless Kubernetes集群中轻松运行Argo Workflow

    导读 Argo是一个基于kubernetes实现的一个Workflow(工作流)开源工具,基于kubernetes的调度能力实现了工作流的控制和任务的运行. 目前阿里云容器服务ACK集群中已经支持工作 ...

  6. 在 Kubernetes 集群中使用 MetalLB 作为 LoadBalancer(下)

    作者 | Addo Zhang 来源 | 云原生指北 在上一篇<在 Kubernetes 集群中使用 MetalLB 作为 LoadBalancer(上)>中,我们使用 MetalLB 的 ...

  7. 从外部访问Kubernetes集群中的应用

    https://zhaohuabing.com/2017/11/28/access-application-from-outside/ 前言 我们知道,kubernetes的Cluster Netwo ...

  8. 在 Kubernetes 集群中使用 MetalLB 作为 LoadBalancer(下)- BGP

    在上一篇<在 Kubernetes 集群中使用 MetalLB 作为 LoadBalancer(上)>中,我们使用 MetalLB 的 Layer2 模式作为 LoadBalancer 的 ...

  9. K8s——kubernetes集群中ceph集群使用【下】

    kubernetes集群中ceph集群使用 一:CephFS 创建和使用 CephFS 允许用户挂载一个兼容posix的共享目录到多个主机,该存储和NFS共享存储以及CIFS共享目录相似 1.file ...

最新文章

  1. 你需要掌握的有关.NET DateTime类型的知识点和坑位 都在这里
  2. 04.微博消息的语言检测
  3. [Git/Github] ubuntu 14.0 下github 配置
  4. 周昌印:忘记技术 从用户与市场考虑问题
  5. 表示我想你的代码java_如何编写可怕的Java代码?
  6. js (javascript) 中获取年月日信息
  7. windows 2008 R2 如何更新SID
  8. 浅谈计算机网络技术应用及发展,【网络技术论文】计算机网络技术的应用及发展(共2891字)...
  9. 15条SQLite3语句
  10. 《信号与系统学习笔记》—周期信号的博里叶级数表示(二)
  11. php pmp是什么,pmp 总时差 自由时差 说明 和计算
  12. 计算机网络维护服务承诺书,网络信息技术中心服务承诺书
  13. Druid监控页面配置与使用
  14. (程序员必备技能)基于Python的鼠标与键盘控制实战扩展与源码
  15. 佳能软件不用光盘安装升级包的方法
  16. 微型计算机只要性能指标,微型计算机的主要性能指标运算速度.ppt
  17. 风影ASP.NET基础教学 10 DetilsView
  18. 1278_FreeRTOS_借助prvAddCurrentTaskToDelayedList接口理解delayed task
  19. ICC II 3 从create_ndm开始design setup
  20. Python爬虫 百度地图搜索数据采集

热门文章

  1. windows服务器远程执行命令(PowerShell+WinRM)
  2. 基于Windows下python3.4.1IDLE常用快捷键小结
  3. php 长整型转字符串 (convert long to string)
  4. 第四章:更多的bash shell命令
  5. vnc报错 font catalog is not properly configured
  6. 喂。請罘葽缺蓆涐旳以后
  7. 将一个包含有2层数据分组的表输出到EXCEL表里,并分组统计
  8. Jmeter之线程组(默认)
  9. [Android学习笔记四] 自定义Android组件之组合方式创建密码框组件
  10. 中间件——构筑复杂分布式应用的关键技术(转)