Docker Swarm环境下containerd-shim/runc子进程及exe进程技术问询
针对你在Docker Swarm环境里碰到的这些进程相关的困惑,结合你提供的auditd快照和补充信息,我来逐个给你拆解清楚:
1. 为何存在多层runc调用?
这其实是runc启动容器的正常流程。runc本身是轻量的容器启动工具,它的工作会拆分成分阶段的调用:父runc进程(PID24234)先fork出子runc进程(PID24240),这个子进程负责完成容器的命名空间隔离、rootfs挂载等初始化操作,之后子runc进程再通过execve调用容器的主进程。这种分层调用是为了把容器初始化逻辑和实际执行进程的逻辑隔离开,确保父runc可以快速退出,由containerd-shim接管后续的容器生命周期管理。
2. 为什么进程显示为"exe"而非runc?它是容器主进程吗?
这个看起来可疑的"exe"其实是auditd日志的特性,完全合法。当一个进程调用execve执行新二进制文件时,在二进制还没完全加载、进程名称还没更新的瞬间,auditd会把这个过渡状态的进程标记为"exe"。在你的快照里,这个"exe"进程(PID24240)就是runc正在启动的容器主进程,等二进制完全加载后,进程名称就会变成容器主进程的实际名字(比如Apache的httpd)。所以它确实是容器主进程的过渡状态。
3. 名为"4"、路径为"/"的进程是什么?
这个"4"是系统调用编号(x86_64架构下,syscall编号4对应sys_write,这里更可能是runc切换容器rootfs时触发的系统调用),而路径"/"是主机视角下容器rootfs的挂载点——当runc准备启动容器主进程时,会切换到容器的rootfs中,从主机角度看,进程的当前工作目录就是容器的"/"。这个进程是容器主进程启动过程中的中间状态,属于容器内进程的一部分,最终会演化成容器的主进程。
4. curl是Apache容器的健康检查吗?
完全正确!结合你补充的Dockerfile里的HEALTHCHECK配置(每5秒执行一次curl检查localhost:80),这个curl进程(PID24242)的父进程是runc(PID24234),而runc的父进程是containerd-shim——这完全符合Docker健康检查的执行逻辑:containerd通过runc exec的方式进入容器内部执行健康检查命令,所以这个curl就是你配置的容器健康检查进程,和你观察到的进程频繁出现的时间线也匹配(每5秒一次,和interval=5s对应)。
5. 如果容器主进程不是"4",怎么通过类似方式查看?
你可以用这些方法来定位容器主进程:
- 查看完整auditd日志:用
ausearch -k procmon -i | grep -i execve过滤execve事件,找父进程链包含containerd-shim/runc,且exe路径对应容器主进程的条目(比如Apache的/usr/sbin/httpd),还可以添加grep httpd精准过滤。 - 用Docker命令直接查询:执行
docker inspect <容器ID> --format '{{.State.Pid}}',就能直接得到容器主进程的PID,再用ps -ef | grep <PID>查看进程详情。 - 查看进程树:用
pstree -p <containerd-shim的PID>,可以清晰看到该shim下的所有子进程,包括runc和容器主进程的层级关系。 - 增强auditd监控规则:如果需要更详细的信息,可以更新auditctl规则:
auditctl -a always,exit -F arch=b64 -S execve -F key=procmon -k execve-detail,这样会记录进程的完整命令行参数,更容易区分容器主进程和其他辅助进程。
内容的提问来源于stack exchange,提问作者Marvin

