Seccomp 和 Kubernetes
Seccomp 是 secure computing mode(安全计算模式)的缩写,自 2.6.12 版本起一直是 Linux 内核的一项功能。它可用于对进程的权限进行沙盒化,限制其能从用户空间发起到内核的调用。Kubernetes 允许您将加载到 节点 上的 seccomp 配置文件自动应用到您的 Pod 和容器。
Seccomp 字段
Kubernetes v1.19 [stable]
有四种方式可以为 Pod 指定 seccomp 配置文件:
- 使用
spec.securityContext.seccompProfile
为整个 Pod 设置 - 使用
spec.containers[*].securityContext.seccompProfile
为单个容器设置 - 使用
spec.initContainers[*].securityContext.seccompProfile
为(可重启 / 边车)初始化容器设置 - 使用
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
。如果临时容器或初始化容器未显式设置 securityContext.seccompProfile
字段,则将从 Pod 继承该值。对于运行 Localhost
配置文件 my-profile.json
的容器也是如此。
总的来说,(临时)容器的字段优先级高于 Pod 级别的设置,而未设置 seccomp 字段的容器则继承 Pod 的配置文件。
注意
对于在容器的securityContext
中设置了 privileged: true
的 Pod 或容器,无法应用 seccomp 配置文件。特权容器始终以 Unconfined
模式运行。seccompProfile.type
可能的取值如下:
Unconfined
- 工作负载在没有任何 seccomp 限制的情况下运行。
RuntimeDefault
- 应用由 容器运行时 定义的默认 seccomp 配置文件。默认配置文件旨在提供强大的安全默认设置,同时保留工作负载的功能。默认配置文件可能因容器运行时及其发布版本而异,例如,比较 CRI-O 和 containerd 之间的差异。
Localhost
- 将应用
localhostProfile
,该文件必须存在于节点磁盘上(在 Linux 上是/var/lib/kubelet/seccomp
)。在容器创建时,由 容器运行时 验证 seccomp 配置文件的可用性。如果配置文件不存在,则容器创建将失败并出现CreateContainerError
。
localhostProfile
Seccomp 配置文件是遵循 OCI runtime specification 定义的模式的 JSON 文件。配置文件主要根据匹配的系统调用定义操作,但也允许将特定值作为参数传递给系统调用。例如:
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"syscalls": [
{
"names": [
"adjtimex",
"alarm",
"bind",
"waitid",
"waitpid",
"write",
"writev"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
上面的配置文件中的 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 runtime spec 和 Seccomp Linux 内核文档。