4. 为什么要设计出pod
introduction
如果这个世界上没有pod是什么样的?
如果我们没有pod, 转而把容器当成最小部署单元会怎样?
现在假设你站在K8s诞生的时间点上, 你想要设计出一个"容器编排"系统, 现在在这种背景下, 如果你不用容器作为最小调度单元, 转而设计出pod作为最小调度单元, 那你最好有一个充分的理由, 否则你很容易会被当成闲着蛋疼没事找事.
回答一个问题, 我们怎么设计的容器? 容器想让你跑一个进程(而不是一组进程), 比如MySQL容器让你跑MySQL进程这样. 在我们的蓝图里, 一个容器就是一个进程, 那么, 负责管理编排容器的, 就对应着管理进程的操作系统, 这就是我们叫"容器编排工具"为操作系统的原因. 现在, 你终于对这句抽象晦涩的描述, 有了一个更深的理解.
更进一步的, 容器是想让你只跑一个进程, 但是我们实际上发现很多场景下我们都不止跑一个, 而是跑好几个进程组合在一起形成某种服务的, 这怎么办? 你想想这怎么办? 当然你可以选择通过 Affinity 来把这些容器布置在同一台宿主机上, 但这又不够原子了吧? 不如想一招把这几个容器塞到一个球里, 然后把这个球当成最小单元就行了吧? ok, pod诞生了.
pod = pause + n*continer
也就是说在任何pod里除了你自己定义出的容器, 还都会有一个pause容器, 如果我们想要理解K8s的网络模型, 一定要先理解pause容器
从pid的角度看pause
上学的时候就知道, 某个进程fork出一个子进程, 但如果父进程没有通过 wait()
等待子进程结束就直接退出, 这种情况下子进程就会直接变成僵尸进程, 继而成为1号进程的子进程. (科普: 子进程在运行完成以后, 它的进程条目表仍然得到保留, 直到父进程通过wait明确得知子进程已经结束, 并清理进程条目才算彻底结束, 明明已经死了却没人帮你从进程条目表里清除, 故得名"僵尸")
收养: 但是书上好像没有说1号进程会怎么处理这些僵尸进程? 这时候1号进程就应该负责调用
wait()
并等待僵尸进程终止, 但这件事并不是所有人都能做到的, 就好像nginx并不会管这些事, 因此pause会负责干这件事, 所有容器都共享pid-namespace, 而其中pause成为他们的1号进程, 负责收集其他容器的僵尸进程, 这样这个pod里就不会到处都是僵尸进程防止误杀: 于此同时我们要求pause进程必须屏蔽某些信号, 比如Ctrl+C之类的信号, 防止这个进程也被误杀, 从侧面印证nginx还是无法成为1号进程.
多说一句docker容器里的事, 你每次执行
docker kill
的时候其实就是在kill容器里的init进程这个init进程可以是
ENTRYPOINT
, 也可以是docker run ubuntu xxx
, 一旦容器里的init进程被杀了, 整个pid-namespace下的所有进程都将终止 (所以JDOS求求你不要杀掉那个sleep 9999d
)
Last updated
Was this helpful?