咱们工作的环境在不断的变好,我们也会思考去提升程序运行的环境,让我们的服务更加容易部署,极简维护,现在很多公司都在向着 devpos 发展,殊不知已经被某些大企玩剩下了
不过没关系,路得一步一步的走,饭得一口一口的吃,这样我们才会走的稳,长的好
情况描述:
起初我们还是主机环境的时候,使用 ansible 来一键部署我们主机环境上的服务,对于我们的服务自然也是做无状态的
对于服务我们有做优雅关闭,简单来说,就是当程序收到 sigterm 等关闭信号的时候,咱们的服务不会一下子断掉,服务会将当前手里的事情迅速做完再关闭咱们的服务
例如咱们一般在 golang 里面会这样来实现:
代码语言:javascript复制stopChan := make(chan os.Signal)
// bind OS events to the signal channel
signal.Notify(stopChan, syscall.SIGTERM)
// 优雅关闭咱们的服务
defer func() {
log.Println("closing....")
// xxxx 做关闭的动作
// TODO ...
}()
// 阻塞等待关闭信号
select {
case <-stopChan:
}
相信对于熟悉 golang 的兄弟对于这个已经不再陌生了,这个会有啥问题呢?
当然,对于在主机环境里面我们过去都跑了很久了,优雅关闭的功能都是正常运行的,久而久之,就没有人关注他了
开始应用 k8s 来部署我们的服务
慢慢的我们过渡到了容器化的方式来部署我们的服务
一般使用容器化,我们回去编写 Dockerfile ,写我们的启动脚本,做成镜像,进而做成 helm 包,推到 helm 仓库中,在环境中我们就可以使用 helm 工具来高效的部署咱们的服务了,此处就过多赘述了,感兴趣的可以查看如下 2 篇历史文章:
- 如何将自己的镜像使用 helm 部署
- 原来服务端的退出姿势也可以这么优雅
实际情况上,服务在线上跑了一年多了,最近要做一个需求,涉及到服务被 kill 的时候,要到优雅关闭中做一些事情,例如清空某些过程数据
万万没想到,正是优雅关闭在 k8s 部署的时候出了问题,还记当刚才我们说到的在 k8s 中部署的时候,咱们会写启动脚本吗?,例如启动脚本是这样的:
start.sh
代码语言:javascript复制#!/bin/bash
./my_demo_svr
例如我们的 Dockerfile 是这样的(仅做示例):
代码语言:javascript复制FROM centos
ADD my_demo_svr /
ADD start.sh /
ENTRYPOINT ["sh", "start.sh"]
正是因为咱们在容器中是通过 shell 脚本来启动咱们的 my_demo_svr 服务,那么实际情况是这样来的
bash(xxxpid) --- shell(xxpid) --- my_demo_svr(xxxpid)
那就相当于 my_demo_svr 是 shell 的子进程,shell 收到 k8s 发送的 sigterm 信号的时候,是不会传递给子进程 my_demo_svr 的,因此 my_demo_svr 是不会进行优雅关闭的
看到这里,实际上我们处理的思路就是:
- 如何让 shell 收到 sigterm 信号的时候,可以传递给他的子进程
实际应用了两种方式
- 在脚本中,实际启动程序的时候 我们加上 exec 命令,exec 命令可以用于调用并执行命令,我们可以这样来修改
#!/bin/bash
exec ./my_demo_svr
简单的修改了这个脚本之后,咱们的 my_demo_svr 程序会替换 shell,并且不会出现子进程,此时 k8s 发送 sigterm 信号的时候,那么接收信号的直接就是 my_demo_svr 服务,此时的优雅关闭就可以正常触发了
- 使用 linux 中的 trap 命令
trap 命令,可以用来传递信号,我们正好就可以应用它来解决我们的实际问题
例如我们就可以这样来写
此处要注意,咱们的服务启动后面是有 & 的,让我们的 my_demo_svr 在后台运行
代码语言:javascript复制#!/bin/sh
./my_demo_svr &
pid="$!"
_kill() {
echo "start closing ..."
kill $pid
wait $pid
exit 0
}
trap _kill SIGTERM
wait
这个时候,当我们的 k8s 中的 pod 被 delete 或者被 rollout restart 的时候,会给咱们容器中的 shell 发送 sigterm 信号,脚本中由于我们使用 trap 命令来传递信号给到 my_demo_svr 程序中,进而触发 my_demo_svr 优雅关闭
至此,请大家引以为鉴,尽量减少踩坑吧,如果有相同经历的欢迎评论交流哦