5

k8s中shell脚本启动如何传递信号

 1 year ago
source link: https://qingwave.github.io/docker-shell-signal/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Feb 3, 2021 · cloud

k8s中shell脚本启动如何传递信号



在 k8s 或 docker 中,有时候我们需要通过 shell 来启动程序,但是默认 shell 不会传递信号(sigterm)给子进程,当在 pod 终止时应用无法优雅退出,直到最大时间时间后强制退出(kill -9)。

普通情况下,大多业务的启动命令如下

command: ["binary", "-flags", ...]

主进程做为 1 号进程会收到sigterm信号,优雅退出(需要程序捕获信号); 而通过脚本启动时,shell作为 1 号进程,不会显示传递信号给子进程,造成子进程无法优雅退出,直到最大退出时间后强制终止。

如何只需一个进程收到信号,可通过execexec会替换当前 shell 进程,即pid不变

#! /bin/bash
# do something
exec binay -flags ...

正常情况测试命令如下,使用 sleep 来模拟应用sh -c 'echo "start"; sleep 100'pstree展示如下,sleep进程会生成一个子进程

bash(28701)───sh(24588)───sleep(24589)

通过exec运行后,命令sh -c 'echo "start"; exec sleep 100'

bash(28701)───sleep(24664)

加入exec后,sleep进程替换了 shell 进程,没有生成子进程

此种方式可以收到信号,但只适用于一个子进程的情况

在 shell 中可以显示通过trap捕捉信号传递给子进程

#!/bin/bash
echo "start"
binary -flags... &
pid="$!"

_kill() {
  echo "receive sigterm"
  kill $pid #传递给子进程
  wait $pid
  exit 0
}

trap _kill SIGTERM #捕获信号
wait #等待子进程退出

此种方式需要改动启动脚本,显示传递信号给子进程

docker-init

docker-init即在 docker 启动时加入--init参数,docker-int 会作为一号进程,会向子进程传递信号并且会回收僵尸进程。

遗憾的是 k8s 并不支持--init参数,用户可在镜像中声明 init 进程,更多可参考container-init

RUN wget -O /usr/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.2/dumb-init_1.2.2_amd64
RUN chmod +x /usr/bin/dumb-init
ENTRYPOINT ["/usr/bin/dumb-init", "-v", "--"]

CMD ["nginx", "-g", "daemon off;"]

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK