为 Pod 或容器配置安全上下文

安全上下文定义了 Pod 或容器的特权和访问控制设置。安全上下文设置包括但不限于:

  • 自主访问控制 (DAC):访问对象(如文件)的权限基于 用户 ID (UID) 和组 ID (GID)

  • 安全增强型 Linux (SELinux):对象被分配了安全标签。

  • 以特权或非特权方式运行。

  • Linux 能力 (Capabilities):赋予进程某些特权,但并非 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 中的所有容器。以下是一个包含 securityContextemptyDir 卷的 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 字段相同。如果省略了 runAsGroupgid 将保持为 0 (root),并且该进程将能够与归 root(0) 组所有以及具有 root(0) 组所需权限的组的文件进行交互。您还可以看到 groups 除了包含 gid 外,还包含了由 fsGroupsupplementalGroups 指定的组 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 安全上下文包含 runAsUserrunAsGroupsupplementalGroups。但是,您可以看到连接到容器进程的实际补充组将包括来自容器镜像中 /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](默认启用)

可以通过为 kubelet 和 kube-apiserver 设置 SupplementalGroupsPolicy 特性门控,并为 Pod 设置 .spec.securityContext.supplementalGroupsPolicy 字段来启用此特性。

supplementalGroupsPolicy 字段定义了用于计算 Pod 中容器进程的补充组的策略。此字段有两个有效值:

  • Merge:将容器主要用户在 /etc/group 中定义的组成员身份进行合并。如果未指定,这是默认策略。

  • Strict:仅将 fsGroupsupplementalGroupsrunAsGroup 字段中的组 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) 等),容器进程可以更改其身份。因此,实际的进程身份将是动态的。

实现

注意: 本节链接到提供 Kubernetes 所需功能的第三方项目。Kubernetes 项目作者不对这些项目负责,项目按字母顺序排列。要将项目添加到此列表,请在提交更改之前阅读 内容指南更多信息。

已知以下容器运行时支持细粒度的 SupplementalGroups 控制。

CRI 级别

您可以在节点状态中查看是否支持该特性。

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 [稳定]

默认情况下,当挂载卷时,Kubernetes 会递归地更改每个卷内容的所有权和权限,以匹配 Pod 的 securityContext 中指定的 fsGroup。对于大容量卷,检查和更改所有权和权限可能非常耗时,从而导致 Pod 启动变慢。您可以使用 securityContext 中的 fsGroupChangePolicy 字段来控制 Kubernetes 检查和管理卷所有权和权限的方式。

fsGroupChangePolicy - fsGroupChangePolicy 定义了在 Pod 内挂载卷之前更改所有权和权限的行为。此字段仅适用于支持 fsGroup 控制所有权和权限的卷类型。此字段有两个可能的值:

  • OnRootMismatch:仅在根目录的权限和所有权与卷的预期权限和所有权不匹配时,才更改权限和所有权。这有助于缩短更改卷所有权和权限所需的时间。
  • Always:挂载卷时总是更改卷的权限和所有权。

例如

securityContext:
  runAsUser: 1000
  runAsGroup: 3000
  fsGroup: 2000
  fsGroupChangePolicy: "OnRootMismatch"

说明

此字段对诸如 secretconfigMapemptyDir 等临时卷类型没有影响。

将卷权限和所有权变更委派给 CSI 驱动程序

功能状态: Kubernetes v1.26 [稳定]

如果您部署了一个支持 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

为容器设置能力 (Capabilities)

通过 Linux 能力 (Capabilities),您可以授予进程某些特权,而不必授予 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_ADMINCAP_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 配置文件

要设置容器的 Seccomp 配置文件,请在 Pod 或容器清单的 securityContext 部分中包含 seccompProfile 字段。seccompProfile 字段是一个 SeccompProfile 对象,由 typelocalhostProfile 组成。type 的有效选项包括 RuntimeDefaultUnconfinedLocalhost。仅当 type: Localhost 时才必须设置 localhostProfile。它表示节点上预配置配置文件的路径,相对于 kubelet 配置的 Seccomp 配置文件位置(通过 --root-dir 标志配置)。

以下是将 Seccomp 配置文件设置为节点容器运行时默认配置文件的示例:

