当前位置: 首页 > news >正文

dumb-init vs tini vs wait - 小镇

dumb-init vs tini vs wait

你应该是想比较 dumb-init vs tini vs wait(shell 内置 wait),以及 PID 1 场景下子进程僵尸回收是否影响父进程

先给结论:

  • dumb-init / tini 都是容器里的 PID 1 init 进程,用于信号转发 + 僵尸进程回收。

  • wait 只是 shell 等待子进程退出的同步机制,不是 init,不负责 orphan reaping。

  • 子进程僵尸不被回收:

    • 不会直接阻塞父进程运行

    • 但是会消耗 PID 表项,长期可能导致 fork() 失败,最终影响父进程或整个容器。

  • 在 Kubernetes 中,推荐使用 tini(Docker 默认 init)或者 dumb-init


1. dumb-init vs tini vs wait 对比

特性dumb-inittiniwait
类型 小型 init 小型 init shell builtin
用途 容器 PID 1 容器 PID 1 等待子进程
是否可作为 PID 1
信号转发
SIGTERM 优雅退出 部分依赖 shell
僵尸进程回收
orphan 子进程接管
子进程退出状态传播
资源占用 极低 极低 无额外
代码复杂度 Python/C C shell
Docker 官方支持 ✅ Docker --init 默认
Kubernetes 常用 较多 较多 不推荐

2. 容器为什么需要 tini/dumb-init?

Linux 里面:

父进程|+-- child|+-- grand child

如果 child 死掉:

PID 1|+-- orphan grand child

Linux 会把 orphan 收养给 PID 1:

PID 1|+-- orphan

然后 PID 1 必须:

waitpid(-1, ...)

回收它。

否则:

PID 1|+-- zombie

出现:

ps auxroot  20  Z  worker <defunct>

3. dumb-init / tini 工作模型

例如:

container|PID 1tini|+-- nginx|+-- worker

启动:

tini|exec nginx

收到:

docker stop|vSIGTERM|vtini

tini:

转发 SIGTERM|vnginx

同时:

waitpid()
waitpid()
waitpid()

回收 zombie。


4. dumb-init vs tini 差异

tini

Docker 官方推荐:

docker run --init

实际上:

docker-init|tini

特点:

  • C 实现

  • 极小

  • 专注 init

  • Kubernetes 常见


dumb-init

结构:

dumb-init|exec app

额外能力:

session 模式

例如:

dumb-init -- python app.py

可以处理:

SIGTERM
SIGINT
SIGKILL

并转发给整个 process group。

适合:

  • Python

  • Java

  • Node.js

  • shell wrapper


5. wait 和 tini/dumb-init 最大区别

假设:

Dockerfile:

CMD ["bash","start.sh"]

start.sh:

#!/bin/bashpython worker.py &wait

进程:

PID 1 bash|+-- python worker

这里:

wait

只是:

bash等待python退出

它不会:

  • 接管 orphan

  • reaping zombie

  • 转发信号

例如:

python|+-- child

python crash:

child|orphan

最后:

PID 1 bash

成为收养者。

但是 bash 的 wait 不负责:

waitpid(-1)

所以 zombie 可能留下。


6. 僵尸子进程会影响父进程吗?

短期

通常:

parent|+-- zombie

父进程:

继续运行

例如:

PID 1 nginxPID 100 worker Z

nginx 还能工作。


长期

影响:

1. 消耗 PID

Linux 有 PID 上限:

/proc/sys/kernel/pid_max

大量 zombie:

PID table full

导致:

fork: Resource temporarily unavailable

例如:

Java:

Unable to create native thread

Python:

OSError: [Errno 11] Resource temporarily unavailable

2. 影响容器重启

Kubernetes:

Pod|PID 1|zombie x 10000

可能:

container still running

但是:

liveness probe fail

最终 kill。


7. PID 1 特殊性

Linux 对 PID 1 有特殊处理。

普通进程:

default SIGTERM handler

PID 1:

如果没有注册 handler
默认忽略很多信号

例如:

你的程序:

PID 1 python app.py

执行:

docker stop

发送:

SIGTERM

但是:

Python PID1:

没有处理

可能:

30秒后 SIGKILL

导致:

  • 无优雅退出

  • 数据丢失

tini:

docker stop|tini|SIGTERM|app

解决。


8. Kubernetes 推荐结构

推荐:

container|PID 1 tini|application|workers

例如:

Dockerfile:

FROM alpineRUN apk add tiniENTRYPOINT ["/sbin/tini","--"]CMD ["./server"]

或者:

Docker:

docker run --init image

9. dumb-init vs tini 选择

场景推荐
Docker 官方环境 tini
Kubernetes tini
Python/Node shell wrapper dumb-init
需要 signal process group dumb-init
最简单 init tini
distroless tini 静态二进制

总结

问题答案
dumb-init/tini 是什么? 容器 PID1 init
wait 能代替吗? 不能
僵尸影响父进程吗? 不会立即影响,但长期耗尽 PID
为什么 Kubernetes 需要? 处理 SIGTERM + zombie reaping
tini 和 dumb-init 谁好? 大多数情况 tini;复杂 shell 场景 dumb-init
父进程退出 zombie 会怎样? 被 PID1 接管并回收

对于 Kubernetes,实际最佳实践通常是:

PID 1|tini|your application

而不是:

PID 1|bash|application