更新时间:2023-12-07 GMT+08:00

工作负载异常:实例调度失败

问题定位

当Pod状态为“Pending”,事件中出现“实例调度失败”的信息时,可根据具体事件信息确定具体问题原因。事件查看方法请参见工作负载状态异常定位方法

排查思路

根据具体事件信息确定具体问题原因,如表1所示。

表1 实例调度失败

事件信息

问题原因与解决方案

no nodes available to schedule pods.

集群中没有可用的节点。

排查项一:集群内是否无可用节点

0/2 nodes are available: 2 Insufficient cpu.

0/2 nodes are available: 2 Insufficient memory.

节点资源(CPU、内存)不足。

排查项二:节点资源(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不能容忍这些污点,所以不可调度。

排查项五:检查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状态。

排查项七:检查everest插件是否工作正常

Failed to create pod sandbox: ...

Create more free space in thin pool or use dm.min_free_space option to change behavior

节点thinpool空间不足。

排查项八:检查节点thinpool空间是否充足

0/1 nodes are available: 1 Too many pods.

该节点调度的Pod超出上限。

检查项九:检查节点上调度的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调度到这个节点上,有两种方法:

  • 若该污点为用户自行添加,可考虑删除节点上的污点。若该污点为系统自动添加,解决相应问题后污点会自动删除。
  • Pod的定义中容忍这个污点,如下所示。详细内容请参见污点和容忍
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
      tolerations:
      - key: "key1"
        operator: "Equal"
        value: "value1"
        effect: "NoSchedule" 

排查项六:检查临时卷使用量

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容器引擎的节点:
    1. 查看节点上的本地镜像。
      crictl images -v
    2. 确认镜像无需使用,并通过镜像ID删除无需使用的镜像。
      crictl rmi {镜像ID}
  • 使用docker容器引擎的节点:
    1. 查看节点上的本地镜像。
      docker images
    2. 确认镜像无需使用,并通过镜像ID删除无需使用的镜像。
      docker rmi {镜像ID}

请勿删除cce-pause等系统镜像,否则可能导致无法正常创建容器。

方案二:扩容磁盘

扩容磁盘的操作步骤如下:

  1. 在EVS界面扩容数据盘。
  2. 登录CCE控制台,进入集群,在左侧选择“节点管理”,单击节点后的“同步云服务器”
  3. 登录目标节点。
  4. 使用lsblk命令查看节点块设备信息。

    这里存在两种情况,根据容器存储Rootfs而不同。

    • Overlayfs,没有单独划分thinpool,在dockersys空间下统一存储镜像相关数据。
      # lsblk
      NAME                MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
      sda                   8:0    0   50G  0 disk 
      └─sda1                8:1    0   50G  0 part /
      sdb                   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/sdb 
      lvextend -l+100%FREE -n vgpaas/dockersys
      resize2fs /dev/vgpaas/dockersys
    • Devicemapper,单独划分了thinpool存储镜像相关数据。
      # lsblk
      NAME                                MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
      sda                                   8:0    0   50G  0 disk 
      └─sda1                                8:1    0   50G  0 part /
      sdb                                   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/sdb 
        lvextend -l+100%FREE -n vgpaas/thinpool
      • 在节点上执行如下命令, 将新增的磁盘容量加到dockersys盘上。
        pvresize /dev/sdb 
        lvextend -l+100%FREE -n vgpaas/dockersys
        resize2fs /dev/vgpaas/dockersys

检查项九:检查节点上调度的Pod是否过多

0/1 nodes are available: 1 Too many pods.表示节点上调度的Pod过多,超出可调度的最大实例数。

创建节点时,在“高级配置”中可选择设置“最大实例数”参数,设置节点上可以正常运行的容器 Pod 的数目上限。该数值的默认值随节点规格浮动,您也可以手动设置。

您可以在“节点管理”页面,查看节点的“容器组(已分配/总额度)”参数列,检查节点已调度的容器是否达到上限。若已达到上限,可通过添加节点或修改最大实例数的方式解决。

您可通过以下方式修改“最大实例数”参数:

  • 默认节点池中的节点:通过重置节点时修改“最大实例数”
  • 自定义节点池中的节点:可修改节点池配置参数中的max-pods参数。