CreateContainer 卡在 WaitForAttach 是因 CSI 卷挂载误判:Pod 未定义 volumeMounts 或 hostPath.type 为空,导致 runtime 错误等待 attach;需检查 volumes 合法性、hostPath.type 显式设置,并确认 runtime 未全局启用 unsafe IO。

ContainerRuntime 接口调用时为什么 CreateContainer 总卡在 WaitForAttach?
因为底层 runtime(比如 containerd)默认等待 CSI 插件完成卷挂载,但你的 Pod 没定义 volumeMounts 或用了 hostPath 却没配 hostPath.type,导致 attach 阶段误判为需要等待。
- 检查
Pod.spec.volumes是否存在且类型合法;hostPath 必须显式设type: DirectoryOrCreate等,空值会触发 attach 流程 - 若确实无需卷,确认 runtime 配置里没全局开启
enable_unsafe_io或类似 hook,某些定制版 containerd 会强制注入 attach 步骤 -
ctr -n k8s.io containers list查看容器状态是否卡在CREATING;再用ctr -n k8s.io tasks ls看对应 task 是否 pending —— pending 就说明还没进 OCI runtime exec 阶段
containerd 中 runtime.v1.RuntimeService.CreateContainer 实际触发哪几个关键步骤?
它不是直通 runc,而是分三段:先由 containerd-shim 创建 sandbox 容器(pause 进程),再调 oci.Create 写 config.json 和 rootfs,最后才调 runc create。中间任一环失败都会让上层报 Failed to create container 而非具体错误。
- config.json 生成依赖
RuntimeOptions(如systemd_cgroup = true),错配会导致 runc 启动时报invalid argument,但 containerd 日志只记failed to create container - sandbox 容器未就绪时,
CreateContainer会阻塞在WaitSandboxReady—— 不是 bug,是设计行为,可通过ctr -n k8s.io tasks ps <sid></sid>确认 pause 进程是否已 running - OCI spec 中
linux.resources.memory.limit_bytes设为 0 表示不限制,但某些老版本 runc 会拒绝该值,需设为-1或明确数值
为什么 runc create --bundle 成功,但 containerd 调用 CreateContainer 却报 no such file or directory?
路径问题。containerd 默认把 bundle 解压到 /run/containerd/io.containerd.runtime.v2.task/k8s.io/<id>/rootfs</id>,而你手动测试时用的 bundle 是相对路径或挂载点不在预期位置。
- 务必确认
rootfs.path在 OCI config.json 中是绝对路径,且 containerd 进程有读权限(尤其 SELinux 启用时,ls -Z看上下文是否匹配container_file_t) - 不要复用
docker export出来的 tar 包——它缺config.json或格式不兼容 v1.0.0+ OCI 规范;要用ctr images export或crictl pull + crictl inspect拿标准 bundle - containerd 的
root配置项(如/var/lib/containerd)决定了所有 runtime 数据存放位置,改过这个值后,ctr命令必须加--address指向对应 socket,否则找不到 bundle
Kubernetes 调 RuntimeService.CreateContainer 时传的 LinuxContainerConfig 哪些字段会被忽略?
containerd 会直接丢弃 LinuxContainerConfig.security_context 里的大部分字段,包括 seccomp_profile(除非启用 seccomp plugin)、apparmor_profile(需加载 apparmor parser)、proc_mount(v1.6+ 才支持)。
-
security_context.capabilities.add有效,但drop列表若含ALL,containerd 会静默转成默认 drop-list,不会报错 -
linux_container_config.resources中的hugepage_limits只在 cgroup v2 + kernel ≥5.11 下生效,低版本直接跳过,不提示 -
annotations字段全量透传给 shim,但只有以io.kubernetes.开头的才会被 kubelet 解析;其他自定义注解得靠自己写 shim plugin 拦截
真正难调试的是 shim 层对 OCI spec 的二次解释 —— 比如 systemd cgroup driver 下,cgroups_path 会被重写成 /kubepods.slice/kubepods-burstable.slice/...,但日志里从不打印这个重写结果。

















