Seccomp 与 Kubernetes
Seccomp 代表安全计算模式(secure computing mode),自 Linux 内核 2.6.12 版本以来一直是其一个特性。它可以用于沙箱化进程的特权,限制其从用户空间向内核发起的调用。Kubernetes 允许你自动将加载到节点上的 Seccomp Profile 应用到你的 Pod 和容器。
Seccomp 字段
Kubernetes v1.19 [stable]
有四种方式为Pod指定 Seccomp Profile
- 使用
spec.securityContext.seccompProfile
为整个 Pod 指定 - 使用
spec.containers[*].securityContext.seccompProfile
为单个容器指定 - 使用
spec.initContainers[*].securityContext.seccompProfile
为 (可重启 / sidecar) Init 容器指定 - 使用 临时容器(Ephemeral container)的
spec.ephemeralContainers[*].securityContext.seccompProfile
字段指定
apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
securityContext:
seccompProfile:
type: Unconfined
ephemeralContainers:
- name: ephemeral-container
image: debian
securityContext:
seccompProfile:
type: RuntimeDefault
initContainers:
- name: init-container
image: debian
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: container
image: docker.io/library/debian:stable
securityContext:
seccompProfile:
type: Localhost
localhostProfile: my-profile.json
上述示例中的 Pod 以 Unconfined
模式运行,而 ephemeral-container
和 init-container
明确定义了 RuntimeDefault
。如果临时容器或 Init 容器没有显式设置 securityContext.seccompProfile
字段,则该值将从 Pod 继承。这同样适用于容器,它运行一个 Localhost
Profile my-profile.json
。
一般来说,(临时)容器中的字段优先级高于 Pod 级别的设置,而未设置 seccomp 字段的容器则会继承 Pod 的 Profile。
注意
无法将 Seccomp Profile 应用于在容器securityContext
中设置了 privileged: true
的 Pod 或容器。特权容器始终以 Unconfined
模式运行。seccompProfile.type
可能的值如下:
Unconfined
- 工作负载在没有任何 Seccomp 限制的情况下运行。
RuntimeDefault
- 应用由容器运行时定义的默认 Seccomp Profile。默认 Profile 旨在提供一套强大的安全默认设置,同时保留工作负载的功能。不同的容器运行时及其发布版本可能具有不同的默认 Profile,例如,比较 CRI-O 和 containerd 的默认 Profile。
Localhost
- 将应用
localhostProfile
,该 Profile 必须在节点磁盘上可用(在 Linux 上路径为/var/lib/kubelet/seccomp
)。容器运行时在创建容器时会验证 Seccomp Profile 的可用性。如果 Profile 不存在,则容器创建将失败并报CreateContainerError
错误。
Localhost
Profile
Seccomp Profile 是遵循OCI 运行时规范定义的方案的 JSON 文件。Profile 主要定义基于匹配的系统调用(syscall)的动作,但也允许将特定值作为参数传递给系统调用。例如:
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"syscalls": [
{
"names": [
"adjtimex",
"alarm",
"bind",
"waitid",
"waitpid",
"write",
"writev"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
上述 Profile 中的 defaultAction
定义为 SCMP_ACT_ERRNO
,并将作为 syscalls
中定义的操作的备用方案返回。错误通过 defaultErrnoRet
字段定义为代码 38
。
通常可以执行以下操作:
SCMP_ACT_ERRNO
- 返回指定的错误代码。
SCMP_ACT_ALLOW
- 允许执行系统调用。
SCMP_ACT_KILL_PROCESS
- 杀死进程。
SCMP_ACT_KILL_THREAD
和SCMP_ACT_KILL
- 仅杀死线程。
SCMP_ACT_TRAP
- 抛出
SIGSYS
信号。 SCMP_ACT_NOTIFY
和SECCOMP_RET_USER_NOTIF
。- 通知用户空间。
SCMP_ACT_TRACE
- 通知跟踪进程指定的值。
SCMP_ACT_LOG
- 在操作已记录到 syslog 或 auditd 后,允许执行系统调用。
某些操作(例如 SCMP_ACT_NOTIFY
或 SECCOMP_RET_USER_NOTIF
)可能不受支持,具体取决于使用的容器运行时、OCI 运行时或 Linux 内核版本。可能还存在其他限制,例如 SCMP_ACT_NOTIFY
不能用作 defaultAction
或用于某些系统调用(如 write
)。所有这些限制都由 OCI 运行时(runc、crun)或 libseccomp 定义。
syscalls
JSON 数组包含一个对象列表,这些对象通过各自的 names
引用系统调用。例如,动作 SCMP_ACT_ALLOW
可用于创建允许的系统调用白名单,如上例所示。也可以使用动作 SCMP_ACT_ERRNO
但指定不同的返回 (errnoRet
) 值来定义另一个列表。
还可以指定传递给某些系统调用的参数(args
)。有关这些高级用例的更多信息,请参阅OCI 运行时规范和Seccomp Linux 内核文档。