SIGINT SIGTERM SIGKILL区别
三者都是结束/终止进程运行。
1.SIGINT SIGTERM区别
前者与字符ctrl+c关联,后者没有任何控制字符关联。
前者只能结束前台进程,后者则不是。
2.SIGTERM SIGKILL的区别
前者可以被阻塞、处理和忽略,但是后者不可以。KILL命令的默认不带参数发送的信号就是SIGTERM.让程序有好的退出。因为它可以被阻塞,所以有的进程不能被结束时,用kill发送后者信号,即可。即:kill-9 进程号。
docker stop与docker kill
docker stop
当我们用docker stop命令来停掉容器的时候,docker默认会允许容器中的应用程序有10秒的时间用以终止运行。
在docker stop命令执行的时候,会先向容器中PID为1的进程(main process
)发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认的10秒,会继续发送SIGKILL的系统信号强行kill掉进程。在容器中的应用程序,可以选择忽略和不处理SIGTERM信号,不过一旦达到超时时间,程序就会被系统强行kill掉,因为SIGKILL信号是直接发往系统内核的,应用程序没有机会去处理它。
docker kill
默认情况下,docker kill命令不会给容器中的应用程序有任何gracefully shutdown的机会。它会直接发出SIGKILL的系统信号,以强行终止容器中程序的运行。
与docker stop命令不一样的地方在于,docker kill没有任何的超时时间设置,它会直接发送SIGKILL信号,以及用户通过signal参数指定的其他信号。
docker stop命令,更类似于Linux系统中的kill命令,二者都是发送系统信号SIGTERM。而docker kill命令,更像是Linux系统中的kill -9或者是kill -SIGKILL命令,用来发送SIGKILL信号,强行终止进程。
关于pid为1的进程
process ID为1的进程,通常是UNIX init进程, 在操作系统中有重要的作用:每当一个进程退出了,如果它还有子进程存在,则该子进程变成了孤儿进程,init进程过来接管。Unix被设计为这样一种方式,父进程必须明确地“等待”子进程终止,以便收集它的退出状态。
子进程在结束后,内核仍然会为其维护一个基本的结构,保存其pid, 退出原因和状态等信息,父进程通过waitpid系统调用,可以获得这些信息。如果父进程没有调用waitpid,这些状态信息会一直保留,变成所谓僵尸进程。如果子进程后于父进程结束,一般来说, init进程会负责这些孤儿进程。
根据一般一个容器只运行一个进程的原则,对于一个web服务,它在容器中运行时的pid是1,假设它调用了bash的cgi脚本,而这个脚本又调用了grep,一段时间后,cgi脚本因为某种原因超时,web服务开始尝试杀死它,但是grep却并未受到影响,因此变成了孤儿进程。这时,pid=1的web服务应该能接管,但是绝大多数的web服务并没有init那样的能力,所以grep就变成了僵尸进程。
kubernetes的pod关闭机制
pod代表着一个集群中节点上运行的进程,让这些进程不再被需要,优雅的退出是很重要的(与粗暴的用一个KILL信号去结束,让应用没有机会进行清理操作)。用户应该能请求删除,并且在室进程终止的情况下能知道,而且也能保证删除最终完成。当一个用户请求删除pod,系统记录想要的优雅退出时间段,在这之前Pod不允许被强制的杀死,TERM信号会发送给容器主要的进程。一旦优雅退出的期限过了,KILL信号会送到这些进程,pod会从API服务器其中被删除。如果在等待进程结束的时候,Kubelet或者容器管理器重启了,结束的过程会带着完整的优雅退出时间段进行重试。
一个示例流程:
1.用户发送一个命令来删除Pod,默认的优雅退出时间是30秒
2.API服务器中的Pod更新时间,超过该时间Pod被认为死亡
3.在客户端命令的的里面,Pod显示为"Terminating(退出中)"的状态
-
4.(与第3同时)当Kubelet看到Pod标记为退出中的时候,因为第2步中时间已经设置了,它开始pod关闭的流程
4.1如果该Pod定义了一个停止前的钩子,其会在pod内部被调用。如果钩子在优雅退出时间段超时仍然在运行,第二步会意一个很小的优雅时间断被调用
4.2进程被发送TERM的信号
5.(与第三步同时进行)Pod从service的列表中被删除,不在被认为是运行着的pod的一部分。缓慢关闭的pod可以继续对外服务,当负载均衡器将他们轮流移除。
6.当优雅退出时间超时了,任何pod中正在运行的进程会被发送SIGKILL信号被杀死。
7.Kubelet会完成pod的删除,将优雅退出的时间设置为0(表示立即删除)。pod从API中删除,不在对客户端可见。
默认情况下,所有的删除操作的优雅退出时间都在30秒以内。kubectl delete命令支持--grace-period=的选项,以运行用户来修改默认值。0表示删除立即执行,并且立即从API中删除pod这样一个新的pod会在同时被创建。在节点上,被设置了立即结束的的pod,仍然会给一个很短的优雅退出时间段,才会开始被强制杀死。
nginx与SIGTERM
有两种方式可以向正在运行的Nginx进程的发送信号以完全管理操作:使用Nginx进程的 -s 选项或者直接使用系统命令kill发送信号给master进程。使用 -s 选项时,nginx会自动查找运行中的master进程ID(master进程负责接收并处理信号,同时根据不同的信号,对所有工作进程完成不同的管理操作).
SIGINT和SIGTERM作用一样,用于强制 Nginx进程退出;master进程接到强制退出信号时,会向所有工作进程发送强制退出信号,如果工作进程未能及时退出,master使用计时器重复发送强制信号,计时器触发时会发送SIGALRM信号;SIGIO信号被Nginx显式忽略;SIGCHLD信号告诉 master进程有工作进程退出,需要完成资源回收或者重启工作进程的工作。
Nginx进程退出分为两种
master进程接到SIGQUIT信号时
将此信号转发给工作进程。工作进程随后关闭监听端口以便不再接收新的连接请求,并闭空闲连接,等待活跃连接全部正常结速后,调用 ngx_worker_process_exit 退出。而 master 进程在所有工作进程都退出后,调用 ngx_master_process_exit 函数退出;master进程接收到SIGTERM或者SIGINT信号时
将信号转发给工作进程。工 作进程直接调用 ngx_worker_process_exit 函数退出。master进程在所有工作进程都退出后,调用ngx_master_process_exit 函数退出。另外,如果工作进程未能正常退出,master进程会等待1秒后,发送SIGKILL信号强制终止工作进程。
nginx的优雅退出
-s signal Send signal to the master process. The argument signal can be
one of: stop, quit, reopen, reload.
The following table shows the corresponding system signals.
stop SIGTERM
quit SIGQUIT
reopen SIGUSR1
reload SIGHUP
其中
stop — 快速关闭
quit — 优雅退出,执行完当前的请求后退出
reload — 重新加载配置文件
reopen — 重新打开日志文件
使用kubernetes Lifecycle Hooks优雅退出nginx
kind: Deployment
metadata:
name: nginx-demo
namespace: scm
labels:
app: nginx-demo
spec:
replicas: 1
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- name: nginx-demo
image: library/nginx-demo
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
# nginx -s quit gracefully terminate while SIGTERM triggers a quick exit
command: ["/usr/local/openresty/nginx/sbin/nginx","-s","quit"]
env:
- name: PROFILE
value: "test"
ports:
- name: http
containerPort: 8080
题外
如何优雅地关闭java应用
command: ["/bin/bash", "-c", "PID=`pidof java` && kill -SIGTERM $PID && while ps -p $PID > /dev/null; do sleep 1; done;"]
doc
uinx 信号 SIGINT SIGTERM SIGKILL区别
优雅的终止docker容器
Termination of Pods
Issues with running as PID 1 in a Docker container.
Docker and the PID 1 zombie reaping problem
Docker 和 PID 1 僵尸进程问题
Docker系统中僵尸进程问题
kubernetes-chinese-docs-pods
Nginx 源代码笔记 - 运维命令
Does nginx have a soft quit?
Container Lifecycle Hooks
Graceful shutdown of pods with Kubernetes
Gracefully stopping a Java process in a pod in Kubernetes?
How can I ensure graceful scaling in kubernetes?
Do Kubernetes pods still receive requests after receiving SIGTERM?
Deleting pods and other resources with graceful shutdown