一、容器进程和宿主机进程的关系
容器在进程空间上和宿主机是隔离的,每创建一个容器,该容器都有一个独属的进程空间简称PID NameSpace。但是容器本质也是一个进程,自然是由其父进程创建的,这个可以使用ps aux命令验证。
| 容器视角中的进程状态:
容器中的1号进程和linux中的1号进程其实是一样的,是init进程,是所有进程的父进程,其它的进程都由init进程来创建。
| 宿主机视角中的进程状态
也就是说容器中的进程其实也只是宿主机上的普普通通一个小进程,可以随时停掉它,在宿主机上。
那么就有问题了,不是PID隔离的吗,为什么在宿主机上可以看到容器中运行的进程呢?其实宿主机上的pidNamespace相当于是所有容器的parent-pid-namespace。
容器中的init进程其实是宿主机上shim-runc 进程的一个子进程。
二、那能不能在容器中kill 掉容器中的进程呢?
kill本质上是向进程发送一个信号,可用作进程间通信,那么具体是如何处理这个信号,完全是由进程本身决定的,进程一般有三种处理方式:
- 忽略
- 执行缺省的handler
- 执行自定义的handler
其中对于sigkill和sigstop,不能注册自定义的hander。因此对于sigkill和sigstop两个信号进程只能使用默认的handler进行处理。
不过对于init进程也就是创建pidnamespace时创建的第一个进程,进程把只有默认handler的信号给忽略了。因此不能在容器中使用kill -9 杀掉init进程。
但是可以通过kill其它信号中止init进程,前提要注册自己的handler。因为对于只有默认handler的信号,init进程就把这个信号给忽略掉了。
总结:init进程,对于只有默认handler的信号会忽略,对于注册了handler的信号会响应,但是sigkill和sigstop不能自定义handler。
三、容器中的僵尸进程
僵尸进程的产生,一个进程都是要占用一些资源状态的,而占用的这些资源状态进程在终止前是需要父进程对其进行回收的,如果父进程没有回收,那么这个子进程就称为僵尸进程其状态为Z。如果父进程退出了,会由init进程接管。
因此容器中也会产生僵尸进程,而且容器中的进程数目是受限制的,因此对于容器中的僵尸进程要格外注意。