Kubernetes 1.24+Containerd:无需--privileged让容器访问指定设备?
问题
我们近期将AWS EKS集群升级至Kubernetes 1.24版本,现有一个使用volumeDevices的Kubernetes Job工作负载,清单如下:
apiVersion: batch/v1 kind: Job metadata: name: test-vol-05ca32fbf6a015b50 spec: template: metadata: spec: containers: - env: - name: AWS_STS_REGIONAL_ENDPOINTS value: legacy - name: DevicePath value: /dev/xvdf - name: DeviceRootPartitionMountPath value: /data image: ****.dkr.ecr.us-east-2.amazonaws.com/engeksserviceimageoutpostworkerrepository:1.59.76.8053 securityContext: capabilities: add: - SYS_ADMIN seccompProfile: localhostProfile: compute-analysis-scanning type: Localhost volumeDevices: - devicePath: /dev/xvdf name: test-vol-05ca32fbf6a015b50 restartPolicy: Never volumes: - name: test-vol-05ca32fbf6a015b50 persistentVolumeClaim: claimName: test-vol-05ca32fbf6a015b50 ttlSecondsAfterFinished: 300
挂载的/dev/xvdf是远程机器的卷,已分区并格式化为ext4/ext3/xfs等文件系统,容器启动后执行命令:
lsblk -fnr -o NAME,FSTYPE /dev/xvdf
预期输出应显示分区及对应文件系统类型:
nvme2n1 nvme2n1p1 ext4 nvme2n1p14 nvme2n1p15 vfat
但实际输出未显示文件系统类型:
nvme1n1 nvme1n1p1 nvme1n1p14 nvme1n1p15
通过strace发现错误:
open("/dev/nvme1n1", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) getuid() = 0 open("/dev/nvme1n1p14", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) getuid() = 0 open("/dev/nvme1n1p1", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) getuid() = 0 open("/dev/nvme1n1p15", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
目前发现容器根文件系统的/dev和/sys路径被屏蔽,仅设置--privileged=true可解除,但我们希望采用类似Docker --device的最小权限方案,请问能否通过Kubernetes清单配置实现指定设备的访问?
解决方案
可以通过Kubernetes的securityContext配置实现最小权限的设备访问,无需启用全特权模式,具体调整方案如下:
方案1:直接使用securityContext.devices字段(Kubernetes 1.23+)
Kubernetes 1.23及以上版本支持在容器securityContext中直接配置devices字段,效果等价于Docker的--device参数,无需额外挂载卷,配置更简洁:
securityContext: capabilities: add: - SYS_ADMIN - DAC_READ_SEARCH # 补充权限,帮助读取文件系统元数据 seccompProfile: localhostProfile: compute-analysis-scanning type: Localhost devices: - path: /dev/nvme1n1 cgroupPermissions: rwm # 授予读写权限 - path: /dev/nvme1n1p1 cgroupPermissions: rwm - path: /dev/nvme1n1p14 cgroupPermissions: rwm - path: /dev/nvme1n1p15 cgroupPermissions: rwm
方案2:挂载主机特定设备节点
如果集群版本不支持devices字段,可通过hostPath卷挂载主机上的指定设备节点到容器/dev目录:
- 在Job的
volumes中添加主机设备卷:
volumes: # 保留原有的PVC卷 - name: test-vol-05ca32fbf6a015b50 persistentVolumeClaim: claimName: test-vol-05ca32fbf6a015b50 # 添加需要访问的设备节点卷 - name: dev-nvme1n1 hostPath: path: /dev/nvme1n1 type: CharDevice - name: dev-nvme1n1p1 hostPath: path: /dev/nvme1n1p1 type: CharDevice - name: dev-nvme1n1p14 hostPath: path: /dev/nvme1n1p14 type: CharDevice - name: dev-nvme1n1p15 hostPath: path: /dev/nvme1n1p15 type: CharDevice
- 在容器的
volumeMounts中挂载这些设备到容器/dev目录:
containers: - # 原容器其他配置不变 volumeMounts: - name: dev-nvme1n1 mountPath: /dev/nvme1n1 - name: dev-nvme1n1p1 mountPath: /dev/nvme1n1p1 - name: dev-nvme1n1p14 mountPath: /dev/nvme1n1p14 - name: dev-nvme1n1p15 mountPath: /dev/nvme1n1p15
- 补充必要权限:
在securityContext中添加DAC_READ_SEARCH能力,确保容器能读取设备的文件系统元数据:
securityContext: capabilities: add: - SYS_ADMIN - DAC_READ_SEARCH seccompProfile: localhostProfile: compute-analysis-scanning type: Localhost
额外检查
如果调整后仍无法读取文件系统类型,需检查自定义的compute-analysis-scanning seccomp配置文件,确保未限制对这些设备的open、ioctl等系统调用,必要时添加对应的允许规则。
内容的提问来源于stack exchange,提问作者ofir mamo
相关产品推荐
相关产品推荐

