诊断流程
如果Pod状态异常,可通过查看Pod的事件、Pod的日志、Pod的配置等信息确定异常原因。大体排查流程如下。
执行kubectl describe pod -n <pod所在命名空间> <podName>查看Pod事件,根据event中的报错信息,排查对应原因
阶段一:调度问题
Pod未调度到节点.
如果Pod长时间处于Pending状态,说明该Pod没有被安排到任何节点上运行。
event中的报错信息 | 说明 | 处理方式 |
no nodes available to schedule pods. | 当前集群中没有符合Pod要求的合适节点可供调度。 | 1、查看集群中是否存在状态为NotReady的节点。如果存在,则对该类节点进行检查和修复。 2、检查Pod中是否声明了nodeSelector、nodeAffinity或污点容忍。 3、若不存在亲和性策略,可以检查kube-system命名空间下的kube-scheduler对应的pod是否正常运行、pod中有无异常日志。 |
0/x nodes are available: x Insufficient cpu. 0/x nodes are available: x Insufficient memory. | 当前集群中没有可用节点能够满足Pod所需的CPU或内存资源。 | 在节点页面查看CPU、内存的使用情况,确定集群的资源使用率。 1、若集群中的CPU或内存已经耗尽,可参考如下方法处理。 1.1、调整工作负载副本数,删除或减少不必要的Pod。 1.2、根据自身业务情况,调整Pod对应工作负载的CPU、内存资源的requests值和limits值。 2、在集群中扩容新的节点。 |
x node(s) didn't match node selector. x node(s) didn't match pod affinity/anti-affinity. | 当前集群现有节点中,没有节点满足Pod声明的nodeSelector要求或Pod亲和性podAffinity或podAnitiAffinity要求。 | 1、检查并调整Pod的节点亲和性策略,包括节点标签、nodeSelector、nodeAffinity、节点污点和Pod容忍等。 2、检查并调整Pod的Pod亲和性策略,如果Pod配置了podAffinity,则需要检查目标节点上是否有匹配的Pod存在;如果配置了podAntiAffinity,则需确认目标节点上没有不应共存的Pod。 |
0/x nodes are available: x node(s) had taints that the pod didn't tolerate. | 当前集群中Pod需要调度的目标节点被打上了污点,不允许该Pod调度到该节点上。 | 如果污点是由用户手动添加,您可以删除非预期的污点。如果无法删除污点,可以为Pod配置相应的容忍。 如果污点为系统自动添加,您可以参见下文解决对应的问题,问题解决后等待Pod重新调度。 |
0/x nodes are available: x Insufficient ephemeral-storage. | 节点临时存储容量不足。 | 检查Pod是否配置了临时存储卷的限制,即Pod YAML中spec.containers.resources.request.ephemeral-storage的取值。如果取值过高,超出了节点的实际可用容量,Pod会调度失败。 执行kubectl describe node | grep -A10 Capacity命令,查看各个节点上可用于临时存储的总容量。如果容量不足,可扩容节点磁盘或增加节点数量。 |
0/x nodes are available: pod has unbound immediate PersistentVolumeClaims. | Pod绑定PVC失败。 | 检查Pod所指定的PVC或PV是否已经创建,通过kubectl describe pvc <pvc-name> 或 kubectl describe pv <pv-name>命令查看PVC、PV的Event信息,进一步进行判断。 |
too many pods | 当前集群中运行的Pod数量超过kubelet可容纳的Pod最大值。 | 默认情况下,kubelet启动参数--max-pods=110表明该节点最大只能容纳110个Pod。根据自身业务情况和集群资源使用情况,调整工作负载副本数,删除或减少不必要的Pod或修改kubelet的--max-pods启动参数值。 |
系统自动添加的污点 | 对应含义 | 可能原因 | 处理方法 |
node.kubernetes.io/not-ready | 节点未准备好,处于NotReady状态。 | 1、节点上kubelet进程异常 2、节点主机状态异常,如:关机、hang死 | 登录主机检查kubelet进程是否异常,有无错误日志 |
node.kubernetes.io/unreachable | 节点控制器访问不到节点,相当于节点状况Ready 的值为Unknown。 | 1、节点上kubelet进程异常 2、master节点到异常节点之间主机网络异常 | 1、登录主机检查kubelet进程是否异常,有无错误日志 2、排查异常节点到master节点直接的主机网络 |
node.kubernetes.io/memory-pressure | 节点存在内存压力。 | 节点上Pod进程和主机进程占用了较多内存,内存使用率较高 | 1、调整工作负载副本数,删除或减少不必要的Pod。2、根据自身业务情况,调整Pod对应工作负载的CPU、内存资源的requests值和limits值。 3、在集群中扩容新的节点。 |
node.kubernetes.io/disk-pressure | 节点存在磁盘压力。 | 节点上Pod进程和主机进程占用了较多的磁盘空间,磁盘空间不足。 | 1、清理主机上不再需要的大文件,如不再需要的镜像文件、日志文件等。 2、新增磁盘挂载或扩容磁盘。 3、在集群中扩容新的节点。 |
node.kubernetes.io/pid-pressure | 节点存在PID压力。 | 节点上Pod进程和主机进程占用了较多的Pid,进程数过多导致可分配Pid不足。 | 1、尽量避免在k8s节点对应的主机上运行业务程序。 2、调整工作负载副本数,删除或减少不必要的Pod。 3、在集群中扩容新的节点。 |
node.kubernetes.io/network-unavailable | 节点网络不可用。 | 节点上网络插件Pod异常 | 检查该节点上的网络插件Pod状态和Pod日志。 |
node.kubernetes.io/unschedulable | 节点不可调度。 | 节点被驱逐 | 检查是否人为将该节点设置为驱逐,可通过执行kubectl uncordon <nodeName>恢复。 |
Pod已调度到节点
如果Pod已经被调度到某个节点上但仍处于Pending状态,请检查Pod是否配置了hostPort。如果Pod配置了hostPort,那么每个节点最多只能运行一个使用该hostPort的Pod实例。因此,工作负载的副本数不能超过集群中的节点数。
检查该端口被主机上的其他进程占用。
如果Pod没有配置hostPort,且Event中没有有效信息时,可查看该节点上的kubelet日志或系统日志(/var/log/messages*),根据Pod名称进行过滤,进一步排查Pod启动过程中存在的问题。
阶段二:镜像拉取问题
报错信息 | 说明 | 推荐的解决方案 |
Failed to pull image "xxxx:xxx": rpc error: code = Unknown desc = Error response from daemon: Get https://xxxxxx/xxxxx/: dial tcp: lookup xxxxxxx.xxxxx: no such host | 从指定的镜像仓库地址拉取镜像时,镜像仓库域名解析失败。 | 检查Pod YAML中spec.containers.image配置的镜像仓库地址是否正确。如有误,需修改对应工作负载中的镜像仓库地址为正确地址。 如地址无误,需要排查从Pod所在节点到镜像仓库的主机网络是否异常。可登录到Pod所在节点,运行命令curl -kv https://xxxxxx/xxxxx/ 判断地址是否可以访问。如有报错,进一步判断是否存在网络配置、防火墙规则、DNS解析等主机网络异常问题。 |
Failed create pod sandbox: rpc error: code = Unknown desc = failed to create a sandbox for pod "xxxxxxxxx": Error response from daemon: mkdir xxxxx: no space left on device | 节点磁盘空间不足。 | 登录到Pod所在节点,运行df -h查看磁盘空间状态。如磁盘已满,请清理主机上不再需要的大文件或扩容磁盘。 |
Failed to pull image "xxxxx": rpc error: code = Unknown desc = Error response from daemon: Get https://xxxxxxx: xxxxx/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) | 无法连接镜像仓库,网络不通。 | 登录到Pod所在节点,运行cmd命令curl https://xxxxxx/xxxxx/判断地址是否可以访问。如有报错,进一步判断是否存在网络配置、防火墙规则、DNS解析等网络访问问题。 如果是公网镜像,判断节点的公网策略是否正常,例如NAT网关、绑定的弹性公网IP等配置。 |
阶段三:启动问题
Pod处于init状态
错误信息 | 说明 | 推荐的解决方案 |
停留在Init:N/M状态 | 该Pod包含M个初始化容器中的N个已经启动完成,剩余的容器未启动成功。 | 1.通过kubectl describe pod -n <ns> <pod name>命令查看Pod的事件,确认当前Pod中未启动的初始化容器是否存在异常。 2.通过kubectl logs -n <ns> <podName> -c <containerName>命令查看Pod中未成功启动的初始化容器的日志,通过日志内容排查问题。 3.查看Pod的配置,例如检查健康检查配置,进一步确认未成功启动的初始化容器配置是否正常。 |
停留在Init:Error状态 | Pod中的初始化容器启动失败。 | |
停留在Init:CrashLoopBackOff状态 | Pod中的初始化容器启动失败并处于反复重启状态。 |
Pod启动失败(CrashLoopBackOff)
错误信息 | 说明 | 推荐的解决方案 |
日志中存在exit(0)。 | 容器中前台进程执行完毕正常退出。 | 非Job类型工作负载对应的Pod容器需要前台进程作为常驻进程,若前台进程执行完毕且无常驻进程,容器就会正常退出,kubelet检测到容器退出后重新拉起该容器,进而导致容器一直在重启。 修改容器主进程为常驻进程。 |
Event信息中存在Liveness probe failed:。 | 容器健康检查失败。 | 核查Pod中所配置的容器健康检查(Liveness Probe)策略是否符合预期,以及对应的健康检查条件是否满足。 |
Pod日志中存在no left space。 | 磁盘空间不足。 | 清理主机上不再需要的大文件或扩容磁盘。 |
启动失败,无Event信息。 | 可能是Pod中声明的Limit资源少于实际Pod进程启动所需资源。 | 检查Pod的资源配置是否正确。 |
Pod日志中出现Address already in use。 | 同一Pod中的Container端口存在冲突。 | 检查Pod是否配置了hostNetwork: true,这意味着Pod内的容器会直接与宿主机共享网络接口和端口空间。如果无需使用,请改为hostNetwork: false。 如果Pod需要使用hostNetwork: true,请配置Pod的反亲和性,确保同一副本集中的Pod被调度到不同节点。 检查并确保不存在也不会有两个或多个具有相同端口需求的Pod运行在同一台节点上。 检查主机上是否有主机进程占用了该端口,尽量避免在k8s节点主机上直接部署业务进程。 |
Pod日志中出现container init caused \"setenv: invalid argument\"": unknown。 | 工作负载中挂载了Secret,但Secret对应的值没有进行Base64加密。 | 通过控制台创建Secret,Secret对应的值会自动进行Base64加密。 通过YAML创建Secret,并执行echo -n "xxxxx" | base64命令手动对密钥值进行Base64加密。 |
无相关信息。 | 可能是业务Pod自身问题,如业务容器中进程启动参数有误。 | 查看Pod日志,通过业务日志内容排查问题。 |
阶段四:Pod运行问题
OOM
当集群中的容器使用超过其限制的内存,容器可能会被终止,触发OOM(Out Of Memory)事件,导致容器异常退出。
OOM可能原因 | 说明 | 推荐的解决方案 |
系统内存不足 | 查看Pod所在节点的内核日志/var/log/messages,日志中存在Killed Process,但不存在kubepods相关日志;且主机内存使用量较高,表明是主机操作系统内存不足。 | 可能是系统全局内存不足、内存碎片化严重、内存泄露等。可提单排查。 |
Pod内存不足 | 查看Pod所在节点的内核日志/var/log/messages,日志中存在类似Task in /kubepods.slice/xxxxx killed as a result of limit of /kubepods.slice/xxxx的报错信息,且主机内存使用量不高或Pod的资源Limit值设置得较小,表明OOM为cgroup级别。 | 根据业务实际运行需要,适当增大Pod的内存Limit。 |
Terminating
可能原因 | 说明 | 推荐的解决方案 |
节点存在异常,处于NotReady状态。 | 节点存在异常,处于NotReady状态。 | 处于NotReady状态的节点恢复正常后会被自动删除。 |
Pod配置了Finalizers。 | 如果Pod配置了Finalizers,Kubernetes会在删除Pod之前执行Finalizers指定的清理操作。如果相关的清理操作没有正常响应,Pod将保持在Terminating状态。 | 通过kubectl get pod -n <ns> <podName> -o yaml查看Pod是否配置了Finalizers,进一步排查异常原因。 |
Pod的preStop配置异常。 | 如果Pod配置了preStop,Kubernetes会在c。Pod正处于终止流程的preStop阶段时,Pod将处于Terminating状态。 | 通过kubectl get pod -n <ns> <pod name> -o yaml查看Pod的preStop配置,进一步排查异常原因。 |
Pod配置了优雅退出时间。 | 如果Pod配置了优雅退出时间(terminationGracePeriodSeconds),Pod收到终止命令后(例如kubectl delete pod <pod_name>命令)会进入Terminating状态。等待terminationGracePeriodSeconds设定的时间后,或容器提前退出后,Kubernetes才认为Pod已经成功关闭。 | 等待容器优雅退出后,Kubernetes将自动删除Pod。 |
容器无响应。 | 发起停止或删除Pod的请求后,Kubernetes会向Pod内的容器发送SIGTERM信号。如果容器在终止过程中没有正确响应SIGTERM信号,Pod可能会停留在Terminating状态 | 使用kubectl delete pod <pod-name> --grace-period=0 --force强制删除,释放Pod资源。 检查Pod所在节点的containerd或Docker日志,进一步进行排查。 |
Evicted
可能原因 | 说明 | 推荐的解决方案 |
发生了非预期的驱逐行为。 | 待运行Pod的节点被手动打上了NoExecute的污点,导致出现非预期的驱逐行为。 | 通过kubectl describe node <node name> | grep Taints命令检查节点是否被打上了NoExecute污点。如是,请删除。 |
节点存在资源压力,包括内存不足、磁盘空间不足等,引发kubelet主动驱逐节点上的一个或者多个Pod,以回收节点资源。 | 可能存在内存压力、磁盘压力、Pid压力等。可以通过kubectl describe node <node name> | grep Taints命令查询。 内存压力:带有污点node.kubernetes.io/memory-pressure。 磁盘压力:带有污点node.kubernetes.io/disk-pressure。 Pid压力:带有污点node.kubernetes.io/pid-pressure。 | 内存压力: 根据自身业务情况,调整Pod的资源配置。 磁盘压力: 定时清理节点上的业务Pod日志,防止磁盘空间被耗尽。 为节点进行磁盘扩容。 Pid压力:根据自身业务情况,调整Pod的资源配置。 |
容器被驱逐后仍然频繁调度到原节点。 | 节点驱逐容器时会根据节点的资源使用率进行判断,而容器的调度规则是根据节点上的“资源分配量”进行判断,被驱逐的Pod有可能被再次调度到这个节点,从而出现频繁调度到原节点的现象。 | 根据集群节点的可分配资源检查Pod的资源Request请求配置是否合理。 |
未按照预期流程执行驱逐。 | --pod-eviction-timeout:当节点宕机时间超过设置时间后,开始驱逐宕机节点上的Pod,默认为5min。 --node-eviction-rate:每秒从节点上驱逐的Pod数量。默认为0.1,即每10s至多从一个节点上驱逐Pod。 --secondary-node-eviction-rate:第二档的节点驱逐速率。当集群中宕机节点过多时,节点驱逐速率会降低至第二档,默认值为0.01。 --unhealthy-zone-threshold:可用区的不健康阈值,默认为0.55,即当宕机的节点数量超过总节点数的55%时,该可用区被判定为不健康。 --large-cluster-size-threshold:集群的大规模阈值,默认为50,即当集群节点数量超过50时判定集群为大规模集群。 | 在小规格的集群(集群节点数小于等于50个节点)中,如果故障的节点大于总节点数的55%,实例的驱逐会被停止。 在大规模集群中(集群节点数大于50),如果集群中不健康的节点数量占总节点数的比例超过了预设的阈值--unhealthy-zone-threshold(默认为0.55),驱逐速率由--secondary-node-eviction-rate控制(代表每分钟驱逐节点上Pod的最大比例),默认值为0.01。 |
Completed
Completed状态下,Pod中容器的启动命令已执行完毕,容器中的所有进程均已成功退出。Completed状态通常适用于Job、Init容器等,该状态是正常状态。