bigywater.tech
Kubernetes · 88

securityContext:runAsUser、fsGroup 与 capabilities

securityContext 里这些字段到底改变了进程的什么?fsGroup 为什么能让卷里的文件有一个固定的组?默认容器有哪些 Linux 能力?runAsNonRoot 是切换用户还是检查?这篇逐个实验,把 id、能力位和文件权限都读出来。

14 / 0 / 15 / 41
默认、drop ALL、add NET_ADMIN、privileged 四种配置下容器的 Linux 能力个数
2777 root:2000
设置 fsGroup: 2000 后 emptyDir 的权限与属组(setgid 位让新文件继承组)
CreateContainerConfigError
runAsNonRoot: true 遇到默认 root 镜像时的容器状态

用户、组与卷的属组

实测 · 本机执行输出
  Pod default:id → uid=0(root) gid=0(root) groups=0(root),10(wheel);emptyDir /data 的权限 → 777 root:root (uid:gid=0:0)
    在 /data 里新建文件:644 0:0;进程 /proc/1/status 的 Groups:Groups:	0 10
  Pod user:id → uid=1000 gid=3000 groups=2000,3000,4000,5000;emptyDir /data 的权限 → 2777 root:UNKNOWN (uid:gid=0:2000)
    在 /data 里新建文件:644 1000:2000;进程 /proc/1/status 的 Groups:Groups:	2000 3000 4000 5000

默认 Pod:id 是 uid=0(root),emptyDir /data 是 777 root:root。设置 runAsUser: 1000、runAsGroup: 3000、fsGroup: 2000、supplementalGroups: [4000, 5000]:id 变成 uid=1000 gid=3000 groups=2000,3000,4000,5000;/data 变成 2777 root:2000(2 是 setgid 位,组是 fsGroup);在里面新建的文件属于 1000:2000,继承了目录的组;/proc/1/status 的 Groups 是 2000 3000 4000 5000。

Linux 能力

实测 · 本机执行输出
  caps-default:CapEff=00000000a80425fb → 14 个:['CHOWN', 'DAC_OVERRIDE', 'FOWNER', 'FSETID', 'KILL', 'SETGID', 'SETUID', 'SETPCAP', 'NET_BIND_SERVICE', 'NET_RAW', 'SYS_CHROOT', 'MKNOD', 'AUDIT_WRITE', 'SETFCAP']
  caps-drop:CapEff=0000000000000000 → 0 个:[]
  caps-add:CapEff=00000000a80435fb → 15 个:['CHOWN', 'DAC_OVERRIDE', 'FOWNER', 'FSETID', 'KILL', 'SETGID', 'SETUID', 'SETPCAP', 'NET_BIND_SERVICE', 'NET_ADMIN', 'NET_RAW', 'SYS_CHROOT', 'MKNOD', 'AUDIT_WRITE', 'SETFCAP']
  caps-priv:CapEff=000001ffffffffff → 41 个:(几乎全部,41 个里的 41 个)
  default 里 chown 别人的文件:成功;drop ALL 里:chown: /tmp/x: Operation not permitted
  default 里创建网卡 ip link add:ip: RTNETLINK answers: Operation not permitted;add NET_ADMIN 里:成功
  privileged 里 mount tmpfs:成功;default 里:mount: permission denied (are you root?)
  非 root(uid 1000)+ drop ALL,监听 80 端口:nc 退出码 143(nc 退出码 143 表示被 timeout 终止=监听成功;1 才是失败)
    该节点上 net.ipv4.ip_unprivileged_port_start=0(容器运行时把它设成了 0,所以不需要 NET_BIND_SERVICE)

读 /proc/1/status 的 CapEff 并解码:默认容器 14 个能力(CHOWN、DAC_OVERRIDE、FOWNER、FSETID、KILL、SETGID、SETUID、SETPCAP、NET_BIND_SERVICE、NET_RAW、SYS_CHROOT、MKNOD、AUDIT_WRITE、SETFCAP);drop: [ALL] 后是 0 个;add: [NET_ADMIN] 多出 NET_ADMIN 共 15 个;privileged: true 是全部 41 个。验证:默认里 chown 成功,drop ALL 里 Operation not permitted;默认里 ip link add 被拒,add NET_ADMIN 里成功;privileged 里能 mount tmpfs,默认里 permission denied。非 root(uid 1000)+ drop ALL 监听 80 端口也成功:节点上 net.ipv4.ip_unprivileged_port_start=0,所以不需要 NET_BIND_SERVICE。

防提权与只读根

实测 · 本机执行输出
  默认:NoNewPrivs=0;allowPrivilegeEscalation=false:NoNewPrivs=1
  readOnlyRootFilesystem:写 /tmp → touch: /tmp/x: Read-only file system;写挂载的卷 /data → 成功

allowPrivilegeEscalation: false 让进程的 NoNewPrivs 从 0 变成 1(setuid 程序不能再提权)。readOnlyRootFilesystem: true 之后,写 /tmp 报 Read-only file system,但挂载的卷 /data 仍可写——只读的是镜像层的根文件系统,要写的目录得挂卷。

runAsNonRoot

实测 · 本机执行输出
  runAsNonRoot: true,但 busybox 镜像默认是 root:phase=Pending;容器状态 CreateContainerConfigError:container has runAsNonRoot and image will run as root (pod: "nonroot_k82(3897fb6e-76ee-4c6e-a7eb-e00a6436d7d8)", contain
  runAsNonRoot: true + runAsUser: 1000:phase=Running;id → uid=1000 gid=0(root) groups=0(root)

runAsNonRoot: true 遇到默认 root 用户的 busybox 镜像:Pod 卡在 Pending,容器状态 CreateContainerConfigError,message 是 container has runAsNonRoot and image will run as root。它是检查而不是切换用户。再加 runAsUser: 1000 就能 Running,id 是 uid=1000 gid=0(root) groups=0(root)。

分步演示

securityContext
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / kind(Docker 里的单节点或多节点真实集群,节点是 Docker Desktop 虚拟机里的容器)/ kubectl;用空的 kubeconfig 之外的独立 kubeconfig,不碰用户自己的集群;计时用 date +%s%N / kubectl 事件时间戳,数字每次运行会有小幅抖动。三节点 kind 集群 kx-main(Kubernetes v1.37.0,containerd v2.3.4 默认能力集);容器是 busybox:1.36;能力位解码用 CAP_* 名字表(0~40),CapEff 取自容器里 /proc/1/status;各验证命令用 kubectl exec 执行;每种情形各一次
    • 没有验证:fsGroupChangePolicy: OnRootMismatch 对大卷的影响;seccompProfile 与 AppArmor / SELinux;sysctls 的安全/不安全分类;appArmorProfile 字段;supplementalGroupsPolicy;Windows 的 securityContext;ambient / inheritable / bounding 能力集的细节;能力在 setuid 程序上的交互
    京ICP备2026067502号-1京公网安备11010502063487号