为 Pod 或容器配置安全上下文
安全上下文定义了 Pod 或 Container 的权限和访问控制设置。安全上下文设置包括但不限于:
自主访问控制:访问对象(例如文件)的权限基于用户 ID (UID) 和组 ID (GID)。
安全增强 Linux (SELinux):对象被分配安全标签。
作为特权用户或非特权用户运行。
Linux 能力:赋予进程某些特权,但不是 root 用户的所有特权。
AppArmor:使用程序配置文件来限制单个程序的能力。
Seccomp:过滤进程的系统调用。
allowPrivilegeEscalation
:控制进程是否可以获得比其父进程更多的特权。这个布尔值直接控制是否在容器进程上设置no_new_privs
标志。当容器满足以下条件时,allowPrivilegeEscalation
始终为 true:- 作为特权容器运行时,或者
- 拥有
CAP_SYS_ADMIN
能力时。
readOnlyRootFilesystem
:将容器的根文件系统挂载为只读。
以上项目并非安全上下文设置的完整列表——请参阅 SecurityContext 获取完整列表。
准备工作
你需要拥有一个 Kubernetes 集群,并且 kubectl 命令行工具已被配置为与集群通信。建议在本教程中使用至少两个非控制平面主机节点的集群。如果你还没有集群,可以使用 minikube 创建一个,或者使用以下 Kubernetes 试玩环境:
要检查版本,请输入 kubectl version
。
为 Pod 设置安全上下文
要为 Pod 指定安全设置,请在 Pod 规约中包含 securityContext
字段。securityContext
字段是一个 PodSecurityContext 对象。为 Pod 指定的安全设置适用于 Pod 中的所有容器。以下是具有 securityContext
和 emptyDir
卷的 Pod 的配置文件:
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
supplementalGroups: [4000]
volumes:
- name: sec-ctx-vol
emptyDir: {}
containers:
- name: sec-ctx-demo
image: busybox:1.28
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- name: sec-ctx-vol
mountPath: /data/demo
securityContext:
allowPrivilegeEscalation: false
在配置文件中,runAsUser
字段指定 Pod 中所有容器内的所有进程都将以用户 ID 1000 运行。runAsGroup
字段指定 Pod 中所有容器内所有进程的主要组 ID 为 3000。如果省略此字段,容器的主要组 ID 将为 root (0)。当指定 runAsGroup
时,创建的任何文件也将归用户 1000 和组 3000 所有。由于指定了 fsGroup
字段,容器的所有进程也都属于补充组 ID 2000。卷 /data/demo
的所有者及其在该卷中创建的任何文件将是组 ID 2000。此外,当指定 supplementalGroups
字段时,容器的所有进程也都属于指定的组。如果省略此字段,则表示为空。
创建 Pod
kubectl apply -f https://k8s.io/examples/pods/security/security-context.yaml
验证 Pod 的容器正在运行
kubectl get pod security-context-demo
获取运行中容器的 Shell
kubectl exec -it security-context-demo -- sh
在 Shell 中,列出运行中的进程
ps
输出显示进程以用户 1000 运行,这是 runAsUser
的值。
PID USER TIME COMMAND
1 1000 0:00 sleep 1h
6 1000 0:00 sh
...
在 Shell 中,导航到 /data
目录,并列出其中的目录
cd /data
ls -l
输出显示 /data/demo
目录的组 ID 为 2000,这是 fsGroup
的值。
drwxrwsrwx 2 root 2000 4096 Jun 6 20:08 demo
在 Shell 中,导航到 /data/demo
目录,并创建一个文件
cd demo
echo hello > testfile
列出 /data/demo
目录中的文件
ls -l
输出显示 testfile
的组 ID 为 2000,这是 fsGroup
的值。
-rw-r--r-- 1 1000 2000 6 Jun 6 20:08 testfile
运行以下命令
id
输出类似于:
uid=1000 gid=3000 groups=2000,3000,4000
从输出可以看出,gid
是 3000,与 runAsGroup
字段的值相同。如果省略 runAsGroup
,gid
将保持为 0 (root),进程将能够与 root (0) 组拥有的文件以及对 root (0) 组具有所需组权限的组进行交互。你还可以看到 groups
包含除了 gid
之外,由 fsGroup
和 supplementalGroups
指定的组 ID。
退出 Shell
exit
容器镜像中 /etc/group
定义的隐式组成员关系
默认情况下,Kubernetes 会将 Pod 中的组信息与容器镜像中 /etc/group
定义的信息合并。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
supplementalGroups: [4000]
containers:
- name: sec-ctx-demo
image: registry.k8s.io/e2e-test-images/agnhost:2.45
command: [ "sh", "-c", "sleep 1h" ]
securityContext:
allowPrivilegeEscalation: false
这个 Pod 安全上下文包含了 runAsUser
、runAsGroup
和 supplementalGroups
。但是,你可以看到附加到容器进程的实际补充组会包含来自容器镜像中 /etc/group
的组 ID。
创建 Pod
kubectl apply -f https://k8s.io/examples/pods/security/security-context-5.yaml
验证 Pod 的容器正在运行
kubectl get pod security-context-demo
获取运行中容器的 Shell
kubectl exec -it security-context-demo -- sh
检查进程身份
$ id
输出类似于:
uid=1000 gid=3000 groups=3000,4000,50000
你可以看到 groups
包含了组 ID 50000
。这是因为镜像中定义的用户 (uid=1000
) 属于容器镜像中 /etc/group
定义的组 (gid=50000
)。
检查容器镜像中的 /etc/group
$ cat /etc/group
你可以看到 uid 1000
属于组 50000
。
...
user-defined-in-image:x:1000:
group-defined-in-image:x:50000:user-defined-in-image
退出 Shell
exit
注意
隐式合并的补充组可能会导致安全问题,尤其是在访问卷时(参见 kubernetes/kubernetes#112879 获取详情)。如果你想避免这种情况,请参阅下面的章节。为 Pod 配置细粒度的 SupplementalGroups 控制
Kubernetes v1.33 [beta]
(默认启用:true)通过为 kubelet 和 kube-apiserver 设置 SupplementalGroupsPolicy
功能门控,并为 Pod 设置 .spec.securityContext.supplementalGroupsPolicy
字段,可以启用此功能。
supplementalGroupsPolicy
字段定义了计算 Pod 中容器进程的补充组的策略。此字段有两个有效值:
Merge
:将合并容器主要用户在/etc/group
中定义的组成员关系。如果未指定,这是默认策略。Strict
:只有fsGroup
、supplementalGroups
或runAsGroup
字段中的组 ID 会被附加为容器进程的补充组。这意味着不会合并容器主要用户在/etc/group
中的任何组成员关系。
启用此功能后,它还会暴露附加到第一个容器进程的进程身份,该身份位于 .status.containerStatuses[].user.linux
字段中。这对于检测是否附加了隐式组 ID 非常有用。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
supplementalGroups: [4000]
supplementalGroupsPolicy: Strict
containers:
- name: sec-ctx-demo
image: registry.k8s.io/e2e-test-images/agnhost:2.45
command: [ "sh", "-c", "sleep 1h" ]
securityContext:
allowPrivilegeEscalation: false
此 Pod 清单定义了 supplementalGroupsPolicy=Strict
。你可以看到,在 /etc/group
中定义的任何组成员关系都不会合并到容器进程的补充组中。
创建 Pod
kubectl apply -f https://k8s.io/examples/pods/security/security-context-6.yaml
验证 Pod 的容器正在运行
kubectl get pod security-context-demo
检查进程身份
kubectl exec -it security-context-demo -- id
输出类似于:
uid=1000 gid=3000 groups=3000,4000
查看 Pod 的状态
kubectl get pod security-context-demo -o yaml
你可以看到 status.containerStatuses[].user.linux
字段暴露了附加到第一个容器进程的进程身份。
...
status:
containerStatuses:
- name: sec-ctx-demo
user:
linux:
gid: 3000
supplementalGroups:
- 3000
- 4000
uid: 1000
...
注意
请注意,status.containerStatuses[].user.linux
字段中的值是附加到容器中第一个容器进程的第一个进程身份。如果容器具有足够的权限进行与进程身份相关的系统调用(例如 setuid(2)
、setgid(2)
或 setgroups(2)
等),则容器进程可以改变其身份。因此,实际的进程身份将是动态的。实现
已知以下容器运行时支持细粒度的 SupplementalGroups 控制。
CRI 级别
- containerd,从 v2.0 起
- CRI-O,从 v1.31 起
你可以在节点状态中查看该功能是否受支持。
apiVersion: v1
kind: Node
...
status:
features:
supplementalGroupsPolicy: true
注意
在此 Alpha 版本(从 v1.31 到 v1.32)中,当使用 SupplementalGroupsPolicy=Strict
的 Pod 被调度到不支持此功能(即 .status.features.supplementalGroupsPolicy=false
)的节点时,Pod 的补充组策略会静默地回退到 Merge
策略。
然而,自 Beta 版本 (v1.33) 起,为了更严格地执行策略,此类 Pod 创建将被 kubelet 拒绝,因为节点无法确保指定的策略。当你的 Pod 被拒绝时,你将看到带有 reason=SupplementalGroupsPolicyNotSupported
的警告事件,如下所示:
apiVersion: v1
kind: Event
...
type: Warning
reason: SupplementalGroupsPolicyNotSupported
message: "SupplementalGroupsPolicy=Strict is not supported in this node"
involvedObject:
apiVersion: v1
kind: Pod
...
为 Pod 配置卷权限和所有权变更策略
Kubernetes v1.23 [stable]
默认情况下,当卷被挂载时,Kubernetes 会递归地更改每个卷内容的权限和所有权,使其与 Pod 的 securityContext
中指定的 fsGroup
匹配。对于大型卷,检查和更改所有权和权限可能需要很长时间,从而减慢 Pod 的启动。你可以在 securityContext
中使用 fsGroupChangePolicy
字段来控制 Kubernetes 检查和管理卷所有权和权限的方式。
fsGroupChangePolicy - fsGroupChangePolicy
定义了在卷暴露给 Pod 内部之前更改卷所有权和权限的行为。此字段仅适用于支持 fsGroup
控制所有权和权限的卷类型。此字段有两个可能的值:
- OnRootMismatch:仅当根目录的权限和所有权与卷的预期权限不匹配时才更改权限和所有权。这有助于缩短更改卷所有权和权限所需的时间。
- Always:在卷挂载时总是更改卷的权限和所有权。
例如:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
fsGroupChangePolicy: "OnRootMismatch"
将卷权限和所有权变更委托给 CSI 驱动
Kubernetes v1.26 [stable]
如果你部署了支持 VOLUME_MOUNT_GROUP
NodeServiceCapability
的 容器存储接口 (CSI) 驱动,则根据 securityContext
中指定的 fsGroup
设置文件所有权和权限的过程将由 CSI 驱动而不是 Kubernetes 执行。在这种情况下,由于 Kubernetes 不执行任何所有权和权限更改,fsGroupChangePolicy
不会生效。并且根据 CSI 规范,驱动应使用提供的 fsGroup
挂载卷,从而使得该卷可由 fsGroup
读取/写入。
为容器设置安全上下文
要为容器指定安全设置,请在容器清单中包含 securityContext
字段。securityContext
字段是一个 SecurityContext 对象。为容器指定的安全设置仅适用于单个容器,并且在有重叠时会覆盖在 Pod 级别进行的设置。容器设置不影响 Pod 的卷。
以下是包含一个容器的 Pod 的配置文件。Pod 和容器都具有 securityContext
字段:
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-2
spec:
securityContext:
runAsUser: 1000
containers:
- name: sec-ctx-demo-2
image: gcr.io/google-samples/hello-app:2.0
securityContext:
runAsUser: 2000
allowPrivilegeEscalation: false
创建 Pod
kubectl apply -f https://k8s.io/examples/pods/security/security-context-2.yaml
验证 Pod 的容器正在运行
kubectl get pod security-context-demo-2
获取运行中容器的 Shell
kubectl exec -it security-context-demo-2 -- sh
在 Shell 中,列出运行中的进程
ps aux
输出显示进程以用户 2000 运行。这是为容器指定的 runAsUser
的值。它覆盖了为 Pod 指定的值 1000。
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
2000 1 0.0 0.0 4336 764 ? Ss 20:36 0:00 /bin/sh -c node server.js
2000 8 0.1 0.5 772124 22604 ? Sl 20:36 0:00 node server.js
...
退出 Shell
exit
为容器设置能力
使用 Linux 能力,你可以授予进程某些特权,而无需授予 root 用户的所有特权。要为容器添加或移除 Linux 能力,请在容器清单的 securityContext
节中包含 capabilities
字段。
首先,看看当你没有包含 capabilities
字段时会发生什么。以下是一个不添加或移除任何容器能力的配置文件:
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-3
spec:
containers:
- name: sec-ctx-3
image: gcr.io/google-samples/hello-app:2.0
创建 Pod
kubectl apply -f https://k8s.io/examples/pods/security/security-context-3.yaml
验证 Pod 的容器正在运行
kubectl get pod security-context-demo-3
获取运行中容器的 Shell
kubectl exec -it security-context-demo-3 -- sh
在 Shell 中,列出运行中的进程
ps aux
输出显示了容器的进程 ID (PID)
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4336 796 ? Ss 18:17 0:00 /bin/sh -c node server.js
root 5 0.1 0.5 772124 22700 ? Sl 18:17 0:00 node server.js
在 Shell 中,查看进程 1 的状态
cd /proc/1
cat status
输出显示了进程的能力位图
...
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
...
记下能力位图,然后退出 Shell
exit
接下来,运行一个与上面容器相同但设置了额外能力的容器。
以下是运行一个容器的 Pod 的配置文件。该配置添加了 CAP_NET_ADMIN
和 CAP_SYS_TIME
能力:
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-4
spec:
containers:
- name: sec-ctx-4
image: gcr.io/google-samples/hello-app:2.0
securityContext:
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
创建 Pod
kubectl apply -f https://k8s.io/examples/pods/security/security-context-4.yaml
获取运行中容器的 Shell
kubectl exec -it security-context-demo-4 -- sh
在 Shell 中,查看进程 1 的能力
cd /proc/1
cat status
输出显示了进程的能力位图
...
CapPrm: 00000000aa0435fb
CapEff: 00000000aa0435fb
...
比较这两个容器的能力
00000000a80425fb
00000000aa0435fb
在第一个容器的能力位图中,位 12 和 25 是清除的。在第二个容器中,位 12 和 25 是设置的。位 12 是 CAP_NET_ADMIN
,位 25 是 CAP_SYS_TIME
。请参阅 capability.h 了解能力常量的定义。
注意
Linux 能力常量具有CAP_XXX
的形式。但在容器清单中列出能力时,必须省略常量的 CAP_
部分。例如,要添加 CAP_SYS_TIME
,请在能力列表中包含 SYS_TIME
。为容器设置 Seccomp Profile
要为容器设置 Seccomp profile,请在 Pod 或容器清单的 securityContext
部分包含 seccompProfile
字段。seccompProfile
字段是一个 SeccompProfile 对象,包含 type
和 localhostProfile
。type
的有效选项包括 RuntimeDefault
、Unconfined
和 Localhost
。localhostProfile
只能在 type: Localhost
时设置。它表示节点上预配置 profile 的路径,该路径是相对于 kubelet 配置的 Seccomp profile 位置(通过 --root-dir
标志配置)的。
以下是一个将 Seccomp profile 设置为节点容器运行时默认 profile 的示例:
...
securityContext:
seccompProfile:
type: RuntimeDefault
以下是一个将 Seccomp profile 设置为预配置文件 <kubelet-root-dir>/seccomp/my-profiles/profile-allow.json
的示例:
...
securityContext:
seccompProfile:
type: Localhost
localhostProfile: my-profiles/profile-allow.json
为容器设置 AppArmor Profile
要为容器设置 AppArmor profile,请在容器的 securityContext
部分包含 appArmorProfile
字段。appArmorProfile
字段是一个 AppArmorProfile 对象,包含 type
和 localhostProfile
。type
的有效选项包括 RuntimeDefault
(默认)、Unconfined
和 Localhost
。localhostProfile
只能在 type
为 Localhost
时设置。它表示节点上预配置 profile 的名称。由于你不知道 Pod 将被调度到哪里,profile 需要加载到所有适合该 Pod 的节点上。有关设置自定义 profile 的方法,请参见使用 profile 设置节点。
注意:如果 containers[*].securityContext.appArmorProfile.type
显式设置为 RuntimeDefault
,则如果节点上未启用 AppArmor,Pod 将不被准入。但如果未指定 containers[*].securityContext.appArmorProfile.type
,则只有在节点启用 AppArmor 时才会应用默认值(也是 RuntimeDefault
)。如果节点禁用 AppArmor,Pod 将被准入,但容器将不受 RuntimeDefault
profile 的限制。
以下是一个将 AppArmor profile 设置为节点容器运行时默认 profile 的示例:
...
containers:
- name: container-1
securityContext:
appArmorProfile:
type: RuntimeDefault
以下是一个将 AppArmor profile 设置为名为 k8s-apparmor-example-deny-write
的预配置 profile 的示例:
...
containers:
- name: container-1
securityContext:
appArmorProfile:
type: Localhost
localhostProfile: k8s-apparmor-example-deny-write
更多详细信息请参见使用 AppArmor 限制容器对资源的访问。
为容器分配 SELinux 标签
要为容器分配 SELinux 标签,请在 Pod 或容器清单的 securityContext
部分包含 seLinuxOptions
字段。seLinuxOptions
字段是一个 SELinuxOptions 对象。以下是一个应用 SELinux 级别的示例:
...
securityContext:
seLinuxOptions:
level: "s0:c123,c456"
注意
要分配 SELinux 标签,必须在主机操作系统上加载 SELinux 安全模块。在不支持 SELinux 的 Windows 和 Linux 工作节点上,此字段以及下面描述的任何 SELinux 功能门控均无效。高效的 SELinux 卷重新打标签
Kubernetes v1.28 [beta]
(默认启用:true)注意
Kubernetes v1.27 引入了此行为的一种早期有限形式,该形式仅适用于使用 ReadWriteOncePod
访问模式的卷(和 PersistentVolumeClaim)。
Kubernetes v1.33 将 SELinuxChangePolicy
和 SELinuxMount
功能门控提升为 Beta 版,以将此性能改进扩展到其他类型的 PersistentVolumeClaim,具体解释如下。在 Beta 阶段,SELinuxMount
默认仍处于禁用状态。
在禁用 SELinuxMount
功能门控(Kubernetes 1.33 及任何之前版本的默认设置)的情况下,容器运行时默认会递归地为所有 Pod 卷中的所有文件分配 SELinux 标签。为了加快此过程,Kubernetes 可以通过使用挂载选项 -o context=<label>
立即更改卷的 SELinux 标签。
为了受益于这种加速,必须满足所有这些条件:
- 功能门控
SELinuxMountReadWriteOncePod
必须启用。 - Pod 必须使用具有适用
accessModes
和 功能门控 的 PersistentVolumeClaim- 要么卷具有
accessModes: ["ReadWriteOncePod"]
且功能门控SELinuxMountReadWriteOncePod
已启用。 - 或者卷可以使用任何其他访问模式,并且必须启用所有功能门控
SELinuxMountReadWriteOncePod
、SELinuxChangePolicy
和SELinuxMount
,同时 Pod 的spec.securityContext.seLinuxChangePolicy
必须为 nil(默认)或MountOption
。
- 要么卷具有
- Pod(或使用该 PersistentVolumeClaim 的所有容器)必须设置
seLinuxOptions
。 - 相应的 PersistentVolume 必须是以下之一:
- 使用遗留的树内
iscsi
、rbd
或fc
卷类型的卷。 - 或者使用 CSI 驱动的卷。CSI 驱动必须通过在其 CSIDriver 实例中设置
spec.seLinuxMount: true
来声明支持使用-o context
挂载。
- 使用遗留的树内
如果未满足任何这些条件,SELinux 将通过另一种方式重新打标签:容器运行时将递归地更改卷中所有 inode(文件和目录)的 SELinux 标签。明确地说,这适用于 Kubernetes 临时卷,例如 secret
、configMap
和 projected
,以及其 CSIDriver 实例未显式声明支持使用 -o context
挂载的所有卷。
当使用这种加速时,同一节点上同时使用同一适用卷的所有 Pod 必须具有相同的 SELinux 标签。具有不同 SELinux 标签的 Pod 将无法启动,并且将处于 ContainerCreating
状态,直到所有使用该卷且具有其他 SELinux 标签的 Pod 被删除。
Kubernetes v1.33 [beta]
(默认启用:true)spec.securityContext.seLinuxChangePolicy
设置为 Recursive
。当多个 Pod 在同一节点上共享单个卷,但它们以允许同时访问卷的不同 SELinux 标签运行时,这是必需的。例如,一个以标签 spc_t
运行的特权 Pod 和一个以默认标签 container_file_t
运行的非特权 Pod。在未设置 spec.securityContext.seLinuxChangePolicy
(或使用默认值 MountOption
)的情况下,只有一个这样的 Pod 能够在节点上运行,另一个将因错误 conflicting SELinux labels of volume <name of the volume>: <label of the running pod> and <label of the pod that can't start>
而处于 ContainerCreating 状态。SELinuxWarningController
为了更容易地识别受 SELinux 卷重新标记变化影响的 Pod,kube-controller-manager 中引入了一个新的控制器,名为 SELinuxWarningController
。该控制器默认禁用,可以通过设置 --controllers=*,selinux-warning-controller
命令行标志 来启用,或者通过设置 KubeControllerManagerConfiguration 中的 genericControllerManagerConfiguration.controllers
字段 来启用。此控制器需要启用 SELinuxChangePolicy
特性门控。
启用后,该控制器会观察正在运行的 Pod,并在检测到两个 Pod 使用同一个卷但具有不同的 SELinux 标签时,
- 它会向这两个 Pod 发出事件。
kubectl describe pod <pod-name>
将显示SELinuxLabel "<pod 上的标签>" conflicts with pod <另一个 pod 的名称> that uses the same volume as this pod with SELinuxLabel "<另一个 pod 上的标签>". If both pods land on the same node, only one of them may access the volume
。 - 提升
selinux_warning_controller_selinux_volume_conflict
指标。该指标包含 Pod 名称和命名空间作为标签,以便轻松识别受影响的 Pod。
集群管理员可以使用此信息来识别受计划变更影响的 Pod,并主动选择退出 Pod 的优化(即设置 spec.securityContext.seLinuxChangePolicy: Recursive
)。
警告
我们强烈建议使用 SELinux 的集群启用此控制器,并在启用SELinuxMount
特性门控或升级到默认启用 SELinuxMount
的版本之前,确保 selinux_warning_controller_selinux_volume_conflict
指标没有报告任何冲突。特性门控
以下特性门控控制 SELinux 卷重新标记的行为
SELinuxMountReadWriteOncePod
: 为accessModes: ["ReadWriteOncePod"]
的卷启用优化。这是一个非常安全的特性门控,因为使用此访问模式的两个 Pod 不可能共享同一个卷。此特性门控自 v1.28 起默认启用。SELinuxChangePolicy
: 启用 Pod 中的spec.securityContext.seLinuxChangePolicy
字段以及 kube-controller-manager 中相关的 SELinuxWarningController。可以在启用SELinuxMount
之前使用此特性来检查集群上运行的 Pod,并主动选择退出 Pod 的优化。此特性门控需要启用SELinuxMountReadWriteOncePod
。它是 Beta 阶段的,在 1.33 版本中默认启用。SELinuxMount
: 为所有符合条件的卷启用优化。由于这可能会破坏现有的工作负载,我们建议首先启用SELinuxChangePolicy
特性门控 + SELinuxWarningController 来检查变更的影响。此特性门控需要启用SELinuxMountReadWriteOncePod
和SELinuxChangePolicy
。它是 Beta 阶段的,但在 1.33 版本中默认禁用。
管理对 /proc
文件系统的访问
Kubernetes v1.31 [beta]
(默认启用:false)对于遵循 OCI 运行时规范的运行时,容器默认以一种模式运行,其中有多个路径是既被屏蔽又只读的。其结果是容器在其挂载命名空间内存在这些路径,并且其功能类似于容器是隔离主机的情况,但容器进程无法写入它们。被屏蔽和只读的路径列表如下:
被屏蔽的路径
/proc/asound
/proc/acpi
/proc/kcore
/proc/keys
/proc/latency_stats
/proc/timer_list
/proc/timer_stats
/proc/sched_debug
/proc/scsi
/sys/firmware
/sys/devices/virtual/powercap
只读路径
/proc/bus
/proc/fs
/proc/irq
/proc/sys
/proc/sysrq-trigger
对于某些 Pod,您可能希望绕过这些路径的默认屏蔽。最常见的使用场景是当您尝试在 Kubernetes 容器(Pod 内)中运行容器时。
securityContext
字段 procMount
允许用户请求容器的 /proc
是 Unmasked
(未屏蔽的),或者被容器进程挂载为读写。这也适用于 /sys/firmware
,它不在 /proc
中。
...
securityContext:
procMount: Unmasked
注意
将procMount
设置为 Unmasked 需要 Pod 规约中的 spec.hostUsers
值为 false
。换句话说:希望拥有 Unmasked 的 /proc
或未屏蔽的 /sys
的容器也必须位于 用户命名空间 中。Kubernetes v1.12 到 v1.29 版本没有强制执行此要求。讨论
Pod 的安全上下文适用于 Pod 的容器,并在适用时也适用于 Pod 的卷。具体来说,fsGroup
和 seLinuxOptions
按如下方式应用于卷:
fsGroup
: 支持所有权管理的卷会被修改,使其归fsGroup
中指定的 GID 所有并可写。更多详细信息请参阅所有权管理设计文档。seLinuxOptions
: 支持 SELinux 标签的卷会被重新标记,以便可以通过seLinuxOptions
下指定的标签进行访问。通常,您只需要设置level
部分。这会设置分配给 Pod 中所有容器以及卷的 多类别安全 (MCS) 标签。
警告
为 Pod 指定 MCS 标签后,所有具有相同标签的 Pod 都可以访问该卷。如果需要 Pod 间的保护,必须为每个 Pod 分配唯一的 MCS 标签。清理
删除 Pod
kubectl delete pod security-context-demo
kubectl delete pod security-context-demo-2
kubectl delete pod security-context-demo-3
kubectl delete pod security-context-demo-4
下一步
- PodSecurityContext
- SecurityContext
- CRI 插件配置指南
- 安全上下文设计文档
- 所有权管理设计文档
- PodSecurity 准入
- AllowPrivilegeEscalation 设计文档
- 有关 Linux 中安全机制的更多信息,请参阅Linux 内核安全特性概述(注意:某些信息已过期)
- 阅读关于 Linux Pod 的用户命名空间。
- OCI 运行时规范中的被屏蔽路径
此页面上的项目引用了提供 Kubernetes 所需功能的第三方产品或项目。Kubernetes 项目作者不对这些第三方产品或项目负责。更多详细信息请参阅CNCF 网站指南。
在提议添加额外的第三方链接的更改之前,您应该阅读内容指南。