Pod 排错
本章介绍 Pod 运行异常的排错方法。
一般来说,无论 Pod 处于什么异常状态,都可以执行以下命令来查看 Pod 的状态
kubectl get pod <pod-name> -o yaml查看 Pod 的配置是否正确kubectl describe pod <pod-name>查看 Pod 的事件kubectl logs <pod-name> [-c <container-name>]查看容器日志
这些事件和日志通常都会有助于排查 Pod 发生的问题。
Pod 一直处于 Pending 状态
Pending 说明 Pod 还没有调度到某个 Node 上面。可以通过 kubectl describe pod <pod-name> 命令查看到当前 Pod 的事件,进而判断为什么没有调度。如
$ kubectl describe pod mypod...Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 12s (x6 over 27s) default-scheduler 0/4 nodes are available: 2 Insufficient cpu.可能的原因包括
资源不足,集群内所有的 Node 都不满足该 Pod 请求的 CPU、内存、GPU 或者临时存储空间等资源。解决方法是删除集群内不用的 Pod 或者增加新的 Node。
HostPort 端口已被占用,通常推荐使用 Service 对外开放服务端口
Pod 一直处于 Waiting 或 ContainerCreating 状态
首先还是通过 kubectl describe pod <pod-name> 命令查看到当前 Pod 的事件
可以发现,该 Pod 的 Sandbox 容器无法正常启动,具体原因需要查看 Kubelet 日志:
发现是 cni0 网桥配置了一个不同网段的 IP 地址导致,删除该网桥(网络插件会自动重新创建)即可修复
除了以上错误,其他可能的原因还有
镜像拉取失败,比如
配置了错误的镜像
Kubelet 无法访问镜像(国内环境访问
gcr.io需要特殊处理)私有镜像的密钥配置错误
镜像太大,拉取超时(可以适当调整 kubelet 的
--image-pull-progress-deadline和--runtime-request-timeout选项)
CNI 网络错误,一般需要检查 CNI 网络插件的配置,比如
无法配置 Pod 网络
无法分配 IP 地址
容器无法启动,需要检查是否打包了正确的镜像或者是否配置了正确的容器参数
Pod 处于 ImagePullBackOff 状态
这通常是镜像名称配置错误或者私有镜像的密钥配置错误导致。这种情况可以使用 docker pull <image> 来验证镜像是否可以正常拉取。
如果是私有镜像,需要首先创建一个 docker-registry 类型的 Secret
然后在容器中引用这个 Secret
Pod 一直处于 CrashLoopBackOff 状态
CrashLoopBackOff 状态说明容器曾经启动了,但又异常退出了。此时 Pod 的 RestartCounts 通常是大于 0 的,可以先查看一下容器的日志
这里可以发现一些容器退出的原因,比如
容器进程退出
健康检查失败退出
OOMKilled
如果此时如果还未发现线索,还可以到容器内执行命令来进一步查看退出原因
如果还是没有线索,那就需要 SSH 登录该 Pod 所在的 Node 上,查看 Kubelet 或者 Docker 的日志进一步排查了
Pod 处于 Error 状态
通常处于 Error 状态说明 Pod 启动过程中发生了错误。常见的原因包括
依赖的 ConfigMap、Secret 或者 PV 等不存在
请求的资源超过了管理员设置的限制,比如超过了 LimitRange 等
违反集群的安全策略,比如违反了 PodSecurityPolicy 等
容器无权操作集群内的资源,比如开启 RBAC 后,需要为 ServiceAccount 配置角色绑定
Pod 处于 Terminating 或 Unknown 状态
从 v1.5 开始,Kubernetes 不会因为 Node 失联而删除其上正在运行的 Pod,而是将其标记为 Terminating 或 Unknown 状态。想要删除这些状态的 Pod 有三种方法:
从集群中删除该 Node。使用公有云时,kube-controller-manager 会在 VM 删除后自动删除对应的 Node。而在物理机部署的集群中,需要管理员手动删除 Node(如
kubectl delete node <node-name>。Node 恢复正常。Kubelet 会重新跟 kube-apiserver 通信确认这些 Pod 的期待状态,进而再决定删除或者继续运行这些 Pod。
用户强制删除。用户可以执行
kubectl delete pods <pod> --grace-period=0 --force强制删除 Pod。除非明确知道 Pod 的确处于停止状态(比如 Node 所在 VM 或物理机已经关机),否则不建议使用该方法。特别是 StatefulSet 管理的 Pod,强制删除容易导致脑裂或者数据丢失等问题。
如果 Kubelet 是以 Docker 容器的形式运行的,此时 kubelet 日志中可能会发现如下的错误:
如果是这种情况,则需要给 kubelet 容器设置 --containerized 参数并传入以下的存储卷
处于 Terminating 状态的 Pod 在 Kubelet 恢复正常运行后一般会自动删除。但有时也会出现无法删除的情况,并且通过 kubectl delete pods <pod> --grace-period=0 --force 也无法强制删除。此时一般是由于 finalizers 导致的,通过 kubectl edit 将 finalizers 删除即可解决。
pod状态为OutOfpods
这个在node节点默认110的pod使用完毕后出现
Pod 行为异常
这里所说的行为异常是指 Pod 没有按预期的行为执行,比如没有运行 podSpec 里面设置的命令行参数。这一般是 podSpec yaml 文件内容有误,可以尝试使用 --validate 参数重建容器,比如
也可以查看创建后的 podSpec 是否是对的,比如
修改静态 Pod 的 Manifest 后未自动重建
Kubelet 使用 inotify 机制检测 /etc/kubernetes/manifests 目录(可通过 Kubelet 的 --pod-manifest-path 选项指定)中静态 Pod 的变化,并在文件发生变化后重新创建相应的 Pod。但有时也会发生修改静态 Pod 的 Manifest 后未自动创建新 Pod 的情景,此时一个简单的修复方法是重启 Kubelet。
参考文档
Last updated