如何使用DaemonSet执行特权代码

简单点说,最低有三个条件。

  1. spec.hostPID is true.
  2. spec.containers.securityContext.privileged is true.
  3. 镜像里有nsenter.

条件1主要是为了让你能找到host的mnt namespace,然后你用条件3里的nsenter来在这个namespace里执行代码。就像这样。

/usr/bin/nsenter -m/proc/1/ns/mnt bash /runOnHost.sh

host上如何执行脚本

nsenter在host namespace下执行的时候,是不访问容器内文件系统的(或者很麻烦)。所以在host上执行脚本,最简单的办法就是拷过去。

cp /srv/runOnHost.sh /host/runOnHost.sh
/usr/bin/nsenter -m/proc/1/ns/mnt bash /runOnHost.sh
rm /host/runOnHost.sh

这就引出了一个新要求。如果要复制文件,pod需要挂载host文件系统。

      containers:
        volumeMounts:
        - mountPath: /host
          name: host-mount
      volumes:
      - hostPath:
          path: /
          type: ""
        name: host-mount

如何访问网络

注意,虽然我们进入了host的mnt namespace,但是network用的还是容器的。如果你的代码不需要网络,或者容器网络就能工作,那很好。如果需要host网络,那么需要设置spec.hostNetwork为true。

最简化镜像

很幸运的是,ubuntu官方镜像带了bashnsenter,因此不单独pack一个image来执行脚本是可能的。

  1. 使用ubuntu镜像。
  2. 用文件目录创建一个ConfigMap。
  3. 在DaemonSet里引用这个ConfigMap并且mount。
      containers:
        volumeMounts:
        - mountPath: /srv
          name: scripts
      volumes:
      - configMap:
          defaultMode: 0755
          name: rce-testing
        name: scripts

Put all together

runOnHost.sh: 随意

runOnPod.sh:

#!/bin/bash

cp /srv/runOnHost.sh /host/runOnHost.sh
/usr/bin/nsenter -m/proc/1/ns/mnt bash /runOnHost.sh
rm /host/runOnHost.sh
sleep 864000000

用以下命令生成一个ConfigMap,内容是上述两个文件。

kubectl create configmap rce-testing --from-file=srv/

rce-testing.yaml:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: rce-testing
  name: rce-testing
spec:
  selector:
    matchLabels:
      app: rce-testing
  template:
    metadata:
      labels:
        app: rce-testing
    spec:
      hostPID: true
      hostNetwork: true
      containers:
      - name: ubuntu
        image: ubuntu
        imagePullPolicy: IfNotPresent
        command:
        - /bin/bash
        args:
        - /srv/runOnPod.sh
        securityContext:
          privileged: true
        volumeMounts:
        - mountPath: /srv
          name: scripts
        - mountPath: /host
          name: host-mount
      volumes:
      - configMap:
          defaultMode: 0755
          name: rce-testing
        name: scripts
      - hostPath:
          path: /
          type: ""
        name: host-mount

其他注意事项

PodSecurityPolicy可能会阻止你开特权pod,注意解锁。