...
securityContext:
  seccompProfile:
    type: RuntimeDefault

以下是将 Seccomp 配置文件设置为 <kubelet-root-dir>/seccomp/my-profiles/profile-allow.json 处预配置文件的示例:

...
securityContext:
  seccompProfile:
    type: Localhost
    localhostProfile: my-profiles/profile-allow.json

为容器设置 AppArmor 配置文件

要为容器设置 AppArmor 配置文件,请在容器的 securityContext 部分中包含 appArmorProfile 字段。appArmorProfile 字段是一个 AppArmorProfile 对象,由 typelocalhostProfile 组成。type 的有效选项包括 RuntimeDefault(默认)、UnconfinedLocalhost。仅当 typeLocalhost 时才必须设置 localhostProfile。它表示节点上预配置配置文件的名称。该配置文件需要加载到所有适合 Pod 的节点上,因为您不知道 Pod 将被调度到哪里。设置自定义配置文件的方法在 设置具有配置文件的节点 中进行了讨论。

注意:如果 containers[*].securityContext.appArmorProfile.type 被明确设置为 RuntimeDefault,那么如果节点上未启用 AppArmor,Pod 将无法被准入。但是,如果未指定 containers[*].securityContext.appArmorProfile.type,则仅在节点启用 AppArmor 时才会应用默认值(也是 RuntimeDefault)。如果节点禁用了 AppArmor,Pod 将被准入,但容器不会受到 RuntimeDefault 配置文件的限制。

以下是将 AppArmor 配置文件设置为节点容器运行时默认配置文件的示例:

...
containers:
- name: container-1
  securityContext:
    appArmorProfile:
      type: RuntimeDefault

以下是将 AppArmor 配置文件设置为名为 k8s-apparmor-example-deny-write 的预配置配置文件的示例:

...
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.36 [stable](默认启用)

说明

Kubernetes v1.27 引入了一种早期的受限行为,仅适用于使用 ReadWriteOncePod 访问模式的卷(以及 PersistentVolumeClaims)。

Kubernetes v1.36 将 SELinuxChangePolicySELinuxMount 特性门控 提升为 GA,以将该性能改进扩展到其他类型的 PersistentVolumeClaims,详见下文。SELinuxMount 默认仍处于禁用状态。

SELinuxMount 特性门控被禁用的情况下(Kubernetes 1.36 及之前版本的默认设置),容器运行时默认会递归地为所有 Pod 卷上的所有文件分配 SELinux 标签。为了加速此过程,Kubernetes 可以通过使用挂载选项 -o context=<label> 立即更改卷的 SELinux 标签。

要从这种加速中受益,必须满足以下所有条件:

  • Pod 必须使用带有适用 accessModes特性门控 的 PersistentVolumeClaim。
    • 要么卷具有 accessModes: ["ReadWriteOncePod"]
    • 要么卷可以使用任何其他访问模式,并且启用了 SELinuxMount 特性门控,且 Pod 的 spec.securityContext.seLinuxChangePolicy 为 nil(默认)或 MountOption
  • Pod(或使用该 PersistentVolumeClaim 的所有容器)必须设置了 seLinuxOptions
  • 相应的 PersistentVolume 必须是以下之一:
    • 使用旧式树内 (in-tree) iscsirbdfc 卷类型的卷。
    • 或使用 CSI 驱动程序的卷。CSI 驱动程序必须通过在其 CSIDriver 实例中设置 spec.seLinuxMount: true 来声明其支持使用 -o context 进行挂载。

当不满足上述任何条件时,SELinux 重打标签将以另一种方式发生:容器运行时递归地更改卷中所有 inode(文件和目录)的 SELinux 标签。明确指出,这适用于 Kubernetes 临时卷(如 secretconfigMapprojected)以及所有其 CSIDriver 实例未明确声明使用 -o context 进行挂载的卷。

当使用此加速时,在同一节点上同时使用相同适用卷的所有 Pod 必须具有相同的 SELinux 标签。具有不同 SELinux 标签的 Pod 将无法启动,并会处于 ContainerCreating 状态,直到删除所有使用该卷且具有不同 SELinux 标签的 Pod 为止。

