Pending 状态说明 Pod 还没有被调度到某个节点上,需要看下 Pod 事件进一步判断原因,比如:
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 3m (x106 over 33m) default-scheduler 0/4 nodes are available: 1 node(s) had no available volume zone, 2 Insufficient cpu, 3 Insufficient memory.
下面列举下可能原因和解决方法。
节点资源不够有以下几种情况:
如果判断某个 Node 资源是否足够? 通过 kubectl describe node 查看 node 资源情况,关注以下信息:
Allocatable: 表示此节点能够申请的资源总和
Allocated resources: 表示此节点已分配的资源 (Allocatable 减去节点上所有 Pod 总的 Request)
前者与后者相减,可得出剩余可申请的资源。如果这个值小于 Pod 的 request,就不满足 Pod 的资源要求,Scheduler 在 Predicates (预选) 阶段就会剔除掉这个 Node,也就不会调度上去。
如果 Pod 包含 nodeSelector 指定了节点需要包含的 label,调度器将只会考虑将 Pod 调度到包含这些 label 的 Node 上,如果没有 Node 有这些 label 或者有这些 label 的 Node 其它条件不满足也将会无法调度。参考官方文档:https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
如果 Pod 包含 affinity(亲和性)的配置,调度器根据调度算法也可能算出没有满足条件的 Node,从而无法调度。affinity 有以下几类:
如果节点上存在污点 (Taints),而 Pod 没有相应的容忍 (Tolerations),Pod 也将不会调度上去。通过 describe node 可以看下 Node 有哪些 Taints:
$ kubectl describe nodes host1
...
Taints: special=true:NoSchedule
...
污点既可以是手动添加也可以是被自动添加,下面来深入分析一下。
$ kubectl taint node host1 special=true:NoSchedule
node "host1" tainted
另外,有些场景下希望新加的节点默认不调度 Pod,直到调整完节点上某些配置才允许调度,就给新加的节点都加上 node.kubernetes.io/unschedulable 这个污点。
TaintNodesByCondition
特性进入 Beta 默认开启,controller manager 会检查 Node 的 Condition,如果命中条件就自动为 Node 加上相应的污点,这些 Condition 与 Taints 的对应关系如下:Conditon Value Taints
-------- ----- ------
OutOfDisk True node.kubernetes.io/out-of-disk
Ready False node.kubernetes.io/not-ready
Ready Unknown node.kubernetes.io/unreachable
MemoryPressure True node.kubernetes.io/memory-pressure
PIDPressure True node.kubernetes.io/pid-pressure
DiskPressure True node.kubernetes.io/disk-pressure
NetworkUnavailable True node.kubernetes.io/network-unavailable
解释下上面各种条件的意思:
OutOfDisk 为 True 表示节点磁盘空间不够了
Ready 为 False 表示节点不健康
Ready 为 Unknown 表示节点失联,在 node-monitor-grace-period 这么长的时间内没有上报状态 controller-manager 就会将 Node 状态置为 Unknown (默认 40s)
MemoryPressure 为 True 表示节点内存压力大,实际可用内存很少
PIDPressure 为 True 表示节点上运行了太多进程,PID 数量不够用了
DiskPressure 为 True 表示节点上的磁盘可用空间太少了
NetworkUnavailable 为 True 表示节点上的网络没有正确配置,无法跟其它 Pod 正常通信
另外,在云环境下,比如腾讯云 TKE,添加新节点会先给这个 Node 加上 node.cloudprovider.kubernetes.io/uninitialized 的污点,等 Node 初始化成功后才自动移除这个污点,避免 Pod 被调度到没初始化好的 Node 上。
可能是低版本 kube-scheduler 的 bug, 可以升级下调度器版本。
检查 maser 上的 kube-scheduler 是否运行正常,异常的话可以尝试重启临时恢复。
有时候服务部署成功运行过,但在某个时候节点突然挂了,此时就会触发驱逐,创建新的副本调度到其它节点上,对于已经挂载了磁盘的 Pod,它通常需要被调度到跟当前节点和磁盘在同一个可用区,如果集群中同一个可用区的节点不满足调度条件,即使其它可用区节点各种条件都满足,但不跟当前节点在同一个可用区,也是不会调度的。为什么需要限制挂载了磁盘的 Pod 不能漂移到其它可用区的节点?试想一下,云上的磁盘虽然可以被动态挂载到不同机器,但也只是相对同一个数据中心,通常不允许跨数据中心挂载磁盘设备,因为网络时延会极大的降低 IO 速率。