为什么杀死pod的pause进程业务容器也会退出,杀死业务进程 pause 进程却不退出?它们都是shim的子进程,区别在哪?
一个pod进程关系如图
root 163187 0.0 0.1 712460 12828 pts/2 Sl 21:40 0:00 \_ /usr/bin/containerd-shim-runc-v2 -namespace k8s.io -id e7927073fe3617c5cfd587c17bd5b9a98131a root 163209 0.0 0.0 1028 4 ? Ss 21:40 0:00 | \_ /pause root 163242 0.0 0.0 1332 4 ? Ss 21:40 0:00 | \_ top
进入容器内 进程关系如图
[root@localhost pod]# nerdctl -n k8s.io exec -it e76 sh
/ # ps -ef
PID USER TIME COMMAND
1 root 0:00 /pause
7 root 0:00 top
38 root 0:00 sh
44 root 0:00 ps -ef
1号进程的父id是0 也就是shim
/ # cat /proc/1/status |grep -i ppid PPid: 0
7号业务进程的父亲进程是0 也就是shim (说明它不是1号进程的后代)
/ # cat /proc/7/status |grep -i ppid PPid: 0
cat /run/containerd/io.containerd.runtime.v2.task/k8s.io/8efdde181c87bf3cbecfd0282218372106a4c6258284bc7c9ca8ddbf2f4f4e5b/config.json|jq 查看runc配置文件
业务的 "namespaces": [ { "type": "pid", "path": "/proc/187682/ns/pid" }, { "type": "ipc", "path": "/proc/187682/ns/ipc" }, { "type": "uts", "path": "/proc/187682/ns/uts" }, { "type": "mount" }, { "type": "network", "path": "/proc/187682/ns/net" } ] pause的 "namespaces": [ { "type": "pid" }, { "type": "ipc" }, { "type": "uts" }, { "type": "mount" }, { "type": "network", "path": "/var/run/netns/cni-8a9bc5d1-491d-a07f-7465-3d17b37bee51" } ]
对比发现pause的没有 "pid" 没有path路径
shim代码如下
// ShouldKillAllOnExit reads the bundle's OCI spec and returns true if // there is an error reading the spec or if the container has a private PID namespace func ShouldKillAllOnExit(ctx context.Context, bundlePath string) bool { var bundleSpec specs.Spec bundleConfigContents, err := os.ReadFile(filepath.Join(bundlePath, "config.json")) if err != nil { log.G(ctx).WithError(err).Error("shouldKillAllOnExit: failed to read config.json") return true } if err := json.Unmarshal(bundleConfigContents, &bundleSpec); err != nil { log.G(ctx).WithError(err).Error("shouldKillAllOnExit: failed to unmarshal bundle json") return true } if bundleSpec.Linux != nil { for _, ns := range bundleSpec.Linux.Namespaces { if ns.Type == specs.PIDNamespace && ns.Path == "" { return false } } } return true }
所以是pause容器的时候返回false(共享pid命名空间,不带路径),业务容器返回true(私有pid命名空间,带了路径)
if ip, ok := p.(*process.Init); ok {// Ensure all children are killed if runc.ShouldKillAllOnExit(s.context, container.Bundle) {
if err := ip.KillAll(s.context); err != nil { logrus.WithError(err).WithField("id", ip.ID()). Error("failed to kill init's children") } }
所以上边代码会kill掉业务容器,忽略掉pause容器
root 186449 0.0 0.1 712460 10140 pts/4 Sl 01:24 0:00 \_ /usr/bin/containerd-shim-runc-v2 -namespace k8s.io -id 7bc44216dfa430195653661661e06d42c7a15 root 186470 0.0 0.0 1028 4 ? Ss 01:24 0:00 \_ /pause kill 杀死业务容器, pause容器仍然存活

浙公网安备 33010602011771号