我读过这篇文章:https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/
设置一些上下文:文章是关于容器中僵尸的问题,它试图说服我们这是一个真正的问题.
一般来说,我的感情很复杂.为什么这有关系 ?毕竟,即使万一在变装主机操作系统中的僵尸能够释放/杀死这个僵尸.我们知道容器中的进程是从主机操作系统正常进程的角度来看的(并且通常在容器中的进程是具有一些命名空间和cgroup的正常进程).
此外,我们还可以找到信息,以避免我们应该使用的僵尸问题bash -c ....为什么?也许,更好的选择是使用--init?
有人可以尝试解释这些事吗?
Mat*_*att 12
有关init进程为您提供的简短但有用的解释,请查看tiniDocker在您指定时使用的内容--init
使用Tini有几个好处:
- 它可以保护您免受意外创建僵尸进程的软件的影响,这些软件可能(随着时间推移!)使您的整个系统陷入困境(并使其无法使用).
- 它确保默认信号处理程序适用于您在Docker镜像中运行的软件.例如,使用Tini,即使您没有为它显式安装信号处理程序,SIGTERM也会正确终止您的进程.
这两个问题都会影响容器.容器中的进程仍然是主机上的进程,因此它占用主机上的PID.无论你在容器中运行什么是PID 1,这意味着它必须安装一个信号处理程序来获取该信号.
Bash恰好包含了一个进程收割器,因此运行命令bash -c可以防止僵尸.除非你是Bash,否则Bash默认不会将信号处理为PID 1 trap.
要理解的第一件事是一个init过程不会神奇地删除僵尸.A(普通)init被设计为当无法等待它们的父进程退出并且僵尸徘徊时收获僵尸.然后,init进程成为僵尸父进程,可以清除它们.
接下来是Docker容器是它们自己的PID命名空间中的一组进程.当容器停止时,该cgroup被清理.移除容器中的任何僵尸stop.他们没有到达主人init.
第三是Docker容器的使用方式.大多数运行一个主要过程,没有别的.如果产生了另一个进程,它通常是该主进程的子进程.所以在父母退出之前,僵尸将存在.然后看第2点.
在容器中运行Node.js,Go或Java app服务器往往不会严重依赖于分叉或产生进程.
运行类似于Jenkins工作程序的东西,会产生大量涉及shell的临时作业,这会导致更糟糕的情况.
init进程可以提供的另一个角色是安装信号处理程序,以便从主机发送的信号可以传递到容器进程.PID 1有点特殊,因为它需要进程监听接收信号.
如果你可以在PID 1进程中安装一个SIGINT和SIGTERM信号处理程序,那么init进程在这里不会增加太多.
应在init进程下运行多个进程.当Docker启动时,init管理它们应该如何启动.容器实际上为其所代表的服务"运行"所需的内容.当容器停止时,应该如何将其传递到每个进程.您可能需要更传统的init系统,s6通过s6-overlay为多进程管理提供了许多有用的容器功能.
特别是当过程是儿童或以外的孩子时.CI工作者(如Jenkins)示例是第一个想到Java生成命令或生成其他命令的shell的例子.
sleep就是一个简单的例子.A docker run busybox sleep 60不能用ctrl-c中断或停止,它会在默认的10秒docker stop超时后被杀死.docker run --init busybox sleep 60按预期工作.
tini是非常小的开销和广泛使用,所以为什么不使用--init大部分时间?
有关详细信息,请参阅此github评论,该评论回答"为什么?" 来自蒂尼的创造者的问题.
| 归档时间: |
|
| 查看次数: |
2686 次 |
| 最近记录: |