优雅退出应用

Wed Aug 10, 2022

200 Words|Read in about 1 Min
Tags: kubernetes   Devops  

  分布式系统中,应用服务容错是关键。kubernetes会做系统中监控各个性能指标(比如节点cpu、内存、亲和性策略等),会使pod在非预期计划的启动与停止。这篇文章讲告诉大家看看如何帮助Kubernetes更有效地完成工作并减少应用程序的停机时间和影响。

  在容器之前的应用服务(比如squid server)都是部署在虚拟机或者裸金属服务器上,如果应用程序因为某种原因崩溃,这会导致人工接入,重新拉起服务。
这种失败并重启的服务恢复时长变的不一定可控,也难以让人接受。

  所以,当应用程序崩溃时,使用进程级监控来重新启动应用程序变得很普遍。如果应用程序崩溃,监控进程可以捕获退出代码并立即重新启动应用程序。随着k8s的出现,进程级别的监控已经不需要。

因为k8s自己会处理重启服务。因为k8s使用事件监测来监控计算节点和pod服务的健康状态。

  这就意味着大家不再像传统运维那样在服务器上开了一个service A,然后还要启动一个Monitor Service B这样的程序。或者是supervisor这样的组件来拉起服务,因为节点出现故障的时候可能你的监控进程本身也不可靠。 当服务资源不可用的时候,k8s会自动在另外可用的计算节点拉起服务。

  k8s不仅仅可以监控服务进程是否存活或者崩溃,还可以创建服务进程、复制服务进程、服务进程运行副本数量、滚动更新、多个版本同时运行在多个机器等等功能。这意味着K8s可能终止、起停健康正常运行容器的次数比较多。比如在k8s的deployment对象进行滚动更新时,会先创建新的pod,然后再缓慢终止一个旧的pod。假如你要剔除一个运行的计算节点,k8s会逐步剔除整个节点的所有pod。还有比如节点的资源不足的时候,k8s会终止掉一些pod以释放资源等等。

在频繁启停pod的过程中,最重要的是应用程序要优雅地处理终止,以便对最终用户的影响最小并尽快的缩短恢复时间。

  一般在实践中,意味着应用程序在关闭时候需要处理SIGTERM信号。这意味着需要保存所有需要保存的数据、关闭网络连接、完成其他剩余的关闭动作等。

当k8s确定要终止这个pod的时候,有一系列的事件产生:

1.pod状态

设置为”Terminating”状态,将pod从所有服务终端列表中移除。
这个状态pod会停止获取新流量,在pod运行的容器不会受到影响

2.PreStop Hook执行状态

发送到pod容器的特殊命令或者http请求

3.SIGTERM信号发送到pod状态

此时,k8s发送SIGTERM信号给pod中的容器,业务代码应该监听该信号并作出一系列关闭动作。
比如关闭长链接或者websocket流、保存当前状态数据获取其他等等事件。

4.k8s在等待宽限期等待pod终止完毕

此时,k8s会在一个默认的30秒内等待pod终止,这个和2、3点同时发生。不会等待2步骤完成。
如果应用程序在30秒内完成关闭,k8s会立即进入下一步,而不会等30秒后才进入下个流程。
如果应用程序在30秒后完成关闭,需要人工增加宽限期时长。

比如

  spec:
    containers:
    - name: squid-pod
      image:squid:latest
    terminationGracePeriodSeconds: 60  
~ $ kubectl explain pod.spec.terminationGracePeriodSeconds
KIND:     Pod
VERSION:  v1

FIELD:    terminationGracePeriodSeconds <integer>

DESCRIPTION:
     Optional duration in seconds the pod needs to terminate gracefully. May be
     decreased in delete request. Value must be non-negative integer. The value
     zero indicates stop immediately via the kill signal (no opportunity to shut
     down). If this value is nil, the default grace period will be used instead.
     The grace period is the duration in seconds after the processes running in
     the pod are sent a termination signal and the time when the processes are
     forcibly halted with a kill signal. Set this value longer than the expected
     cleanup time for your process. Defaults to 30 seconds.

5.SIGKILL 信号发生到pod并移除pod

如果容器在宽限期后仍在运行,则会向它们发送 SIGKILL 信号并强制删除。此时,所有k8s对象也都被清理干净了。

See Also

Wed Aug 10, 2022

200 Words|Read in about 1 Min
Tags: kubernetes   Devops