特性状态: Kubernetes v1.36 [stable](默认启用)
对于希望选择不使用挂载选项进行重打标签的 Pod,可以将 spec.securityContext.seLinuxChangePolicy 设置为 Recursive。当多个 Pod 在同一节点上共享单个卷,但它们运行的 SELinux 标签允许同时访问该卷时,这是必需的。例如,运行在标签 spc_t 下的特权 Pod 和运行在默认标签 container_file_t 下的非特权 Pod。当 spec.securityContext.seLinuxChangePolicy 未设置(或使用默认值 MountOption)时,此类 Pod 中只有一个能够在节点上运行,另一个会因 conflicting SELinux labels of volume <卷名>: <运行中 Pod 的标签> and <无法启动的 Pod 的标签> 错误而处于 ContainerCreating 状态。

SELinuxWarningController

为了更容易识别受 SELinux 卷重打标签变更影响的 Pod,kube-controller-manager 中引入了一个名为 SELinuxWarningController 的新控制器。它默认禁用,可以通过设置 --controllers=*,selinux-warning-controller 命令行标志,或在 KubeControllerManagerConfiguration 中设置 genericControllerManagerConfiguration.controllers 字段 来启用。此控制器要求启用 SELinuxChangePolicy 特性门控。

启用后,该控制器会观察正在运行的 Pod,当它检测到两个 Pod 使用相同的卷且具有不同的 SELinux 标签时:

  1. 它会向两个 Pod 发出事件。kubectl describe pod <pod名> 显示 SELinuxLabel "<Pod上的标签>" 与使用相同卷且带有 SELinuxLabel "<另一个Pod的标签>" 的 Pod <另一个Pod名> 冲突。如果两个 Pod 落在同一节点上,只有一个 Pod 可以访问该卷
  2. 上报 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 共享一个卷的情况。此特性门控自 1.28 起默认启用,并在 1.36 中达到 GA。
  • SELinuxChangePolicy:在 Pod 中启用 spec.securityContext.seLinuxChangePolicy 字段,并在 kube-controller-manager 中启用相关的 SELinuxWarningController。此特性可在启用 SELinuxMount 之前用于检查集群上运行的 Pod,并主动让 Pod 选择不使用该优化。此特性门控要求启用 SELinuxMountReadWriteOncePod。它是 beta 版本,自 1.33 起默认启用,在 1.36 中达到 GA。
  • SELinuxMount:为所有符合条件的卷启用此优化。由于它可能会破坏现有工作负载,我们建议先启用 SELinuxChangePolicy 特性门控 + SELinuxWarningController 来检查变更的影响。此特性门控要求启用 SELinuxMountReadWriteOncePodSELinuxChangePolicy。它是 beta 版本,但在 1.33 中默认禁用。

管理对 `/proc` 文件系统的访问

特性状态: Kubernetes v1.36 [stable](默认启用)

对于遵循 OCI 运行时规范的运行时,容器默认以一种存在多个被屏蔽 (masked) 且只读路径的模式运行。结果是,容器在容器的挂载命名空间内存在这些路径,它们的功能类似于容器是一个隔离的主机,但容器进程无法写入它们。屏蔽和只读路径列表如下:

  • 屏蔽路径

    • /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,或者将其挂载为容器进程可读写。这也适用于不在 /proc 中的 /sys/firmware

...
securityContext:
  procMount: Unmasked

说明

procMount 设置为 Unmasked 需要 Pod 规范中的 spec.hostUsers 值为 false。换句话说:希望拥有 Unmasked /proc 或 unmasked /sys 的容器也必须处于 用户命名空间 中。Kubernetes v1.12 到 v1.29 未强制执行此要求。

讨论

Pod 的安全上下文适用于 Pod 的容器,并在适用时也适用于 Pod 的卷。具体来说,fsGroupseLinuxOptions 在卷上的应用方式如下:

  • 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

接下来


最后修改时间 2026 年 2 月 23 日下午 1:46 PST:将初始 SELinuxMount 特性升级为 GA (62fd05556d)

此页面上的项目涉及提供 Kubernetes 所需功能的第三方产品或项目。Kubernetes 项目作者不对这些第三方产品或项目负责。有关详细信息,请参阅 CNCF 网站指南

在提出添加额外的第三方链接的更改之前,您应该阅读 内容指南