在K8s环境中,下发的故障已经被恢复了,但是Pod中仍存在该故障的“僵尸进程”。本文介绍该情况可能的原因以及解决方案。

可能原因

这是因为容器中存在PID Namespace隔离。在容器中,故障演练进程的父进程是PID=1的进程,容器中的一号进程不具有进程资源回收的能力,所以导致故障演练进程被终止之后,资源没有得到回收,从而成为僵尸进程。

解决方案

通过手动共享PID Namespace解决该问题。

在Pod的YAML文件中增加shareProcessNamespace: true,从而将Pod容器中PID=1的进程改为/pause进程,如下所示。

apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubernetes.io/psp: ack.privileged
  labels:
    app: myapp
  name: myapp-pod
  namespace: ahas
spec:
  shareProcessNamespace: true
  containers:
  - command:
    - sh
    - -c
    - echo Hello Kubernetes! && sleep 3600
    image: busybox
    imagePullPolicy: Always
    name: myapp-container
    resources: {}

注意事项

共享PID Namespace会带来以下影响:

  • 容器进程不再具有PID 1。

    在没有PID 1的情况下,一些容器镜像会拒绝启动(例如使用systemd的容器),或者拒绝执行kill -HUP 1之类的命令来通知容器进程。在具有共享进程命名空间的Pod中,如果执行kill -HUP 1,将会把消息通知到Pod沙箱(本文示例中的Pod沙箱即/pause)。

  • 进程对Pod中的其他容器可见。

    包括/proc中可见的所有信息,例如作为参数或环境变量传递的密码,这些信息仅受常规Unix权限的保护。

  • 容器文件系统通过/proc/$pid/root链接对Pod中的其他容器可见。

    这使调试更加容易,但也意味着文件系统安全性只受文件系统权限的保护。