十一、容器的优雅退出
00 分钟
2024-6-27
2024-7-22
type
status
date
slug
summary
tags
category
icon
password
文章状态

什么是信号?

信号是 Linux 内核与进程以及进程间通信的一种方式
其应用于异步事件的处理,实质上是一种软中断
针对每个信号进程都有个默认的动作,不过进程可以通过定义信号处理程序来覆盖默认的动作,除了 SIGSTOPSIGKILL。此二者都不能被捕获或重写,前者用来将进程暂停在当前状态,而后者则是从内核层面立即杀掉进程
  • 暴力与优雅
有两个比较重要的进程 SIGTERMSIGKILL
SIGTERM 是优雅地关闭命令,
SIGKILL 则是暴力的关闭命令。
比如 Docker,容器会先收到 SIGTERM 信号,10s 后会收到 SIGKILL 信号。

Kill 参数

使用 kill -l 可以查看 Linux 系统中的所有信号,如下:
信号值
信号名
说明
备注
1
SIGHUP
启动被终止的程序,可让该进程重新读取自己的配置文件,类似重新启动
2
SIGINT
相当于用键盘输入 [ctrl]-c 中断一个程序的进行。
interrupt
9
SIGKILL
代表强制中断一个程序的进行。若该程序进行到一半,那么尚未完成的部分可能会有“半产品”产生,类似 vim 会有 .filename.swp 保留下来。
kill,此信号无法捕捉
15
SIGTERM
正常的方式来终止该程序。由于是正常的终止,所以后续的动作仍会完成。然而,若该程序已经发生问题——无法使用正常的方法终止时,此信号也是无用的。
terminate
19
SIGSTOP
相当于用键盘输入 [ctrl]-z暂停一个程序的进行。
stopped,此信号无法捕捉

当容器接收到信号…

只有容器中的 1 号进程能够收到信号。
只有容器中的 1 号进程能够收到信号
容器中的进程属于容器的 1 号进程
Docker 的 stopkill 命令都是用来向容器发送信号的。
docker stop 命令会首先发送 SIGTERM 信号,并等待应用优雅的结束(此时间用户可指定);
如果发现应用没有结束,docker 会再发送一个 SIGKILL 信号强行结束程序。docker kill 命令默认发送的是 SIGKILL 信号,用户可通过 -s 标签指定任何信号。
步骤一:准备捕捉信号后做出动作的代码
通常由 Dev 提供
步骤二:编写测试环境的 Dockerfile
直接启动步骤一中准备的 APP,即程序为 1 号进程
构建镜像,测试信号
容器中的进程不属于容器的 1 号进程
步骤一:创建启动程序的 app1.sh 脚本文件
通过脚本启动程序,即程序非 1 号进程
步骤二:编写测试环境的 Dockerfile
构建镜像,测试信号
在脚本中捕获信号
步骤一:创建可捕捉信号的 app2.sh 脚本文件
步骤二:编写测试环境的 Dockerfile
构建镜像,测试信号
使用 tini 作为容器启动入口
Docker 1.13 之后版本包含 Tini 在其中
Tini 是一个为容器设计的微小但有效的 init 系统。
Tini 是一个为容器设计的微小但有效的 init 系统。
其主要用于在一个容器中启动一个单一的子进程,并等待其退出,同时负责回收僵尸进程和进行信号转发:
  • 回收僵尸进程
    • Tini 能够有效地回收僵尸进程,避免它们占用系统资源。
  • 信号转发
    • Tini 能够将信号转发给子进程,确保子进程能够正确地处理这些信号。
在执行 docker run 命令时,通过指定 --init 参数,Docker 会自动将 Tini 程序(位于 /sbin/docker-init)注入到容器中,并将其设置为容器的初始化进程。这一操作会覆盖原有的 ENTRYPOINT 配置,使得容器内的主进程在 Tini 的管理下运行。Tini 作为 PID 1 的进程,负责启动并监控容器内的主进程,同时处理僵尸进程的回收和信号的转发。
 
上一篇
<K8S> vol. 01 - kubernetes 组件
下一篇
十、镜像缓存与多级构建