containerd传递错误宿主机hostPath导致K8s Pod创建失败
问题根因
该报错是OCI运行时执行容器挂载操作时找不到待挂载源文件导致,和猜测的containerd config.toml配置问题关联度极低,最高概率的触发原因有三类:
- 配置hostPath卷时subPath路径书写错误,多写/错写了路径层级。从贴出的报错可以看到,预期挂载的源文件位于临时运行时目录的
host_dir/config/services-config.json路径,但实际执行stat查找的路径多了一级service/目录,和subPath配置错误的特征完全吻合。 - hostPath指定的宿主机源文件/目录不存在。注意:hostPath如果配置type为File/Directory,kubelet不会自动创建对应路径,必须提前在宿主机上创建好;即便是配置FileOrCreate,也只会创建目标空文件,不会自动创建父目录,父目录不存在同样会触发挂载失败。
- 宿主机SELinux拦截或路径权限不足。containerd 1.5版本在SELinux开启状态下,如果hostPath路径没有打正确的容器可读标签,shim进程访问路径时会被拦截,返回的错误信息和文件不存在完全一致,容易误导排查方向。
排查解决步骤
- 第一步:核对Deployment资源YAML配置
- 检查
volumes.hostPath段配置:确认path字段填写的宿主机路径真实存在,路径下的待挂载文件位置正确;如果要自动创建路径,将type设置为DirectoryOrCreate(目录场景)或FileOrCreate(文件场景),注意提前手动创建好所有父目录。 - 检查
volumeMounts段配置:重点核对subPath字段的路径值,不要多写、错写目录层级。举个正确配置示例:如果宿主机hostPath路径为/data/host_dir,要将路径下的config/services-config.json挂载到容器内/app/config/local.json,subPath就应该写config/services-config.json,如果手滑写为service/config/services-config.json就会触发当前遇到的报错。
- 检查
- 第二步:排查宿主机权限与SELinux拦截
- 临时关闭SELinux测试:在Pod调度到的节点上执行
setenforce 0,删除旧的失败Pod触发重新调度,如果Pod能正常启动,说明是SELinux标签问题,给hostPath对应路径打标签即可:chcon -Rt container_file_t <你的hostPath宿主机完整路径>,打标完成后执行setenforce 1重新开启SELinux即可。 - 检查路径权限:执行
ls -l <待挂载的宿主机文件完整路径>,确认root用户(containerd和kubelet默认运行用户)对该文件有读权限,权限位不足的话执行chmod 644 <文件路径>调整。
- 临时关闭SELinux测试:在Pod调度到的节点上执行
- 第三步:低概率问题排查(仅当前两步无效时操作)
- 检查containerd运行时目录状态:默认containerd状态目录为
/run/containerd,执行df -h /run/containerd确认目录所在磁盘没有被占满,如果使用率100%清理目录下的过期临时文件即可。 - 核对containerd配置:打开
/etc/containerd/config.toml,确认state字段配置为/run/containerd,没有配置错误的挂载拦截规则,修改配置后执行systemctl restart containerd重启服务生效。
- 检查containerd运行时目录状态:默认containerd状态目录为
结果验证
配置修复完成后,删除原有失败的Pod,等待Deployment控制器重新拉起新Pod,执行kubectl describe pod <新Pod名称>确认没有挂载相关报错,再执行kubectl exec <新Pod名称> -- ls -l /app/config/local.json确认文件正常挂载即可。
内容的提问来源于stack exchange,提问作者functionX
相关产品推荐
相关产品推荐

