工作负载异常:实例调度失败
问题定位
当Pod状态为“Pending”,事件中出现“实例调度失败”的信息时,可根据具体事件信息确定具体问题原因。事件查看方法请参见工作负载状态异常定位方法。
排查思路
根据具体事件信息确定具体问题原因,如表1所示。
事件信息 |
问题原因与解决方案 |
---|---|
no nodes available to schedule pods. |
集群中没有可用的节点。 |
0/2 nodes are available: 2 Insufficient cpu. 0/2 nodes are available: 2 Insufficient memory. |
节点资源(CPU、内存)不足。 |
0/2 nodes are available: 1 node(s) didn't match node selector, 1 node(s) didn't match pod affinity rules, 1 node(s) didn't match pod affinity/anti-affinity. |
节点与Pod亲和性配置互斥,没有满足Pod要求的节点。 |
0/2 nodes are available: 2 node(s) had volume node affinity conflict. |
Pod挂载云硬盘存储卷与节点不在同一个可用区。 |
0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate. |
节点存在污点Tanits,而Pod不能容忍这些污点,所以不可调度。 |
0/7 nodes are available: 7 Insufficient ephemeral-storage. |
节点临时存储不足。 |
0/1 nodes are available: 1 everest driver not found at node |
节点上everest-csi-driver不在running状态。 |
Failed to create pod sandbox: ... Create more free space in thin pool or use dm.min_free_space option to change behavior |
节点thinpool空间不足。 |
0/1 nodes are available: 1 Too many pods. |
该节点调度的Pod超出上限。 |
排查项一:集群内是否无可用节点
登录CCE控制台,检查节点状态是否为可用。或使用如下命令查看节点状态是否为Ready。
$ kubectl get node NAME STATUS ROLES AGE VERSION 192.168.0.37 Ready <none> 21d v1.19.10-r1.0.0-source-121-gb9675686c54267 192.168.0.71 Ready <none> 21d v1.19.10-r1.0.0-source-121-gb9675686c54267
如果状态都为不可用(Not Ready),则说明集群中无可用节点。
解决方案:
- 新增节点,若工作负载未设置亲和策略,pod将自动迁移至新增的可用节点,确保业务正常。
- 排查不可用节点问题并修复,排查修复方法请参见集群可用,但节点状态为“不可用”?。
- 重置不可用的节点。
排查项二:节点资源(CPU、内存等)是否充足
0/2 nodes are available: 2 Insufficient cpu. CPU不足。
0/2 nodes are available: 2 Insufficient memory. 内存不足。
当“实例资源的申请量”超过了“实例所在节点的可分配资源总量”时,节点无法满足实例所需资源要求导致调度失败。
如果节点可分配资源小于Pod的申请量,则节点无法满足实例所需资源要求导致调度失败。
解决方案:
资源不足的情况主要解决办法是扩容,建议在集群中增加节点数量。
排查项三:检查工作负载的亲和性配置
当亲和性配置出现如下互斥情况时,也会导致实例调度失败:
例如:
workload1、workload2设置了工作负载间的反亲和,如workload1部署在Node1,workload2部署在Node2。
workload3部署上线时,既希望与workload2亲和,又希望可以部署在不同节点如Node1上,这就造成了工作负载亲和与节点亲和间的互斥,导致最终工作负载部署失败。
0/2 nodes are available: 1 node(s) didn't match node selector, 1 node(s) didn't match pod affinity rules, 1 node(s) didn't match pod affinity/anti-affinity.
- node selector 表示节点亲和不满足。
- pod affinity rules 表示Pod亲和不满足。
- pod affinity/anti-affinity 表示Pod亲和/反亲和不满足。
解决方案:
- 在设置“工作负载间的亲和性”和“工作负载和节点的亲和性”时,需确保不要出现互斥情况,否则工作负载会部署失败。
- 若工作负载配置了节点亲和性,需确保亲和的节点标签中supportContainer设置为true,否则会导致pod无法调动到节点上,查看事件提示如下错误信息:
No nodes are available that match all of the following predicates: MatchNode Selector, NodeNotSupportsContainer
节点标签为false时将会调度失败。
排查项四:挂载的存储卷与节点是否处于同一可用区
0/2 nodes are available: 2 node(s) had volume node affinity conflict. 存储卷与节点之间存在亲和性冲突,导致无法调度。
这是因为云硬盘不能跨可用区挂载到节点。例如云硬盘存储卷在可用区1,节点在可用区2,则会导致无法调度。
CCE中创建云硬盘存储卷,默认带有亲和性设置,如下所示:
kind: PersistentVolume apiVersion: v1 metadata: name: pvc-c29bfac7-efa3-40e6-b8d6-229d8a5372ac spec: ... nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: failure-domain.beta.kubernetes.io/zone operator: In values: -
解决方案:
重新创建存储卷,可用区选择与节点同一分区,或重新创建工作负载,存储卷选择自动分配。
排查项五:检查Pod污点容忍情况
0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate. 是因为节点打上了污点,不允许Pod调度到节点上。
查看节点的上污点的情况。如下则说明节点上存在污点。
$ kubectl describe node 192.168.0.37 Name: 192.168.0.37 ... Taints: key1=value1:NoSchedule ...
在某些情况下,系统会自动给节点添加一个污点。当前内置的污点包括:
- node.kubernetes.io/not-ready:节点未准备好。
- node.kubernetes.io/unreachable:节点控制器访问不到节点。
- node.kubernetes.io/memory-pressure:节点存在内存压力。
- node.kubernetes.io/disk-pressure:节点存在磁盘压力,此情况下您可通过节点磁盘空间不足的方案进行解决。
- node.kubernetes.io/pid-pressure:节点的 PID 压力。
- node.kubernetes.io/network-unavailable:节点网络不可用。
- node.kubernetes.io/unschedulable:节点不可调度。
- node.cloudprovider.kubernetes.io/uninitialized:如果kubelet启动时指定了一个“外部”云平台驱动, 它将给当前节点添加一个污点将其标志为不可用。在cloud-controller-manager初始化这个节点后,kubelet将删除这个污点。
解决方案:
要想把Pod调度到这个节点上,有两种方法:
排查项六:检查临时卷使用量
0/7 nodes are available: 7 Insufficient ephemeral-storage. 节点临时存储不足。
检查Pod是否限制了临时卷的大小,如下所示,当应用程序需要使用的量超过节点已有容量时会导致无法调度,修改临时卷限制或扩容节点磁盘可解决此问题。
apiVersion: v1 kind: Pod metadata: name: frontend spec: containers: - name: app image: images.my-company.example/app:v4 resources: requests: ephemeral-storage: "2Gi" limits: ephemeral-storage: "4Gi" volumeMounts: - name: ephemeral mountPath: "/tmp" volumes: - name: ephemeral emptyDir: {}
您可以通过kubectl describe node命令查询节点临时卷的容量(Capacity)和可使用量(Allocatable),并可查询节点已分配的临时卷申请值和限制值。
返回示例如下:
... Capacity: cpu: 4 ephemeral-storage: 61607776Ki hugepages-1Gi: 0 hugepages-2Mi: 0 localssd: 0 localvolume: 0 memory: 7614352Ki pods: 40 Allocatable: cpu: 3920m ephemeral-storage: 56777726268 hugepages-1Gi: 0 hugepages-2Mi: 0 localssd: 0 localvolume: 0 memory: 6180752Ki pods: 40 ... Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 1605m (40%) 6530m (166%) memory 2625Mi (43%) 5612Mi (92%) ephemeral-storage 0 (0%) 0 (0%) hugepages-1Gi 0 (0%) 0 (0%) hugepages-2Mi 0 (0%) 0 (0%) localssd 0 0 localvolume 0 0 Events: <none>
排查项七:检查everest插件是否工作正常
0/1 nodes are available: 1 everest driver not found at node。集群everest插件的everest-csi-driver 在节点上未正常启动。
检查kube-system命名空间下名为everest-csi-driver的守护进程,查看对应Pod是否正常启动,若未正常启动,删除该Pod,守护进程会重新拉起该Pod。
排查项八:检查节点thinpool空间是否充足
节点在创建时会绑定一个供kubelet及容器引擎使用的专用数据盘。若数据盘空间不足,将导致实例无法正常创建。
方案一:清理镜像
- 使用containerd容器引擎的节点:
- 查看节点上的本地镜像。
crictl images -v
- 确认镜像无需使用,并通过镜像ID删除无需使用的镜像。
crictl rmi {镜像ID}
- 查看节点上的本地镜像。
- 使用docker容器引擎的节点:
- 查看节点上的本地镜像。
docker images
- 确认镜像无需使用,并通过镜像ID删除无需使用的镜像。
docker rmi {镜像ID}
- 查看节点上的本地镜像。
请勿删除cce-pause等系统镜像,否则可能导致无法正常创建容器。
方案二:扩容磁盘
扩容磁盘的操作步骤如下:
- 在EVS界面扩容数据盘。
- 登录CCE控制台,进入集群,在左侧选择“节点管理”,单击节点后的“同步云服务器”。
- 登录目标节点。
- 使用lsblk命令查看节点块设备信息。
这里存在两种情况,根据容器存储Rootfs而不同。
- Overlayfs,没有单独划分thinpool,在dockersys空间下统一存储镜像相关数据。
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 8:0 0 50G 0 disk └─vda1 8:1 0 50G 0 part / vdb 8:16 0 200G 0 disk ├─vgpaas-dockersys 253:0 0 90G 0 lvm /var/lib/docker # 容器引擎使用的空间 └─vgpaas-kubernetes 253:1 0 10G 0 lvm /mnt/paas/kubernetes/kubelet # kubernetes使用的空间
在节点上执行如下命令, 将新增的磁盘容量加到dockersys盘上。
pvresize /dev/vdb lvextend -l+100%FREE -n vgpaas/dockersys resize2fs /dev/vgpaas/dockersys
- Devicemapper,单独划分了thinpool存储镜像相关数据。
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vda 8:0 0 50G 0 disk └─vda1 8:1 0 50G 0 part / vdb 8:16 0 200G 0 disk ├─vgpaas-dockersys 253:0 0 18G 0 lvm /var/lib/docker ├─vgpaas-thinpool_tmeta 253:1 0 3G 0 lvm │ └─vgpaas-thinpool 253:3 0 67G 0 lvm # thinpool空间 │ ... ├─vgpaas-thinpool_tdata 253:2 0 67G 0 lvm │ └─vgpaas-thinpool 253:3 0 67G 0 lvm │ ... └─vgpaas-kubernetes 253:4 0 10G 0 lvm /mnt/paas/kubernetes/kubelet
- 在节点上执行如下命令, 将新增的磁盘容量加到thinpool盘上。
pvresize /dev/vdb lvextend -l+100%FREE -n vgpaas/thinpool
- 在节点上执行如下命令, 将新增的磁盘容量加到dockersys盘上。
pvresize /dev/vdb lvextend -l+100%FREE -n vgpaas/dockersys resize2fs /dev/vgpaas/dockersys
- 在节点上执行如下命令, 将新增的磁盘容量加到thinpool盘上。
- Overlayfs,没有单独划分thinpool,在dockersys空间下统一存储镜像相关数据。
检查项九:检查节点上调度的Pod是否过多
0/1 nodes are available: 1 Too many pods.表示节点上调度的Pod过多,超出可调度的最大实例数。
创建节点时,在“高级配置”中可选择设置“最大实例数”参数,设置节点上可以正常运行的容器 Pod 的数目上限。该数值的默认值随节点规格浮动,您也可以手动设置。
您可以在“节点管理”页面,查看节点的“容器组(已分配/总额度)”参数列,检查节点已调度的容器是否达到上限。若已达到上限,可通过添加节点或修改最大实例数的方式解决。
您可通过以下方式修改“最大实例数”参数:
- 默认节点池中的节点:通过重置节点时修改“最大实例数”。
- 自定义节点池中的节点:可修改节点池配置参数中的max-pods参数。