今天遇到一个问题,是我们的jenkins-node 突然出现好多僵尸进程
ps -ef |egrep defunct
sh [defunct]
基本都是这种进程
通过前述的 ps 命令,我们发现这些 zombies 的父进程基本都是 jenkins-agent 进程
通过网上搜索发现是我们启动的父进程是1 的进程(我这里是jenkins-agent 进程)不具备init 系统的功能,也就不会将操作系统的信号转发到子进程上,也不会回收孤儿进程,所以会产生大量的僵尸进程
这和我启动jenkins-node的方式有关我构建的Dockerfile的启动方式是直接CMD

这样启动的容器必然是jenkins-agent 的进程为1 ,不具备init 系统具备的功能,所以会产生大量的僵尸进程,又无法回收
这里介绍一下init 系统应该具备的功能
init 系统有以下几个特点:
- 它是系统的第一个进程,负责产生其他所有用户进程。
- init 以守护进程方式存在,是所有其他进程的祖先。
- 它主要负责:
- 启动守护进程
- 回收孤儿进程
- 将操作系统信号转发给子进程
所以解决方案是启动一个具备init进程的进程来启动相应的容器,按照网上的解决最终选择tini


init 系统有很多种,这里推荐使用 tini,它是专用于容器的轻量级 init 系统
https://github.com/krallin/tini
如果你想直接通过 docker 命令来运行容器,可以直接通过参数 --init 来使用 tini,不需要在镜像中安装 tini。如果是 Kubernetes 就不行了,还得老老实实安装 tini
所以最终的解决方案是
ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/jenkins.sh"]


参考文档
https://github.com/jenkinsci/docker/issues/54
https://github.com/jenkinsci/docker-inbound-agent/issues/51
https://zhuanlan.zhihu.com/p/145512162
