Seccomp 和 Kubernetes

Seccomp 表示安全计算(Secure Computing)模式,自 2.6.12 版本以来,一直是 Linux 内核的一个特性。 它可以用来沙箱化进程的权限,限制进程从用户态到内核态的调用。 Kubernetes 能使你自动将加载到节点上的 seccomp 配置文件应用到你的 Pod 和容器。

Seccomp 字段

特性状态: Kubernetes v1.19 [stable]

有四种方式可以为 Pod 指定 seccomp 配置文件:

  1. pods/security/seccomp/fields.yaml
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: pod
  5. spec:
  6. securityContext:
  7. seccompProfile:
  8. type: Unconfined
  9. ephemeralContainers:
  10. - name: ephemeral-container
  11. image: debian
  12. securityContext:
  13. seccompProfile:
  14. type: RuntimeDefault
  15. initContainers:
  16. - name: init-container
  17. image: debian
  18. securityContext:
  19. seccompProfile:
  20. type: RuntimeDefault
  21. containers:
  22. - name: container
  23. image: docker.io/library/debian:stable
  24. securityContext:
  25. seccompProfile:
  26. type: Localhost
  27. localhostProfile: my-profile.json

上面的示例中的 Pod 以 Unconfined 运行,而 ephemeral-containerinit-container 独立设置了 RuntimeDefault。 如果临时容器或 Init 容器没有明确设置 securityContext.seccompProfile 字段, 则此值将从 Pod 继承。同样的机制也适用于运行 Localhost 配置文件 my-profile.json 的容器。

一般来说,(临时)容器的字段优先级高于 Pod 层级的值,而未设置 seccomp 字段的容器则从 Pod 继承配置。

说明:

你不可以将 seccomp 配置文件应用到在容器的 securityContext 中设置了 privileged: true 的 Pod 或容器。特权容器始终以 Unconfined 运行。

对于 seccompProfile.type,可以使用以下值:

Unconfined

工作负载在没有任何 seccomp 限制的情况下运行。

RuntimeDefault

容器运行时定义的默认 seccomp 配置文件被应用。这个默认的配置文件旨在提供一套强大的安全默认值,同时保持工作负载的功能不受影响。 不同的容器运行时及其版本之间的默认配置文件可能会有所不同, 例如在比较 CRI-Ocontainerd 的默认配置文件时就会发现不同。

Localhost

localhostProfile 将被应用,这一配置必须位于节点磁盘上(在 Linux 上是 /var/lib/kubelet/seccomp)。 在创建容器时,容器运行时会验证 seccomp 配置文件的可用性。如果此配置文件不存在,则容器创建将失败,并报错 CreateContainerError

Localhost 配置文件

Seccomp 配置文件是遵循 OCI 运行时规范定义的 JSON 文件。配置文件主要根据所匹配的系统调用来定义操作,但也允许将特定值作为参数传递给系统调用。例如:

  1. {
  2. "defaultAction": "SCMP_ACT_ERRNO",
  3. "defaultErrnoRet": 38,
  4. "syscalls": [
  5. {
  6. "names": [
  7. "adjtimex",
  8. "alarm",
  9. "bind",
  10. "waitid",
  11. "waitpid",
  12. "write",
  13. "writev"
  14. ],
  15. "action": "SCMP_ACT_ALLOW"
  16. }
  17. ]
  18. }

上述配置文件中的 defaultAction 被定义为 SCMP_ACT_ERRNO,并可回退至 syscalls 中所定义的操作。 此错误通过 defaultErrnoRet 字段被定义为代码 38

通常可以使用以下操作:

SCMP_ACT_ERRNO

返回指定的错误码。

SCMP_ACT_ALLOW

允许执行系统调用。

SCMP_ACT_KILL_PROCESS

杀死进程。

SCMP_ACT_KILL_THREADSCMP_ACT_KILL

仅杀死线程。

SCMP_ACT_TRAP

发送 SIGSYS 信号。

SCMP_ACT_NOTIFYSECCOMP_RET_USER_NOTIF

通知用户空间。

SCMP_ACT_TRACE

使用指定的值通知跟踪进程。

SCMP_ACT_LOG

在将操作记录到 syslog 或 auditd 之后,允许执行系统调用。

SCMP_ACT_NOTIFYSECCOMP_RET_USER_NOTIF 这类操作可能不被支持, 具体取决于所使用的容器运行时、OCI 运行时或 Linux 内核版本。也可能存在其他限制, 例如 SCMP_ACT_NOTIFY 不能用作 defaultAction 或用于某些系统调用(如 write)。 所有这些限制由 OCI 运行时 (runccrun) 或 libseccomp 所定义。

syscalls JSON 数组包含对象列表,每个对象通过系统调用的 names 引用系统调用。 例如,SCMP_ACT_ALLOW 操作可用于创建包含如上例所示的系统调用的白名单。 也可以使用 SCMP_ACT_ERRNO 操作定义另一个列表,但会有不同的返回值(errnoRet)。

你还可以指定传递给某些系统调用的参数(args)。有关这些高级用例的细节,请参见 OCI 运行时规范Seccomp Linux 内核文档

进一步阅读