【问题排查】一次kube-scheduler调度失败问题分析

Posted by Hao Liang's Blog on Friday, September 10, 2021

一、背景

最近,线上经常发生业务 Pod 调度失败的现象,查看集群监控,集群的资源确实比较紧张,但仍然存在部分节点资源充足。 例如,业务 Pod 的 request 值设置为:

resoureces:
  limits:
    cpu: "36"
    memory: 100Gi
  requests:
    cpu: "18"
    memory: 10Gi

集群中存在资源空闲的节点: Pod Event 却报没有足够资源可调度:

二、调度过程分析

在调度器调度过程中,调度器的 NodeResources 预选算法会计算出待调度 Pod 的 requests 值是否满足节点可调度资源(allocatable),不满足则筛选掉该节点,并打印出 insufficient xxx 的 event。

*** pkg/scheduler/framework/plugins/noderesources/fit.go ***

上图代码中,节点的 allocatable 可调度资源是从 nodeInfo 这个对象中取出。直观上看,nodeInfo 就应该和我们用 kubectl describe <node name> 看到的信息一致,节点中存在空闲资源的节点, 不应该在 NodeResources 预选阶段就打印出 insufficient xxx 资源不足的 event。

后经过对调度器源码分析,发现 nodeInfo 并不仅仅统计的是当前 node 的 allocatable 值,调度器会从 Nominated queue中取出 Pod,加到 nodeInfo 的 podList中,进行后续的资源计算。

*** pkg/scheduler/core/generic_scheduler.go ***

因此,调度时不仅仅要考虑节点的 allocatable 值,还要考虑是否有 Pod 的 nominated Node 绑定了该节点:

# kubectl get pod -A -owide | grep 10.123.2.135 | grep -i pending
test-ns test-pods-rjqngl     0/1   Pending    0  15d   <none>  <none>  10.123.2.135  1/1
test-ns test-pods-retbgf     0/1   Pending    0  15d   <none>  <none>  10.123.2.135  1/1

集群中有 Pod 的nominated Node 绑定了空闲节点,导致调度时该节点资源不足,无法通过 NodeResources 预选算法。 同时,因为集群中的 Pod PriorityClass 优先级相同,新的 Pod 无法抢占旧的 nominated Pod,最终调度失败,当 我们将新 Pod 的优先级调高后,发现集群中的这些空闲节点被利用了起来。

三、结论

Nominated 状态的 Pod 常常被我们忽略,而调度器调度时不仅仅考虑节点当前的 allocatable 值,还会考虑节点所绑定的 Nominated Pod 所占用的资源。 在分析 Pod 调度失败问题时,分享几个非常实用的命令方便问题的排查:

动态调整调度器日志级别

  1. 登录到 scheduler 所在主机或者 pod
  2. 执行如下命令,设置日志级别,例如设置为级别"4"
  3. 收集到所需日志后,运行相同命令把日志级别设置为2
$ curl -X PUT http://localhost:10251/debug/flags/v -d "4"

scheduler日志导出

  1. 通过 kube-scheduler 的 endpoint 找到调度器主节点,然后 ps -ef | grep scheuduler 找到调度器的 pid

  2. 给 kube-scheduler 进程发送 SIGUSR2 信号,会在日志中 dump 出 cache 和队列信息 kill -SIGUSR2

  3. 然后 docker inspect xxx | grep log 找到调度器的 log 文件位置。

  4. 如何找到 dump 的 node 缓存信息(节点 allocatable 配额、已使用 requests 值、绑定的 Pod 列表):1、日志中搜索"Dump of cached NodeInfo",2、日志中搜索 “Node Name: <节点名>”

  5. 如何找到 dump 的 Pending Pod 信息:日志中搜索"Dump of scheduling queue"