文章目录
- 前言
- 1、诊断流程
- 2、常用的排查方法
- 3、Pod 状态、原因分析及故障处理
- 总结
前言
通过 Kubernetes 部署服务,服务并未按照计划正常提供服务。如何通过 Pod 状态,进行异常问题的定制就显得特别重要了!
1、诊断流程
2、常用的排查方法
# 查看节点的资源使用情况
kubectl describe node <node-name> -n xxx
kubectl top node
kubectl top pod
# 查看所有节点的状态
kubectl get nodes
# 查看调度器的日志
kubectl logs -n kube-system <scheduler-pod-name>
# 手动指定运行节点
kubectl apply -f <pod-file.yaml> --node-name=<node-name>
# 校验 yaml 文件
kubectl apply --validate -f XXX.yaml
kubectl create --validate -f mypod.yaml
# 输出 Pod 的 yaml 文件用于对比
kubectl get pods [$Pod] -o yaml > pod.yaml
# 进入容器
kubectl exe -it [$Pod] bash
# 查看日志
kubectl logs [$Pod] [$Container]
kubectl logs --previous [$Pod] [$Container]
# 查看 Pod 建立情况
kubectl describe [$Pod]
# 强制删除 Pod。注意:除非明确知道 Pod 的确处于停止状态(比如 Node 所在 VM 或物理机已经关机),否则不建议使用该方法
kubectl delete pods [$Pod] -n [$namespace] --grace-period=0 --force
3、Pod 状态、原因分析及故障处理
序号 | Pod 状态 | 说明 | 原因分析 | 故障处理 |
---|---|---|---|---|
1 | Pending | Pod未被调度到节点上。Pod 已被 Kubernetes 系统接收并被创建,处于等待中的状态,还没有完成调度。Kubernetes 正在尝试在节点上分配资源并启动Pod,涉及下载镜像、分配IP地址、执行初始化容器等操作。可能是由于调度器正在寻找合适的节点来运行容器,或者正在等待容器镜像下载或其他初始化操作。 | 在 Kubernetes 中,Pending 状态的 Pod 通常是由于调度器无法将该 Pod 调度到可用的节点上。可能的原因包括: 1.节点资源不足:如果节点上的资源(如 CPU、内存、存储、GPU 等资源)或者 HostPort(通常推荐使用 Service 对外开放服务端口)已经被其他 Pod 占用。那么调度器就无法将新的 Pod 调度到该节点上。 2.节点标签不匹配:如果 Pod 的调度要求某些特定的节点标签,而当前可用节点上没有符合要求的标签,那么调度器就无法将该 Pod 调度到该节点上。 3.网络问题:如果节点之间的网络连接不稳定或存在故障,那么调度器就无法将 Pod 调度到可用的节点上。 | 为了排查 Pending 状态的 Pod,可以执行以下步骤: 1.确认节点资源是否足够:使用 kubectl describe node -n xxx 命令查看节点的资源使用情况,确保节点上有足够的资源来运行该 Pod。 2.确认节点标签是否匹配:使用 kubectl describe node -n xxx 命令查看节点的标签,确保节点上符合 Pod 调度要求的标签已经设置。 3.检查网络连接是否正常:使用 kubectl get nodes 命令查看所有节点的状态,确保节点之间的网络连接正常。 4.查看调度器日志:使用 kubectl logs -n kube-system 命令查看调度器的日志,以了解调度器为什么无法将 Pod 调度到可用节点上。 5.手动指定节点:如果无法解决调度问题,可以考虑手动指定节点来运行该 Pod,使用 kubectl apply -f <pod-file.yaml> --node-name= 命令来指定节点。 总的来说,Pending 状态的 Pod 可能是由于多种原因引起的,需要根据具体情况进行排查和解决。 |
2 | Init:N/M | Pod包含M个Init容器,其中N个已经启动完成 | ||
3 | Init:Error | Init容器已启动失败 | ||
4 | Init:CrashLoopBackOff | Init容器启动失败,反复重启 | ||
5 | Running | 1.Pod 运行正常。 2.Pod Running 但是未正常工作。Pod 已经被绑定到一个节点上,并且所有的容器都已经被创建,而且至少有一个是运行状态,或者是正在启动或者重启。Pod 状态为 Running,并不代表 Pod 正常,也需要 READY 为 N/N。 | 部署使用的 YAML 文件有问题 | 1.查看 Pod 的配置,确定 Pod 中容器的配置是否符合预期 2.排查环境变量中的某一个 Key 是否存在拼写错误。通过 kubectl apply --validate -f XXX.yaml 输出的错误信息进行判断,或者通过 kubectl get pods [$Pod] -o yaml > pod.yaml 的输出结果 pod.yaml 文件与创建 Pod 使用的文件进行对比 3.查看 Pod 的日志,通过日志内容排查问题 4.可通过终端进入容器查看容器内的本地文件是否符合预期 |
6 | Succeeded | Pod 中的所有的容器已经正常执行成功并终止,并且不会自动重启,一般会是在部署 job 的时候会出现。 | ||
7 | Failed | Pod 中的所有容器都已终止了,并且至少有一个容器以失败的方式终止。也就是说,容器以非0状态退出或者被系统终止。 | 看容器退出代码:检查容器的退出代码,如果退出代码为非零,表示容器内部发生了错误,定位可以查看容器的日志。 依赖资源不可用:某些容器可能依赖于其他基础设施资源(如数据库、配置文件、权限文件、配置等),如果这些资源不可用、或密码不正确、权限不够也会导致启动失败。 初始化容器启动失败:如果 Pod 中定义了初始化容器,并且初始化容器失败,那么 Pod 也会失败。 资源限制与污点:Pod 可能无法满足定义的资源限制来运行容器。检查 Pod 的资源请求和集群的资源配额。 镜像拉取失败:如果容器使用的镜像无法从容器注册表中拉取,Pod 可能会失败。请确保镜像名称正确,并检查网络连接以确保能够访问镜像注册表。 挂载卷失败:如果 Pod 中定义了挂载的卷,如 pv、pvc、目录挂载等。并且挂载失败,容器可能会因为找不到所需的文件或目录而失败。检查挂载卷的配置和权限设置。 节点故障:如果运行 Pod 的节点发生故障或不可用,Pod 可能会失败。检查节点的健康状态。 就绪探针检测失败:在定义了就绪探针时,探针评定 Pod 内的应用启动失败从而一直重启或退出。 | 为了排查 Failed 状态的 Pod,可以执行以下步骤: 1.查看 Pod 的日志:使用 kubectl logs 命令查看 Pod 的日志,以了解容器启动时发生了什么错误。 2.查看 Pod 建立情况:使用 kubectl describe 命令查看 Pod 建立情况 |
8 | Unknown | Unknown 这个异常状态意味着 Pod 的状态不能持续地被 kubelet 汇报给 kube-apiserver,这很有可能是主从节点(Master 和 Kubelet)间的通信出现了问题。 | 检查网络:检查集群中各个组件之间的网络连接是否正常。确保 API 服务器、调度器、控制器等关键组件之间的通信没有问题。 查看日志:尝试查看和分析与 API 服务器相关的日志,以确定是否有与 Pod 状态收集相关的错误或异常信息。 验证权限不通过:确保正在尝试获取 Pod 状态的用户具有足够的权限。有时候权限不足也可能导致获取状态失败,排查如 RBAC 或镜像仓库权限等。 集群节点故障:组件可能产生故障,无法获取pod状态,可以检查集群的整体健康状况,确保节点和其他关键组件都在正常运行。 调度后无法满足污点容忍:如果节点下线,污点又恰巧不能容忍到其他节点,会导致pod调度失败,可能也会产生 Unknown 的状态。 | 解决方案万能重启大法,有时候重启受影响的组件(如 kubelet、kube-proxy)短时间缓解问题,可以恢复对 Pod 状态的获取。 从v1.5开始,Kubernetes 不会因为 Node 失联而删除其上正在运行的 Pod,而是将其标记为 Terminating 或 Unknown 状态。 想要删除这些状态的 Pod 有三种方法: 1、从集群中删除 Node。使用公有云时,kube-controller-manager 会在 VM 删除后自动删除对应的 Node。而在物理机部署的集群中,需要管理员手动删除 Node(命令: kubectl delete node)。 2、Node 恢复正常。kubelet 会重新跟 kube-apiserver 通信确认这些 Pod 的期待状态,进而再决定删除或者继续运行这些 Pod。用户强制删除,用户可以执行( kubectl delete pods pod-name --grace-period=0 --force)强制删除 Pod。除非明确知道 Pod 的确处于停止状态(比如 Node 所在 VM 或物理机已经关机),否则不建议使用该方法。特别是 StatefulSet 管理的 Pod,强制删除容易导致脑裂或数据丢失等问题。 3、Pod 行为异常,这里所说的行为异常是指 Pod 没有按预期的行为执行,比如没有运行 podSpec 里面设置的命令行参数。这一般是 podSpec yaml 文件内容有误,可以尝试使用 --validate 参数重建容器,比如( kubectl delete pod mypod 和 kubectl create --validate -f mypod.yaml);也可以查看创建后的podSpec 是否是对的,比如( kubectl get pod mypod -o yaml);修改静态 Pod 的 Manifest 后未自动重建,kubelet 使用 inotify 机制检测 /etc/kubernetes/manifests 目录(可通过 kubelet 的 -pod-manifest-path 选项指定)中静态 Pod 的变化,并在文件发生变化后重新创建相应的 Pod。但有时也会发现修改静态 Pod的 Manifest 后未自动创建新 Pod 的情景,此时已过简单的修复方法是重启 Kubelet。 |
9 | Unschedulable | Pod 不能被调度,kube-scheduler 没有匹配到合适的 node 节点。 | ||
10 | PodScheduled | Pod 正处于调度中,在 kube-scheduler 刚开始调度的时候,还没有将 Pod 分配到指定的 node,在筛选出合适的节点后就会更新 etcd 数据,将 Pod 分配到指定的 node。 | ||
11 | Initialized | 所有 pod 中的初始化容器已经完成了。 | ||
12 | ImagePullBackOff | Pod镜像拉取失败 | Pod 状态为 ImagePullBackOff ErrImagePull 通常表示镜像拉取失败,一般是由于镜像名称错误、镜像不存在、网络不通或者需要登录认证引起的。 | 为了排查 ImagePullBackOff ErrImagePull 状态的 Pod,可以执行以下步骤: 1.确认容器镜像名称是否正确 2.登录到 Pod 所在的节点,执行 docker pull [$Image] 命令,查看是否能正常抓取容器镜像 3.查看 Pod 的日志:使用 kubectl logs 命令查看 Pod 的日志,以了解容器启动时发生了什么错误。 4.查看 Pod 建立情况:使用 kubectl describe 命令查看 Pod 建立情况 |
13 | ErrImagePull | 通用的拉取镜像出错,超时或下载被强制终止 | 参考 ImagePullBackOff 描述 | 参考 ImagePullBackOff 描述 |
14 | Ready | 表示 pod 中的容器已经可以提供访问服务。 | ||
15 | Error | Pod 启动过程中发生错误。 | 常见的原因: 1.依赖的 ConfigMap、Secret 或 PV 等不存在; 2.请求的资源超过了管理员设置的限制。比如超过了 LimitRange 等; 3.违反集群的安全策略,比如违反了 PodSecurityPolicy 等; 4.容器无法操作集群内的资源,比如开启 RDAC 后,需要为 ServiceAccount 配置角色绑定。 | |
16 | NodeLost | Pod 所在节点失联。 | ||
17 | Waiting | Pod 等待启动。 | 可能的原因有: 1、镜像拉取失败,比如镜像地址配置错误、拉取不了国外镜像源(gcr.io)、私有镜像密钥配置错误、镜像太大导致拉取超时 (可以适当调整 kubelet 的 -image-pull-progress-deadline 和 -runtime-request-timeout 选项)等。 2、CNI 网络错误,一般需要检查 CNI 网络插件的配置,比如:无法配置 Pod 网络、无法分配 IP 地址。 3、容器无法启动,需要检查是否打包了正确的镜像或者是否配置了正确的容器参数 4、Failed create pod sandbox,查看kubelet日志,原因可能是磁盘坏道(input/output error)。 | Pod 一直处于 Waiting 或 ContainerCreating 状态 首先还是通过 kubectl describe pod 命令查看当前 Pod 的事件。 |
18 | Terminating | Terminating(终止中/Pod 正在关闭中):当 Pod 被删除或终止时,它将进入终止中的状态。在这个状态下,Kubernetes 会尝试停止容器并清理资源。 | 若 Pod 一直停留在 Terminating 状态,可执行如下命令强制删除: kubectl delete pod [ P o d ] − n [ Pod] -n [ Pod]−n[namespace] --grace-period=0 --force | |
19 | CrashLoopBackOff | Pod启动失败,反复重启 | Pod 状态为 CrashLoopBackOff 通常表示容器在启动后立即崩溃或退出。这可能是由于许多原因导致的,包括容器配置错误、应用程序错误、内存不足、权限问题等。 这时可以先查看一下容器的日志。 | 以下是一些排查 Pod 状态异常的建议: 1.查看 Pod 的日志:使用 kubectl logs ${POD_NAME} ${CONTAINER_NAME} 和 kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME} 命令查看 Pod 的日志,以了解容器启动时发生了什么错误。 2.检查容器配置:确保容器的配置正确。例如,检查容器的入口点、环境变量、端口、卷等。 3.检查应用程序错误:如果容器配置正确,则可能是应用程序错误导致容器崩溃。使用 kubectl exec -it ${POD_NAME} bash 命令进入容器检查应用程序的日志和状态,或者使用 kubectl exec [POD] – [COMMAND]。 4.检查系统资源:如果容器在启动后立即崩溃,则可能是由于内存不足、CPU 不足或磁盘空间不足等系统资源问题导致的。 5.检查权限问题:如果容器需要特定的权限才能运行,则可能是权限问题导致容器崩溃。例如,容器需要访问宿主机的某些文件或网络资源,但没有足够的权限。 总之,要排查 Pod 状态异常,需要仔细检查容器的配置、应用程序的错误、系统资源以及权限问题。找到问题后,可以尝试修复它,并重新启动 Pod。 |
20 | InvalidImageName | node 节点无法解析镜像名称导致的镜像无法下载。 | ||
21 | ImageInspectError | 无法校验镜像,镜像不完整导致。 | ||
22 | ErrImageNeverPull | 策略禁止拉取镜像,镜像中心权限是私有等。 | ||
23 | RegistryUnavailable | 连接不到镜像中心、镜像服务器不可用、网络原因或 harbor 宕机。 | ||
24 | CreateContainerConfigError | 不能创建 kubelet 使用的容器配置 | ||
25 | CreateContainerError | 创建容器失败 | ||
26 | PreStartContainer | 执行 preStart hook 报错,Pod hook(钩子)是由 Kubernetes 管理的 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,比如容器创建完成后里面的服务启动之前可以检查一下依赖的其它服务是否启动,或者容器退出之前可以把容器中的服务先通过命令停止。 | ||
27 | RunContainerError | 启动容器失败,容器中没有初始化 PID 为1的守护进程等。 | ||
28 | ContainersNotInitialized | 容器没有初始化完毕 | ||
29 | ContainersNotReady | 容器没有准备完毕 | ||
30 | ContainerCreating | ContainerCreating(创建容器中/容器正在被创建):当Pod的容器正在创建中时,Pod将进入创建容器中的状态。常见在容器镜像下载或初始化容器执行的过程中。 | 有可能出现一直在创建的问题,这可能是因为挂载 volume 的时候出现了问题,一直处在创建中。第二个可能是对容器资源进行限制的时候,单位 可能写错了。比如在对 memory 进行限制的时候,两百兆的正确写法应该是 200MI,很多情况 下会写错成 200M,其实 200M 并不代表 200 兆,代表的是 0.2bytes。这很容易产生一个问题: 容器还没起来就遇到了 Cgroup 的 OOM 把容器给杀死了。还有可能是内存碎片化产生的问题。 | |
31 | PodInitializing | Pod 正在初始化中。 | ||
32 | DockerDaemonNotReady | node 节点 docker 服务没有完全启动。 | ||
33 | NetworkPluginNotReady | 网络插件还没有完全启动。 | ||
34 | PreStartHookError | 执行 preStart hook 报错 | ||
35 | PostStartHookError | 执行 postStart hook 报错。 | ||
36 | NetworkPluginNotReady | 网络插件还没有完全启动 | ||
37 | Evicted | Pod被驱逐 | 当节点的内存、磁盘空间、文件系统的 inode 和操作系统可分配的 PID 等资源中的一个或者多个达到特定的消耗水平,就会引发 kubelet 主动地驱逐节点上一个或者多个 Pod,以回收节点资源 | 查看 Pod 的 status.message 字段,来确定 Pod 被驱逐的原因。使用 kubectl get pod [ P o d ] − o y a m l − n [ Pod] -o yaml -n [ Pod]−oyaml−n[namespace] status.message 关键信息示例:内存压力(MemoryPressure)、PID压力(PIDPressure)和磁盘压力 (DiskPressure) |
38 | OOMKilled | Pod 状态为 OOMKilled 通常表示容器内存溢出,一般是容器的内存 Limit 设置的过小,或者程序本身有内存溢出 | 为了排查 OOMKilled 状态的 Pod,可以执行以下步骤: 1.查看 Pod 的日志:使用 kubectl logs 命令查看 Pod 的日志,以了解容器启动时发生了什么错误。 2.查看Pod建立情况:使用 kubectl describe 命令查看 Pod 建立情况 | |
39 | SysctlForbidden | Pod 状态为 SysctlForbidden 通常表示 Pod 自定义了内核配置,但 kubelet 没有添加内核配置或配置的内核参数不支持 | 可以执行以下步骤: 1.查看 Pod 的日志:使用 kubectl logs 命令查看 Pod 的日志,以了解容器启动时发生了什么错误。 2.查看Pod建立情况:使用 kubectl describe 命令查看 Pod 建立情况 | |
40 | Completed | Pod的启动命令已执行完毕 | Pod 状态为 Completed 通常表示容器内部主进程退出,一般计划任务执行结束会显示该状态 | 可以执行以下步骤: 1.查看 Pod 的日志:使用 kubectl logs 命令查看 Pod 的日志,以了解容器启动时发生了什么错误。 2.查看Pod建立情况:使用 kubectl describe 命令查看 Pod 建立情况 |
总结
刚接触 Kubernetes 可能感觉比较蒙,不太知道如何通过 Pod 的状态定位故障。掌握套路之后,其实并没有那么困难!