优雅停止(Graceful shutdown)
这个说法来自于操作系统,我们执行关机之后都得 OS 先完成一些清理操作,而与之相对的就是硬中止(Hard shutdown),比如拔电源。
到了分布式系统中,优雅停止就不仅仅是单机上进程自己的事了,往往还要与系统中的其它组件打交道。比如说我们起一个微服务,网关把一部分流量分给我们,这时:
按照惯例,SIGKILL 是硬终止的信号,而 SIGTERM 是通知进程优雅退出的信号,因此很多微服务框架会监听 SIGTERM 信号,收到之后去做反注册等清理操作,实现优雅退出。[4]
Pod
就像是豌豆荚一样,它由一个或者多个容器组成(例如Docker容器),它们共享容器存储、网络和容器运行配置项。Pod中的容器总是被同时调度,有共同的运行环境。你可以把单个Pod想象成是运行独立应用的“逻辑主机”——其中运行着一个或者多个紧密耦合的应用容器——在有容器之前,这些应用都是运行在几个相同的物理机或者虚拟机上。[1]
在 k8s 执行 Rolling-Update
的时,默认会向旧的 pod 发生一个 SIGTERM
信号,如果业务应用没有对 SIGTERM
信号做处理的话,有可能导致程序退出后也没有处理完请求,引起客户端访问异常。
注意
:SIGTERM
信号如果进程没有处理就会导致进程被强杀,如果处理了但是超过 terminationGracePeriodSeconds
配置的时间也一样会被强杀,所以这个时间可以根据具体的情况去设置。[2]
注
:绿色Pod
为当前已运行Pod , 紫色Pod
为新创建Pod
Deployment
部署文件,触发 Rolling-Update
操作,根据 k8s 调度算法选出一个 Node ,在这台 Node上创建一个 紫色Pod
滚动更新允许以下操作:
PreStop hook
,hook 可以执行一个 HTTP GET请求
或者 exec命令
,并且它们执行是阻塞的,可以利用这个特性来做优雅停止。spec:
contaienrs:
- name: my-container
lifecycle:
preStop:
httpGet:
path: "/stop"
port: 8080
scheme: "HTTP"
spec:
contaienrs:
- name: my-container
lifecycle:
preStop:
exec:
command: ["/bin/sh","-c","/pre-stop.sh"]
PreStop hook
会执行 PreStop hook
,PreStop hook
执行完成后会向 pod 发送 SIGTERM
信号。terminationGracePeriodSeconds
时间限制内,PreStop hook
还没有执行完,一样会直接发送 SIGTERM
信号,并且时间延长 2秒
,最后强制 Kill 。