下面把 device_ownership_from_security_context = true 的作用、原理、使用场景、风险与注意事项讲清楚
diff --git a/roles/container-engine/containerd/templates/config.toml.j2 b/roles/container-engine/containerd/templates/config.toml.j2
index 6bffae254..91e6803c3 100644
--- a/roles/container-engine/containerd/templates/config.toml.j2
+++ b/roles/container-engine/containerd/templates/config.toml.j2
@@ -33,6 +33,7 @@ oom_score = {{ containerd_oom_score }}
tolerate_missing_hugetlb_controller = {{ containerd_tolerate_missing_hugetlb_controller | lower }}
disable_hugetlb_controller = {{ containerd_disable_hugetlb_controller | lower }}
image_pull_progress_timeout = "{{ containerd_image_pull_progress_timeout }}"
+ device_ownership_from_security_context = true
{% if enable_cdi %}
enable_cdi = true
cdi_spec_dirs = ["/etc/cdi", "/var/run/cdi"]
结论(先说要点)
- 作用:让 containerd 在把主机上的设备节点(如
/dev/sdb、块设备或由 CDI / device-plugin 分配的设备)挂到容器时,把这些设备节点的所有权(UID/GID)设置为 Pod 的securityContext(runAsUser/runAsGroup)而不是保留主机上的 uid/gid。(Go Packages) - 为什么要用:允许 非 root(非 0 UID)容器安全地访问设备(例如 KubeVirt CDI 的块设备、某些 GPU / accelerator 用例),不需要容器以 root 启动去
chown。(Aerospike)
原理(发生了什么)
- kubelet/CRI 请求 containerd 把主机上的设备 bind-mount 到容器(或创建相应的设备节点)。
- containerd 在挂载/创建这些设备节点时,会根据该配置项 读取 Pod 的 securityContext(runAsUser/runAsGroup) ,并对设备节点做
chown(uid,gid),使设备在容器内可由该非 root 用户访问。否则设备会保留主机上的 uid/gid,容器内非 root 用户可能无法访问。(Go Packages)
典型使用场景
- KubeVirt CDI:导入块设备到 VM/容器,需要设备所有权匹配容器内用户,常把该项设为
true。(GitHub) - 非 root 容器访问物理设备(GPU / accelerators / block device workloads):避免容器以 root 启动只是为了做
chown。(Aerospike)
如何启用(示例)
在 config.toml 的 CRI 插件区块里加入/修改:
[plugins."io.containerd.grpc.v1.cri"]
...
device_ownership_from_security_context = true
保存后重启 containerd:
systemctl restart containerd
确保所有工作节点都统一修改(不一致会导致行为差异)。(Go Packages)
使用时的注意事项与风险(非常重要)
-
会改变主机设备节点的属主
- 这实际上会在主机上对
/dev下的设备节点做chown(或对被 bind 的设备节点影响宿主视图),可能影响其他进程/容器对该设备的访问。务必评估副作用。(GitHub)
- 这实际上会在主机上对
-
安全边界要谨慎
- 允许 containerd 根据 Pod 指定的 UID/GID 修改设备所有权,有潜在滥用 / 提权 的风险(例如恶意 Pod 请求设备并通过改变 owner 问题影响主机资源)。仅在信任工作负载或有适当审计/策略时启用。(Kubernetes)
-
需要 Pod 配置正确
- 必须在 Pod spec 中设置
securityContext.runAsUser/runAsGroup(或相同效果的 Pod-level securityContext),否则 containerd 不知道该用哪个 uid/gid。没有设置时行为取决于实现(可能仍为 root 或保持主机 owner)。(Go Packages)
- 必须在 Pod spec 中设置
-
版本要求
- 该选项在 CRI-O / containerd 的演进里逐步加入;请确保你的 containerd 版本支持它(文档提到 containerd v1.6.x 开始引入相关支持,某些发行版要求更高的补丁)。在启用前确认 containerd 版本与实现细节。(Aerospike)
-
可能导致节点行为异常
- 社区 issue 报告过在某些平台/配置下开启后会引发容器创建失败或非预期行为(例如 k3s/rke2 上的个别问题),因此先在测试节点验证再大规模 rollout。(GitHub)
推荐实践 / 验证步骤
- 在单台测试节点启用
device_ownership_from_security_context = true。 - 在该节点上部署一个带
runAsUser: 1000的 Pod,mount 一个已知设备(或用 CDI 测试块设备),确认容器内ls -l /dev/<device>的 uid/gid 为 1000。 - 检查主机上该设备的属主变化和其他进程是否受影响。
- 在 CI/集群中逐步 rollout,并确保节点间配置一致。
- 如果担心风险,结合 PodSecurityAdmission / admission webhook 策略限制哪些 Pod 能请求设备。(karpenter.sh)
对你 diff 中文本中 device_ownership_from_security_context = true 的总结
你在 roles/container-engine/containerd/templates/config.toml.j2 中新增该配置后,意思就是:你决定允许 containerd 按 Pod 的 securityContext(runAsUser/runAsGroup)为挂载进容器的设备设置属主(UID/GID) ,以便非 root 容器可以直接访问这些设备(例如 CDI 的块设备、某些设备插件分配的设备)。但同时你必须测试并评估上述安全 / 兼容性风险,并在所有节点上同样配置与重启 containerd。(Go Packages)
你想先要哪一个?