docker进程管理(1号进程,僵尸进程详解)

前沿
大家都知道对linux系统来说1号进程为init进程,是由0号进程(内核进程)通过调用系统init函数创建的第一个用户进程1进程,主要做用户态进程的管理,垃圾回收等动作。
对docker来讲1号进程大多数情况下都是服务进程,或者是用户自己开发的服务daemon进程,这也是瘦容器的理论,那服务进程作为1号进程有什么区别呢?
本文详细讲述1号进程的区别,如何规避僵尸进程等

docker的进程管理
docker进程管理的基础是LINUX内核中的PID命名空间技术,在不同PID名空间中,进程ID是独立的;即在两个不同名空间下的进程可以有相同的PID。
在Docker中,每个Container都是Docker Daemon的子进程,每个Container进程缺省都具有不同的PID名空间。通过名空间技术,Docker实现容器间的进程隔离。
当创建一个Docker容器的时候,就会新建一个PID名空间。容器启动进程在该名空间内PID为1。当PID1进程结束之后,Docker会销毁对应的PID名空间,并向容器内所有其它的子进程发送SIGKILL。

知识点2:由于PID1进程的特殊性,Linux内核为他做了特殊处理。如果它没有提供某个信号的处理逻辑,那么与其在同一个PID名空间下的进程发送给它的该信号都会被屏蔽。这个功能的主要作用是防止init进程被误杀
附加知识点: 自从Docker 1.5之后,docker run命令引入了–pid=host参数来支持使用宿主机PID名空间来启动容器进程,这样可以方便的实现容器内应用和宿主机应用之间的交互:比如利用容器中的工具监控和调试宿主机进程。
指定docker的1号进程
可以被Dockerfile中的ENTRYPOINT或CMD指令所指明;也可以被docker run命令的启动参数所覆盖
这里主要描述在ENTRYPOINT和CMD指令中,提供两种不同的进程执行方式 shell 和 exec

shell 方式 CMD executable param1 param2
CMD redisadmin -d startup -P 6379 -f

注意:如果redisadmin是shell脚本,则启动方式为/bin/sh -c ”redisadmin -d startup -P 6379 -f”,这样1号进程就为/bin/sh,1号进程中拉起的redisadmin -d startup -P 6379 -f
但是我的redisadmin为python的,首行写的#!/usr/bin/env python3,所以从上面例子可以看到1号进程为python3 /usr/local/bin/redisadmin -d startup -P 6379 -f
这样实际上跟exec方式一样了。

exec 方式 CMD [“executable”,“param1”,“param2”] 这种方式跟run命令的启动参数覆盖的1号进程一样,写的什么什么就是1号进程
这两种方式的具体不同在哪里?
这里就用到了进程管理那部分的知识,PID1进程对于操作系统而言具有特殊意义。操作系统的PID1进程是init进程,以守护进程方式运行,是所有其他进程的祖先,具有完整的进程生命周期管理能力。在Docker容器中,PID1进程是启动进程,它也会负责容器内部进程管理的工作。而这也将导致进程管理在Docker容器内部和完整操作系统上的不同。
不同1: 到底谁负责进程管理,比如我redisadmin为1号,我在里面写了很多子进程处理的代码,但是shell方式他的1号进程是bash,就会导致无法做处理了
不同2:Docker提供了两个命令docker stop和docker kill来向容器中的PID1进程发送信号
当执行docker stop命令时,docker会首先向容器的PID1进程发送一个SIGTERM信号,用于容器内程序的退出。如果容器在收到SIGTERM后没有结束, 那么Docker Daemon会在等待一段时间(默认是10s)后,再向容器发送SIGKILL信号,将容器杀死变为退出状态。
也就是说如果我在1号进程实现了SIGTERM(15)信号处理,比如不是上面那样简单的退出自己,而是先优雅的对redis执行shutdown(redis做bgsave保证数据不丢失),然后再sys.exit(1),这样就实现了容器优雅stop
而docker kill可以向容器内PID1进程发送任何信号,缺省是发送SIGKILL信号来强制退出应用,当然这里并不是用exec执行的,上面提到过exec是干不掉1号进程的,这里在宿主机上对1号进程下发的kill
僵尸进程
当一个子进程终止后,它首先会变成一个“失效(defunct)”的进程,也称为“僵尸(zombie)”进程,等待父进程或系统收回(reap)。在Linux内核中维护了关于“僵尸”进程的一组信息(PID,终止状态,资源使用信息),从而允许父进程能够获取有关子进程的信息。如果不能正确回收“僵尸”进程,那么他们的进程描述符仍然保存在系统中,系统资源会缓慢泄露。
僵尸进程:终止的进程但是因为父进程没有垃圾回收功能导致的进程,跟孤儿进程的区别是孤儿进程知识父进程退出了,但是自己还未终止
孤儿进程:子进程未退出,但是父进程退出了,这种进程会变为孤儿进程,在Linux中Init进程(PID1)作为所有进程的父进程,会维护进程树的状态,一旦有某个子进程成为了“孤儿”进程后,init就会负责接管这个子进程。当一个子进程成为“僵尸”进程之后,如果其父进程已经结束,init会收割这些“僵尸”,释放PID资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值