1. Kubernetes CreateContainerError 故障排查手册
遇到 Pod 卡在 CreateContainerError 状态?别慌,这通常是容器启动阶段的配置或环境问题。作为在 Kubernetes 生产环境摸爬滚打多年的老司机,我整理了这份最全排障指南,帮你快速定位和解决这类问题。
CreateContainerError 表示 Pod 已经完成调度,镜像通常也已拉取成功,但在最后一步 - 创建和启动容器进程时失败了。这与常见的 CrashLoopBackOff 不同,后者是容器能启动但应用进程崩溃。理解这个区别对高效排障至关重要。
2. 快速定位路径:10分钟高效排障法
2.1 第一步:查看 Events 获取关键线索
bash复制kubectl -n <ns> describe pod <pod-name>
重点关注 Events 部分的错误信息,这通常是问题的最直接体现。同时检查失败容器的 State、Last State 和 Reason 字段。
经验之谈:Events 中的错误信息往往比容器日志更有价值,因为容器可能还没来得及生成日志就挂了。
2.2 第二步:检查容器日志(含 previous)
bash复制kubectl -n <ns> logs <pod-name> -c <container-name>
kubectl -n <ns> logs <pod-name> -c <container-name> --previous
如果日志几乎为空,说明容器在启动阶段就失败了。这种情况下,ENTRYPOINT/CMD、权限、挂载或安全上下文的问题可能性更大。
2.3 第三步:冻结启动并进入容器验证
临时修改 deployment,将启动命令替换为 sleep:
bash复制kubectl -n <ns> patch deploy <deploy-name> --type='json' -p='[
{"op":"add","path":"/spec/template/spec/containers/0/command","value":["/bin/sh","-c"]},
{"op":"add","path":"/spec/template/spec/containers/0/args","value":["sleep 3600"]}
]'
然后进入容器进行详细检查:
bash复制kubectl -n <ns> exec -it <pod-name> -c <container-name> -- sh
进入容器后,优先执行以下5个检查(命中率最高):
bash复制id # 查看当前用户和组
pwd # 确认当前工作目录
ls -lah # 查看当前目录文件权限
mount | head # 查看挂载情况
env | head # 查看环境变量
3. 六大常见原因及解决方案
3.1 ENTRYPOINT/CMD 无效(最常见问题)
典型症状:
- Events 中出现
exec: "<xxx>": executable file not found in $PATH - 容器启动瞬间失败,几乎没有日志输出
排查命令:
bash复制kubectl -n <ns> get pod <pod> -o jsonpath='{.spec.containers[0].command}{" "}{.spec.containers[0].args}{"\n"}'
进入容器后验证入口文件:
bash复制ls -lah /path/to/entry # 检查文件是否存在及权限
file /path/to/entry # 检查文件类型
解决方案:
- 使用绝对路径指定 CMD,不要依赖 PATH 环境变量
- 确保二进制文件或脚本存在且有执行权限(chmod +x)
- 对于 shell 脚本,确认首行有正确的 shebang(如 #!/bin/sh)
避坑指南:我曾经遇到过一个案例,开发环境使用 /bin/bash 而生产环境只有 /bin/sh,导致脚本执行失败。建议统一使用 #!/bin/sh 提高兼容性。
3.2 权限问题:Permission denied
典型症状:
- Events 或 runtime 日志中出现 Permission denied
- 非 root 容器特别容易出现此问题
排查命令:
bash复制kubectl -n <ns> get pod <pod> -o jsonpath='{.spec.securityContext}{"\n"}{.spec.containers[0].securityContext}{"\n"}'
进入容器验证:
bash复制id # 查看当前用户和组
ls -lah /app /app/bin 2>/dev/null # 检查关键目录权限
解决方案(按推荐顺序):
- 调整镜像内文件属主和权限(最推荐)
- 修正 runAsUser/runAsGroup/fsGroup 配置
- 避免在只读目录写入(见3.4节)
3.3 镜像架构不匹配:Exec format error
典型症状:
- Events 中出现 Exec format error
- 常见于 M 系列 Mac 构建的镜像运行在 amd64 节点
排查命令:
bash复制kubectl get node -o wide
kubectl get node <node> -o jsonpath='{.status.nodeInfo.architecture}{"\n"}'
解决方案:
- 构建多架构镜像(multi-arch)
- 指定正确的平台构建(--platform=linux/amd64 或 linux/arm64)
3.4 readOnlyRootFilesystem 导致写入失败
典型症状:
- 应用需要写入 /tmp、日志目录或缓存目录
- 日志可能为空或只有一行输出
排查命令:
bash复制kubectl -n <ns> get pod <pod> -o jsonpath='{.spec.containers[0].securityContext.readOnlyRootFilesystem}{"\n"}'
进入容器测试写权限:
bash复制touch /tmp/_write_test && echo OK || echo FAIL
touch /var/log/_write_test && echo OK || echo FAIL
解决方案:
- 为可写目录挂载 emptyDir
- 将写入路径改到已挂载的卷目录
3.5 VolumeMount 覆盖关键目录
典型症状:
- 镜像内 /app 有程序,但 ConfigMap/Volume 挂载到 /app 导致原目录被覆盖
- 入口命令找不到或配置缺失
排查命令:
bash复制kubectl -n <ns> get pod <pod> -o jsonpath='{.spec.containers[0].volumeMounts}{"\n"}'
进入容器验证:
bash复制mount | grep -E '/app|/etc|/config' || true
ls -lah /app /etc /config 2>/dev/null
解决方案:
- 修改 mountPath 到更安全位置(如 /config)
- 使用 subPath 只挂载单个文件,避免覆盖整个目录
3.6 容器运行时/节点侧问题
典型症状:
- 同镜像同 YAML 在某些节点必现,换节点就好
- Events 中出现 runtime 相关错误(创建 sandbox、OCI runtime 等)
排查命令:
bash复制kubectl -n <ns> get pod <pod> -o wide
kubectl describe node <node>
必要时查看节点运行时日志:
bash复制journalctl -u containerd -n 200 --no-pager
解决方案:
- 临时将 Pod 调度到健康节点
- 处理节点 runtime 问题(重启 containerd/kubelet、检查磁盘压力、调整 cgroup 配置等)
4. 一键对照检查清单
按照以下顺序检查,可以覆盖80%以上的CreateContainerError问题:
- [ ] 已查看
kubectl describe pod的 Events,找到明确错误关键词 - [ ] 已检查
kubectl logs --previous(如果有) - [ ] 确认入口命令存在且可执行(路径、权限、shebang)
- [ ]
runAsUser/runAsGroup/fsGroup与文件权限匹配 - [ ]
readOnlyRootFilesystem不影响写入目录(已挂卷或改路径) - [ ] VolumeMount 未覆盖关键目录(特别是 /app、/usr、/etc)
- [ ] 节点架构与镜像架构一致(amd64/arm64)
- [ ] 节点无明显资源/磁盘压力(node condition / eviction)
- [ ] 测试换节点是否复现(区分应用问题与节点问题)
5. 常见报错速查(FAQ)
Q1:Events 里是 "executable file not found in $PATH"
结论:入口命令不在 PATH 或文件不存在。
动作:改用绝对路径 + 确保文件在镜像内。
Q2:Events 里是 "Permission denied"
结论:权限/安全上下文/SELinux 类问题。
动作:核对 runAsUser、文件属主、挂载目录权限。
Q3:报 "Exec format error"
结论:镜像架构不匹配。
动作:构建 multi-arch 或换正确平台镜像。
Q4:没日志,Pod 就是 CreateContainerError
结论:容器启动前就失败(入口命令/权限/挂载/只读根)。
动作:用 sleep 3600 冻结启动,进入容器核查路径与权限。
6. 可直接复制的排查命令合集
bash复制# 1) 事件与状态
kubectl -n <ns> describe pod <pod-name>
# 2) 容器日志
kubectl -n <ns> logs <pod-name> -c <container-name>
kubectl -n <ns> logs <pod-name> -c <container-name> --previous
# 3) 查看 securityContext / mounts / command args
kubectl -n <ns> get pod <pod-name> -o jsonpath='{.spec.containers[0].securityContext}{"\n"}'
kubectl -n <ns> get pod <pod-name> -o jsonpath='{.spec.containers[0].volumeMounts}{"\n"}'
kubectl -n <ns> get pod <pod-name> -o jsonpath='{.spec.containers[0].command}{" "}{.spec.containers[0].args}{"\n"}'
# 4) 查看 Pod 所在节点
kubectl -n <ns> get pod <pod-name> -o wide
在实际运维中,CreateContainerError 虽然令人头疼,但只要按照这套方法系统排查,大多数问题都能快速解决。记住一个原则:先看 Events,再查日志,最后进容器验证。这样可以避免在错误的方向上浪费时间。