1. Ephemeral Containers

Ephemeral Containers 是 Kubernetes 1.17 之后引入的新功能,通过 Ephemeral Containers 用户可以在不重建 Pod 的前提下注入一个特殊的容器,该容器和 Pod 的其他容器类似,他们共享 uts、net、ipc 命名空间。Ephemeral Containers 一定程度上放宽了 Kubernetes 对 Pod 是不可变单元的要求。

Ephemeral Containers 并没有独立的 Resource 定义,目前用户只能通过以下两种方式创建 Ephemeral Containers:

  • kubectl debug 命令
  • 调用 kube-apiserver 原始 API 接口

上述两种方式本质上都是对 Pod 进行 Patch 操作,kubectl debug 命令为例,执行以下命令可以在 pod/centos-ping 中注入一个 ephemeralContainers:

1
kubectl  debug pod/centos-ping --image=busybox -it bash

执行上述命令后,通过 kubectl get pod/centos-ping -oyaml 我们可以看到 Pod 中多了一下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
spec:
  ephemeralContainers:
  - image: busybox:latest
    imagePullPolicy: IfNotPresent
    name: debugger-2v5jr
    resources: {}
    stdin: true
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    tty: true
status:
  ephemeralContainerStatuses:
  - containerID: docker://18539c01041bcbb92ac92bdad1d17555d688afe18a975b082c4e95bfd12d4a53
    image: busybox:latest
    imageID: docker://sha256:675a8e1c58873b67bf0f5d0cf1c2aa7633ddda4187642861152efaa0bdfc9937
    lastState: {}
    name: debugger-2v5jr
    ready: false
    restartCount: 0
    state:
      running:
        startedAt: "2022-07-29T07:04:50Z"

2. 共享其他命名空间

Ephemeral Containers 本质上和 Pod 中的其他容器没有区别,它们只能共享 uts、net、ipc 命名空间,但 mnt、pid 命名空间各自独立。

以下内容分享一下一些共享 mnt、pid 命名空间的技巧。

Kubernetes 支持在 pod 中设置 spec.shareProcessNamespace=true 强制使所有容器共享 pid 命名空间,开启 shareProcessNamespace 后,在任意容器中通过 ps 命令能够看到所有容器的进程信息,并且此时 pause 容器主进程的进程号为 1,如下:

1
2
3
4
5
6
kubectl patch deployment <deployment> --patch '
spec:
  template:
    spec:
      shareProcessNamespace: true
'

通常情况下,用户不会在生产环境下开启 shareProcessNamespace ,而临时更新 shareProcessNamespace 配置会使 Pod 重建破坏了现场。

在测试过程中发现开启 shareProcessNamespace 后, 删除 pod 时容器内的业务进程似乎无法接收到系统发出的 SIGHUP 。

针对上述问题,kubectl 命令提供了 –target 参数,该参数可以使 EphemeralContainers 和 Pod 中的指定容器共享 pid 命名空间,效果如下:

1
kubectl  debug pod/<podname> --image=busybox --target=<pod_container_name>  -it bash

如果 Pod 中包含多个容器,用户需要在同一个 pid 命名空间中观察所有进程时,kubectl debug 提供的方案是重新启动一个完全一样的 pod,并且开启 shareProcessNamespace,命令如下:

1
kubectl  debug pod/<podname> --image=busybox --copy-to=<copy_podname> --share-processes=true --same-node=true  -it bash

目前 kubectl debug 不支持为 Ephemeral Containers 挂载 volume ,如果想要在 Ephemeral Containers 中查看目标的文件系统,需要先共享目标容器的 pid namespace,此时 目标容器的文件系统被挂载在 /proc/${pid}/root 目录下。

3. 通过 API 接口创建 Ephemeral Containers

通过接口创建 Ephemeral Containers 时可以挂载指定的 volume,参考以下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
$ kubectl get pod ${POD_NAME} \
  -o jsonpath='{.status.ephemeralContainerStatuses}' \
  | python3 -m json.tool
[
    {
        "containerID": "containerd://049d76...",
        "image": "docker.io/library/busybox:latest",
        "imageID": "docker.io/library/busybox@sha256:ebadf8...",
        "lastState": {},
        "name": "debugger",
        "ready": false,
        "restartCount": 0,
        "state": {
👉          "running": {
                "startedAt": "2022-05-29T13:41:04Z"
            }
        }
    }
]

参考