Seccomp 和 Kubernetes
Seccomp 表示安全计算(Secure Computing)模式,自 2.6.12 版本以来,一直是 Linux 内核的一个特性。 它可以用来沙箱化进程的权限,限制进程从用户态到内核态的调用。 Kubernetes 能使你自动将加载到节点上的 seccomp 配置文件应用到你的 Pod 和容器。
Seccomp 字段
Kubernetes v1.19 [stable]
有四种方式可以为 Pod 指定 seccomp 配置文件:
- 为整个 Pod 使用
spec.securityContext.seccompProfile
- 为单个容器使用
spec.containers[*].securityContext.seccompProfile
- 为(可重启/边车)Init 容器使用
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
。
如果临时容器或 Init 容器没有明确设置 securityContext.seccompProfile
字段,
则此值将从 Pod 继承。同样的机制也适用于运行 Localhost
配置文件 my-profile.json
的容器。
一般来说,(临时)容器的字段优先级高于 Pod 层级的值,而未设置 seccomp 字段的容器则从 Pod 继承配置。
说明:
你不可以将 seccomp 配置文件应用到在容器的 securityContext
中设置了 privileged: true
的
Pod 或容器。特权容器始终以 Unconfined
运行。
对于 seccompProfile.type
,可以使用以下值:
Unconfined
- 工作负载在没有任何 seccomp 限制的情况下运行。
RuntimeDefault
- 由容器运行时定义的默认 seccomp 配置文件被应用。这个默认的配置文件旨在提供一套强大的安全默认值,同时保持工作负载的功能不受影响。 不同的容器运行时及其版本之间的默认配置文件可能会有所不同, 例如在比较 CRI-O 和 containerd 的默认配置文件时就会发现不同。
Localhost
localhostProfile
将被应用,这一配置必须位于节点磁盘上(在 Linux 上是/var/lib/kubelet/seccomp
)。 在创建容器时,容器运行时会验证 seccomp 配置文件的可用性。如果此配置文件不存在,则容器创建将失败,并报错CreateContainerError
。
Localhost
配置文件
Seccomp 配置文件是遵循 OCI 运行时规范定义的 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 运行时规范
和 Seccomp Linux 内核文档。