排查自定义 ComputeClass 问题

本文档可帮助您排查以下问题:GKE 工作负载无法调度到由自定义 ComputeClass 定义的节点上,或者集群自动扩缩器未预配预期的机器类型。

本文档适用于使用自定义 ComputeClass 在 GKE 中管理工作负载调度和节点池自动创建的应用开发者、平台管理员和运维人员。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务。

主要概念

为帮助您排查问题,请确保您熟悉以下 GKE 组件和机制:

  • 自定义 ComputeClass:一种 GKE 专用资源,可让您为自动扩缩定义节点配置的优先级列表。如需了解详情,请参阅自定义 ComputeClass 简介。

  • 集群自动扩缩器:根据工作负载需求自动在集群中添加或移除节点的组件。如需了解详情,请参阅 GKE 集群自动扩缩简介。

  • 节点池自动创建:GKE 集群自动扩缩器会根据工作负载要求自动创建和管理节点池。如需了解详情,请参阅节点池自动创建简介。

  • 回退逻辑:一种机制,集群自动扩缩器会尝试先预配与最高优先级规则匹配的节点。如需了解详情,请参阅选择回退计算优先级。

按症状排查问题

本文档按顺序组织了问题排查步骤,从基本检查到更高级的配置。为了更全面地诊断问题,我们建议您按顺序执行以下步骤。或者,如果您遇到特定问题,请参阅下表中的相关链接:

症状 问题排查步骤
请求自定义 ComputeClass 的 Pod 卡在 Pending 状态
集群自动扩缩器未创建与自定义 ComputeClass 匹配的新节点
集群自动扩缩器创建默认机器类型,而不是专用类型 分析自动扩缩器的回退行为
kubectl describe computeclass 命令的输出显示健康状况不佳 验证自定义 ComputeClass 配置
工作负载未迁移到优先级更高的节点 验证集群自动扩缩器的总体健康状况
GPU 或 Spot 虚拟机工作负载存在调度问题

超出范围的问题

本文档未解决以下问题:

  • 一般 GKE 网络问题,例如 Pod 到 Pod 的连接性或服务负载均衡。
  • 与 Pod 横向自动扩缩器 (HPA) 或 Pod 纵向自动扩缩器 (VPA) 相关的问题。
  • 与自定义 ComputeClass 机制无关的问题,例如应用级错误或与调度限制无关的 PersistentVolume 问题。
  • 与 ComputeClass 回退逻辑没有直接关联的配额或资源不可用问题。

识别占位变量

如需自定义本文档中的命令,请在 Variable 列中输入您的特定值。修改后的值会自动在所有代码块和命令中同步。

变量 说明
PROJECT_ID 您的 Google Cloud 项目 ID。
LOCATION 集群所在的 Compute Engine 区域或可用区。
CLUSTER_NAME 集群的名称。
NODE_POOL_NAME 要检查的节点池的名称(如果适用于 Standard 集群)。
CUSTOM_COMPUTECLASS_NAME Pod 请求的自定义 ComputeClass 的名称。
NAMESPACE 无法调度的 Pod 的命名空间。
POD_NAME 无法调度的 Pod 的名称。

准备工作

如需获得执行本文档中的任务所需的权限,请让您的管理员为您授予 Google Cloud 项目的以下 IAM 角色:

  • 访问 GKE 集群:Kubernetes Engine Cluster Viewer (roles/container.viewer)。
  • 查看日志:日志查看器 (roles/logging.viewer)。
  • 管理 GKE 集群:Kubernetes Engine Admin (roles/container.admin)。

如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。

您也可以通过自定义角色或其他预定义角色来获取所需的权限。

如需配置 kubectl 以与集群通信,请运行以下命令:

  gcloud container clusters get-credentials CLUSTER_NAME
      --location LOCATION
      --project PROJECT_ID

执行基本诊断检查

验证核心组件是否已正确配置,以及集群是否支持自定义 ComputeClass。

验证 Pod 状态和选择器

确认 Pod 处于 Pending 状态,并且正确请求了自定义 ComputeClass。

  1. 列出处于 Pending 状态的 Pod:

    kubectl get pods --all-namespaces -o wide | grep Pending
    
  2. 检查 Pod 规范中的 nodeSelector 字段:

    kubectl get pod POD_NAME
        -n NAMESPACE
        -o jsonpath='{.spec.nodeSelector}'
    

评估结果

  • 输出显示标签:nodeSelector 字段已正确配置 cloud.google.com/compute-class 标签。
  • 输出未显示标签:
    • 解读:工作负载部署配置中 cloud.google.com/compute-class 标签的 nodeSelector 字段可能不正确或缺失。
    • 解决方法:修改工作负载的 YAML 文件(例如 Deployment 或 Job),在 spec.template.spec 部分中添加 nodeSelector 字段。

验证集群版本兼容性

自定义 ComputeClass 需要 GKE 1.30.3-gke.1451000 版或更高版本。验证您的集群是否正在运行支持自定义 ComputeClass 的版本。

检查集群版本:

gcloud container clusters describe CLUSTER_NAME
    --location LOCATION
    --format="value(currentMasterVersion)"

评估结果

  • 1.30.3-gke.1451000 版或更高版本:您的集群版本支持自定义 ComputeClass。
  • 低于 1.30.3-gke.1451000 的版本:
    • 解读:您的集群尚未升级到支持自定义 ComputeClass 的版本。
    • 解决方法:您必须升级集群才能使用自定义 ComputeClass。

验证为自定义 ComputeClass 预配的节点

如需检查集群中是否有与您的 ComputeClass 关联的节点,请列出与 ComputeClass 标签匹配的节点:

kubectl get nodes -l cloud.google.com/compute-class=CUSTOM_COMPUTECLASS_NAME

如果输出为 No resources found,则表示没有与 ComputeClass 关联的节点。验证工作负载是否实际选择了该 ComputeClass,并检查自动扩缩事件是否存在扩容错误。

验证自定义 ComputeClass 配置

自定义 ComputeClass 资源中的配置错误可能会阻止 Pod 进行调度,或阻止 GKE 正确预配节点。

检查 ComputeClass 的健康状况和状态

验证 GKE 是否报告自定义 ComputeClass 运行正常。

  1. 列出所有 ComputeClass 资源:

    kubectl get computeclass
    
  2. 描述特定的 ComputeClass 资源:

    kubectl describe computeclass CUSTOM_COMPUTECLASS_NAME
    

评估结果

  • 健康状况显示 True:自定义 ComputeClass 运行正常。以下是健康状况良好的自定义 ComputeClass 的示例:

    Status:
      Conditions:
        Last Transition Time:  2024-01-19T17:18:48Z
        Message:               CCC is healthy.
        Reason:                Health
        Status:                True
        Type:                  Health
    
  • 健康状态显示为False:

    • 解读:自定义 ComputeClass 运行状况不佳。查看输出中的 Message 和 Reason 字段,以确定问题。
    • 解决方法:请执行与输出中的 Reason 字段对应的操作:
      • NodePoolNotExist:确保引用的节点池存在,或更新 ComputeClass 以引用现有节点池。
      • ReservationUnusable:检查所引用预留的配置和使用情况。
      • Invalid machine type:更新 ComputeClass,以使用集群所在区域或可用区支持的机器类型。

验证 unsatisfiable 政策

whenUnsatisfiable 字段决定了无法满足任何优先级规则时的行为。

查看政策:

kubectl get computeclass CUSTOM_COMPUTECLASS_NAME -o yaml

检查输出中的 spec.whenUnsatisfiable 字段。此字段可以具有以下值之一:

  • DoNotScaleUp:如果无法创建首选节点,Pod 会保持 Pending 状态。
  • ScaleUpAnyway:如果首选节点不可用,Pod 可能会在默认节点类型(例如 E2 系列)上运行。

评估结果

whenUnsatisfiable 政策的效果取决于其值:

  • 如果值为 DoNotScaleUp:
    • 解读:当无法满足任何优先级规则时,这是预期行为,可能是由于资源不可用或配额限制。如果 Pod 必须等待特定硬件,则此值正确。
    • 解决方法:如果运行工作负载比在特定硬件上运行更重要,请将政策更改为 ScaleUpAnyway。
  • 如果值为 ScaleUpAnyway:
    • 解读:这是预期行为。GKE 正在回退到默认节点类型,因为首选节点不可用。
    • 解决方法:如果 Pod 不得在默认节点类型上运行,请将政策更改为 DoNotScaleUp。
  • 默认行为:如果您未指定 whenUnsatisfiable 字段的值,并且使用的是 1.33 之前的 GKE 版本,则政策默认为 ScaleUpAnyway。

以下示例展示了如何通过修改 ComputeClass 清单中的 whenUnsatisfiable 字段来更新政策:

apiVersion: cloud.google.com/v1
kind: ComputeClass
metadata:
  name: CUSTOM_COMPUTECLASS_NAME
spec:
  # ... other fields
  whenUnsatisfiable: DoNotScaleUp # or ScaleUpAnyway

检查 Pod 调度限制条件

确保您的 Pod 规范与自定义 ComputeClass 预配的节点的属性兼容。

验证 Pod 资源请求

检查 Pod 的 CPU、内存和 GPU 请求是否可以由自定义 ComputeClass 的 priorities 字段中定义的至少一种机器类型满足。

  1. 获取 Pod 资源请求:

    kubectl get pod POD_NAME
        -n NAMESPACE
        -o jsonpath='{.spec.containers[*].resources.requests}'
    

    检查 cpu、memory 和 GPU 请求(例如 nvidia.com/gpu)的输出。

  2. 将这些请求与自定义 ComputeClass 的 priorities 字段中定义的机器类型进行比较:

    kubectl get computeclass CUSTOM_COMPUTECLASS_NAME
        -o jsonpath='{.spec.priorities}'
    

    检查输出中是否存在 machineType 或 machineFamily 字段。对于自定义 ComputeClass 中的每种机器类型,请在机器类型文档中查看其规范,并验证其可分配资源是否大于 Pod 的请求。

评估结果

  • 资源兼容:Pod 的资源请求小于或等于 ComputeClass 中至少一种机器类型的可分配资源。
  • 资源超出容量:

    • 解读:Pod 无法调度,因为 ComputeClass 中没有任何机器类型提供足够的 CPU、内存或 GPU。如果 nodePoolAutoCreation 字段设置为 true,并且 Pod 的内存请求超出了自动创建的节点池的限制,也可能会发生这种情况。
    • 解决方案:调整 Pod 的资源请求或自定义 ComputeClass 的机器类型:
      • 减少 Pod 资源请求:如果资源请求较高,请降低工作负载 YAML 文件中的 cpu、memory 或 gpu 值。
      • 更改为更大的机器类型:如果 Pod 的请求合理,请修改自定义 ComputeClass 清单中的 spec.priorities 字段,以包含可以满足 Pod 需求的更大的 machineType 或 machineFamily 选项。例如:
    spec:
      priorities:
      - machineType: n2d-highmem-96 # A larger machine type
        spot: true
      # ... other priorities
    

检查是否存在冲突的污点和容忍设置

为自定义 ComputeClass 创建的节点具有 cloud.google.com/compute-class=CUSTOM_COMPUTECLASS_NAME:NoSchedule 污点。GKE 会自动将此容忍设置添加到 Pod。

不过,GPU 等专用硬件具有额外的污点,例如 nvidia.com/gpu=present:NoSchedule 污点。如果您的 ComputeClass 使用具有专用硬件的节点,则 Pod 必须具有对这些污点的容忍设置,才能在这些节点上调度。

检查 Pod 的 tolerations 字段:

kubectl get pod POD_NAME
    -n NAMESPACE
    -o jsonpath='{.spec.tolerations}'

评估结果

  • 正确的容忍度:污点和容忍度配置正确。
  • 缺少容忍度:

    • 解读:缺少容忍度会导致 Pod 无法调度到具有专用硬件污点的节点上。例如,如果 ComputeClass 使用 GPU 节点,则 Pod 可能缺少 nvidia.com/gpu=present:NoSchedule 容忍度。如需了解 GPU 专属要求,请参阅验证 GPU 配置。
    • 解决方案:在 Pod 规范的 tolerations 字段中,添加必要的容忍度,以匹配由 ComputeClass 定义的节点上的污点。例如,对于 GPU 节点,请按如下方式为 nvidia.com/gpu=present:NoSchedule 污点添加容忍:

      spec:
      template:
      spec:
      tolerations:
      - key: "nvidia.com/gpu"
      operator: "Exists"
      effect: "NoSchedule"
      # ... other tolerations and Pod spec
      

分析集群自动扩缩器待处理 Pod 指标

适用的 GKE 版本:1.37 及更高版本

如需了解请求特定 ComputeClass 的 Pod 处于待处理状态的原因,请使用 Cloud Monitoring 中的 kubernetes.io/autoscaler/cluster_pending_pods_per_ccc 指标。此指标可帮助您查明问题是 ComputeClass 缺少合适的节点、预配问题,还是 Pod 配置固有的问题。此指标显示集群自动扩缩器正在处理的 Pod 数量,按 ComputeClass、处于待处理状态的原因以及是系统 Pod 还是用户 Pod 进行细分。

查询步骤

如需在 Google Cloud 控制台中查询该指标,请执行以下步骤:

  1. 在 Google Cloud 控制台中,前往 Metrics Explorer 页面。
  2. 选择资源类型:k8s_entity。
  3. 选择指标:kubernetes.io/autoscaler/cluster_pending_pods_per_ccc。
  4. 添加过滤条件:entity_type = ComputeClass。
  5. 为您的特定 ComputeClass 添加过滤条件:entity_name = "COMPUTECLASS_NAME"。
    • 如需查看未使用任何 ComputeClass 的 Pod,请使用 entity_name = "" 进行过滤。
  6. 按 metric.labels.reason 分组,以查看这些 Pod 的自动扩缩器状态。您还可以使用 metric.labels.type 键标签对 Pod 进行分组。

PromQL 查询示例

如需查找请求“COMPUTECLASS_NAME”ComputeClass 的待处理用户 Pod 的状态,请使用以下 PromQL 查询:

sum by (reason) (
  kubernetes_io:autoscaler_cluster_pending_pods_per_ccc{
    monitored_resource="k8s_entity",
    entity_type="ComputeClass",
    entity_name="COMPUTECLASS_NAME",
    type="user_pod"
  }
)

指标原因

metric.labels.reason 键标签的输出可能包含以下内容:

  • unable_to_provision:集群自动扩缩器被屏蔽。由于无法创建新节点,因此无法调度 ComputeClass 的处于此状态的 Pod。查看控制平面中的集群自动扩缩器日志,详细了解 ComputeClass 定义中的缺货、配额或配置错误。 此外,请查看集群自动扩缩器可见性事件。

  • provisioning_in_progress:已针对应满足 ComputeClass 要求的节点触发扩容。如果 Pod 仍留在此处,则节点创建或就绪可能会出现延迟。

  • unprocessed:集群自动扩缩器尚未评估这些 Pod。如果该值持续偏高,可能表示自动扩缩器存在延迟。

  • no_action_taken:集群自动扩缩器已决定不针对这些 Pod 进行扩缩。此行为可能是由于 ComputeClass 的节点类型无法满足 Pod 限制条件,或存在其他集群级限制。检查 Pod 规范 (kubectl describe pod) 和集群自动扩缩器日志。

分析节点预配失败

适用的 GKE 版本:1.37 及更高版本

如需检查 ComputeClass 的当前健康状况,请参阅验证 ComputeClass 健康状况。如果您发现与 ComputeClass 关联的 Pod 处于 unable_to_provision 状态,则表示集群自动扩缩器未预配符合 ComputeClass 要求的新节点。您可以使用 kubernetes.io/autoscaler/cluster_node_provisioning_failed_attempts_count_per_ccc Cloud Monitoring 指标来诊断根本原因。

  1. 在 Google Cloud 控制台中,依次前往监控和 Metrics Explorer。
  2. 将资源类型选择为 k8s_entity。
  3. 选择指标 kubernetes.io/autoscaler/cluster_node_provisioning_failed_attempts_count_per_ccc。
  4. 添加过滤条件:resource.labels.entity_type = ComputeClass。
  5. 为您的特定 ComputeClass 添加过滤条件:entity_name = "CUSTOM_COMPUTECLASS_NAME"。
    • 如需查看未使用任何 ComputeClass 的 Pod,请使用 entity_name = "" 进行过滤。
  6. 在分组依据部分,选择 metric.labels.reason 和 resource.labels.entity_name。
  7. 选择聚合器,例如 rate 或 delta。

系统会显示失败率或失败率变化,并按原因细分。

解读失败原因

metric.labels.reason 字段可让您深入了解节点创建失败的原因。通过找出失败的主要原因,您可以采取纠正措施。

可能的原因包括:

原因 说明 潜在纠正措施
QUOTA_EXCEEDED 已达到 Google Cloud 配额上限(例如 CPU、磁盘或 IP 地址)。查看项目配额。 申请增加配额。
RESOURCE_POOL_EXHAUSTED Compute Engine 不可用;可用区中没有足够的容量来满足所请求的资源。 请尝试其他机器类型或可用区。修改 ComputeClass,以添加后备机器类型或可用区。使用预留。
IP_SPACE_EXHAUSTED 节点子网已用尽可用 IP 地址。 扩展子网的主要 IP 地址范围。
PERMISSIONS_ERROR GKE 服务账号缺少创建资源(例如实例、磁盘)所需的 IAM 权限。 向 GKE 服务账号授予所需角色。
VM_EXTERNAL_IP_ACCESS_POLICY_CONSTRAINT 组织政策 (constraints/compute.vmExternalIpAccess) 会阻止创建具有外部 IP 的节点(如已配置)。 检查并修改组织政策或 ComputeClass 节点配置。
INVALID_RESERVATION 配置的 Compute Engine 预留无效、配置错误或与节点请求不匹配。 检查预留设置和 ComputeClass 定义。
RESERVATION_NOT_FOUND 指定的 Compute Engine 预留名称不存在。 验证 ComputeClass 中的预留名称。
RESERVATION_NOT_READY 目标预留尚未生效或仍在预配中。 等待预留生效。
RESERVATION_CAPACITY_EXCEEDED 预留已满,无法满足请求。 请增加预留大小或使用其他机器类型。
RESERVATION_INCOMPATIBLE 节点配置(例如机器类型或可用区)与预留的属性不匹配。 使 ComputeClass 节点规范与预留的属性保持一致。
AUTOMATIC_RESERVATIONS_NOT_AVAILABLE 尝试使用自动预留时出现问题。 检查日志;您可能需要与 Cloud Customer Care 联系。
AUTOMATIC_RESERVATIONS_NO_CAPACITY 自动预留容量不足。 可能需要切换到手动预留或不同的机器类型。
UNSUPPORTED_TPU_CONFIGURATION 所请求的 TPU 配置无效,或者在所选可用区或项目中不受支持。 查看 TPU 文档和 ComputeClass。
GkePersistentOperationError 在节点创建过程中,GKE 控制平面内发生了持续性错误。 与 Cloud Customer Care 团队联系。
OTHER 不属于其他类别的故障的统称。 如需了解详情,请查看控制平面上的集群自动扩缩器日志。

节点池配置(Standard 集群)

在 GKE Standard 集群中,手动创建的节点池必须带有标签和污点,才能与自定义 ComputeClass 搭配使用。

验证节点池标签和污点

  1. 确定自定义 ComputeClass 中的节点池。如果自定义 ComputeClass 使用 nodePools 字段,请记下列出的节点池的名称:

    kubectl get computeclass CUSTOM_COMPUTECLASS_NAME -o yaml
    
  2. 对于您确定的每个节点池,请验证其配置:

    gcloud container node-pools describe NODE_POOL_NAME
        --cluster CLUSTER_NAME
        --location LOCATION
        --format="yaml(config.labels, config.taints)"
    

评估结果

  • 节点池已正确配置:节点池具有标签 cloud.google.com/compute-class: CUSTOM_COMPUTECLASS_NAME 和污点 cloud.google.com/compute-class=CUSTOM_COMPUTECLASS_NAME:NoSchedule。
  • 节点池配置错误:

    • 解读:节点池未配置与自定义 ComputeClass 关联所需的标签和污点。
    • 解决方法:更新节点池以添加标签和污点:

      1. 添加或更新节点标签:

        gcloud container node-pools update NODE_POOL_NAME \
            --cluster=CLUSTER_NAME --location=LOCATION \
            --node-labels=cloud.google.com/compute-class=CUSTOM_COMPUTECLASS_NAME
        
      2. 添加或更新节点污点:

        gcloud container node-pools update NODE_POOL_NAME \
            --cluster=CLUSTER_NAME --location=LOCATION \
            --node-taints=cloud.google.com/compute-class=CUSTOM_COMPUTECLASS_NAME:NoSchedule
        

验证节点池自动创建配置

对于 nodePoolAutoCreation 设置为 true 的 Autopilot 集群和 Standard 集群,必须正确配置节点池自动创建功能。

验证是否已启用节点池自动创建

  1. 检查自定义 ComputeClass 中的 nodePoolAutoCreation.enabled 字段是否设置为 true:

    kubectl get computeclass CUSTOM_COMPUTECLASS_NAME -o yaml
    
  2. 检查集群上是否启用了节点池自动创建功能:

    gcloud container clusters describe CLUSTER_NAME
        --location LOCATION
        --format="value(autoscaling.enableNodeAutoprovisioning)"
    

如果其中任一功能处于停用状态,节点池自动创建功能将不会为您的自定义 ComputeClass 创建新的节点池。

评估结果

  • 已启用节点池自动创建:在 ComputeClass 中,nodePoolAutoCreation.enabled 字段设置为 true,并且在集群级启用了节点自动预配。
  • 节点池自动创建已停用:

    • 解读:如果 ComputeClass 中 nodePoolAutoCreation.enabled 字段的值为 false 或缺失,或者如果集群级节点自动预配处于停用状态,则节点池自动创建处于停用状态。
    • 解决方案:启用节点池自动创建:

      1. 修改自定义 ComputeClass YAML 文件,以添加 nodePoolAutoCreation: enabled: true:

        spec:
          # ... priorities
          nodePoolAutoCreation:
            enabled: true
        
      2. 在集群级启用节点池自动创建并配置资源限制:

        gcloud container clusters update CLUSTER_NAME --location LOCATION \
          --enable-autoprovisioning \
          --autoprovisioning-min-cpu=MIN_CPU \
          --autoprovisioning-max-cpu=MAX_CPU \
          --autoprovisioning-min-memory=MIN_MEMORY \
          --autoprovisioning-max-memory=MAX_MEMORY
        

检查节点池自动创建的资源限制

节点池自动创建功能对 CPU 和内存有集群级限制。如果集群的当前用量加上新节点的资源超过这些限制,则节点池自动创建不会预配新节点。

  1. 查看资源限制:

    gcloud container clusters describe CLUSTER_NAME
        --location LOCATION
    --format="value(autoscaling.resourceLimits)"
    

    输出会列出 CPU 和内存(以 GB 为单位)的 resourceType、minimum 和 maximum 字段。

  2. 查看自定义 ComputeClass 优先级中的机器类型。如需查看其 CPU 和内存规格,请参阅机器类型文档。

  3. 确定集群中所有节点的当前总 CPU 和内存容量。当前容量加上潜在新节点的资源之和不得超过节点池自动创建的上限。

评估结果

  • 容量充足:集群在资源限制范围内具有足够的 CPU 和内存容量,可供节点池自动创建功能预配新节点。
  • 超出限制:

    • 解读:节点池自动创建功能无法预配新节点,因为集群已达到 CPU 或内存限制,或者限制设置得太低,无法满足 ComputeClass 中的机器类型要求。
    • 解决方法:提高节点池自动创建的资源限制:

      1. 确定新的上限,以考虑当前用量和未来增长,包括自定义 ComputeClass 中最大的机器类型。

      2. 更新节点池自动创建的资源限制。您可以在一个命令中设置多个资源:

        gcloud container clusters update CLUSTER_NAME --location LOCATION \
          --set-nap-resource-limits resourceType=cpu,maximum=NEW_MAX_CPU \
          --set-nap-resource-limits resourceType=memory,maximum=NEW_MAX_GB
        

分析自动扩缩器回退行为

本部分可帮助您调查外部因素,了解集群自动扩缩器为何可能会跳过首选选项并使用后备选项,或无法扩容。

自定义 ComputeClass 使用优先级后备逻辑。如果 Pod 未在与最高优先级规则匹配的节点上调度,通常是因为资源不可用或项目配额等限制。当 GKE 无法预配与特定优先级规则匹配的节点时(例如,由于 Compute Engine 出现 ZONE_RESOURCE_POOL_EXHAUSTED 或 QUOTA_EXCEEDED 错误),集群自动扩缩器会立即尝试 priorities 列表中的下一个规则。在 GKE 回退到下一个优先级之前,没有等待期,但使用 TPU 或 Flex Start 配置模型时除外,它们支持可配置的延迟。

检查资源是否不可用

通过检查集群自动扩缩器日志或 Compute Engine 托管式实例组 (MIG) 错误,验证指定可用区中的资源是否不可用。

方法 1:检查集群自动扩缩器可见性事件

在 Google Cloud 控制台中,前往 Cloud Logging > Logs Explorer,然后运行以下查询,查找可能表明资源不可用的自动扩缩器事件:

resource.type="k8s_cluster"
resource.labels.location="LOCATION"
resource.labels.cluster_name="CLUSTER_NAME"
log_id("container.googleapis.com/cluster-autoscaler-visibility")
jsonPayload.noScaleUpReason.messageId="no.scale.up.nap.resource.exhausted"

方法 2:检查 MIG 错误

您可以在 Google Cloud 控制台中或使用 Cloud Logging 查询来检查 MIG 错误。

  • 使用 Google Cloud 控制台:

    1. 在 Google Cloud 控制台中,前往 Compute Engine > 实例组。
    2. 找到与无法扩容的节点池对应的 MIG。
    3. 点击 MIG 名称,然后前往错误标签页。查找指示资源耗尽的消息。
  • 使用 Cloud Logging 查询:

    1. 在 Google Cloud 控制台中,前往 Cloud Logging > Logs Explorer。
    2. 运行以下查询,检查 MIG 是否出现资源耗尽错误:
    resource.type="gce_instance"
    log_id("cloudaudit.googleapis.com/activity")
    protoPayload.status.message:("ZONE_RESOURCE_POOL_EXHAUSTED" OR "does not have enough resources available to fulfill the request" OR "resource pool exhausted" OR "does not exist in zone")
    

评估结果

  • 资源可用:如果日志未显示 ZONE_RESOURCE_POOL_EXHAUSTED 消息,则资源不可用不太可能是扩容失败的原因。
  • 资源不可用:

    • 解读:节点预配失败,原因可能是该可用区中对特定机器类型(尤其是 Spot 虚拟机或 GPU)的临时需求较高,或者 Pod 受 PersistentVolume 亲和性限制,无法访问资源不可用的可用区。
    • 解决方案:资源不可用是暂时性的,但您可以通过在配置中添加灵活性来提高恢复能力:

      • 使机器类型多样化:确保自定义 ComputeClass 中的 spec.priorities 字段包含多个机器类型或系列作为后备:

        spec:
          priorities:
          - machineFamily: c3  # Highest priority
          - machineFamily: n2d # Fallback option
          - machineFamily: e2  # Lowest priority
        
      • 使用区域级集群:如果集群是可用区级集群,则容易受到该单个可用区中资源不可用的影响。使用区域级集群后,集群自动扩缩器会尝试在区域内可能具有可用容量的其他可用区中预配节点。

      • 使用 Compute Engine 预留:对于无法容忍延迟的关键工作负载,请创建 Compute Engine 预留,以帮助确保特定机器类型的容量。

验证项目配额

确认您的项目有足够的配额来支持新节点所需的资源,例如 CPU、GPU 和 IP 地址。

  1. 检查自动扩缩器日志中是否存在配额错误。使用 Cloud Logging 在自动扩缩器可见性事件中搜索与配额相关的出错提示:

    resource.type="k8s_cluster"
    resource.labels.location="LOCATION"
    resource.labels.cluster_name="CLUSTER_NAME"
    log_id("container.googleapis.com/cluster-autoscaler-visibility")
    jsonPayload.noScaleUpReason.messageId="no.scale.up.nap.quota.exceeded"
    

    或者,您也可以使用以下 Cloud Logging 查询来检查 MIG 中与配额相关的错误日志:

    resource.type="gce_instance"
    protoPayload.methodName:"compute.instances.insert"
    protoPayload.status.message:"QUOTA_EXCEEDED"
    severity=ERROR
    
  2. 在 Google Cloud 控制台中查看配额:

    1. 在 Google Cloud 控制台中,前往 IAM 和管理 > 配额。
    2. 过滤出 Compute Engine API 服务。
    3. 检查 GKE 集群所在区域的相关指标(例如 CPU、GPU [所有类型] 和正在使用的 IP 地址)的使用情况。验证当前用量未达到上限。

评估结果

  • 配额低于限制:如果配额用量低于配额限制,并且日志中未发现 QUOTA_EXCEEDED 错误,则配额限制不会阻止扩容。
  • 超出配额:
    • 解读:由于 CPU、GPU、IP 地址或 MIG 等资源的配额不足,节点预配失败。
    • 解决方法:如果您的项目已达到配额上限,请申请增加配额。

高级配置

GPU、Spot 虚拟机和 Compute Engine 预留等配置有其各自的特定要求和潜在故障点,需要进行检查。

验证 GPU 配置

对于用于预配 GPU 节点的自定义 ComputeClass,请验证自定义 ComputeClass 中的 GPU 配置,并确保 Pod 具有必需的 nvidia.com/gpu 容忍度。

  1. 检查自定义 ComputeClass 的 YAML,看看优先级规则中是否有 gpu 块:

    kubectl get computeclass CUSTOM_COMPUTECLASS_NAME -o yaml
    

    gpu 块应指定 type 字段和 count 字段,例如:

    priorities:
    - machineType: a2-highgpu-1g
      gpu:
        type: nvidia-tesla-a100
        count: 1
    
  2. 检查 Pod 的 GPU 容忍度。任何需要调度到 GPU 节点上的 Pod 都必须具有 nvidia.com/gpu 容忍设置,即使该 Pod 本身不请求 GPU 也是如此。

    kubectl get pod POD_NAME -n NAMESPACE -o jsonpath='{.spec.tolerations}'
    

    在 spec.tolerations 字段下检查容忍度。

评估结果

  • GPU 配置正确:如果 ComputeClass 定义了 GPU type 和 count,并且 Pod 包含 nvidia.com/gpu 容忍度,则 GPU 配置正确。以下显示了所需的容忍度:

    tolerations:
    - key: "nvidia.com/gpu"
      operator: "Exists"
      effect: "NoSchedule"
    
  • GPU 配置错误:

    • 解读:Pod 可能缺少所需的 nvidia.com/gpu 容忍度,ComputeClass 可能因 GPU 字段不匹配而运行状况不佳,或者 GKE 版本可能无法正确处理 GPU 配置。
    • 解决方法:请执行以下操作之一:
      • 修改工作负载的 YAML 文件,以包含强制性 GPU 容忍度,然后重新应用该 YAML 文件。
      • 升级 GKE 集群。如果自定义 ComputeClass 运行状况不佳,并且问题与 GPU 字段有关,请检查已知问题并升级到已修复的 GKE 版本,例如 1.31.8-gke.1045000 或更高版本。

验证 Spot 虚拟机配置

如果您使用 Spot 虚拟机,请确保 spot: true 设置位于 ComputeClass 清单中的正确优先级规则中。此外,请务必了解集群自动扩缩器的价格计算逻辑。

检查 ComputeClass 清单:

kubectl get computeclass CUSTOM_COMPUTECLASS_NAME -o yaml

在输出中,在 spec.priorities 字段中查找 spot: true,例如:

priorities:
- machineFamily: n2d
  spot: true

在比较不同 Spot 虚拟机类型的费用时,集群自动扩缩器可能会使用 us-central1 的价格数据作为基准,这可能会导致在其他区域中做出看似非最优的选择。这是已知行为。

评估结果

  • Spot 虚拟机配置正确:如果指定了 spot: true 字段,并且集群自动扩缩器预配了 Spot 虚拟机,则配置会按预期运行。
  • Spot 虚拟机无法调度:

    • 解读:由于目标可用区中的资源不可用,或者由于集群自动扩缩器可能根据其 us-central1 价格模式选择其他虚拟机类型,需要 Spot 虚拟机的 Pod 可能无法在 Spot 虚拟机上调度。
    • 解决方法:

      • 如果您怀疑资源不可用,请参阅检查资源是否不可用。
      • 如需控制 Spot 虚拟机的选择,请在 priorities 字段中明确列出 machineType 条目,并按您所在区域的价格从低到高排序。此方法可让您直接控制回退顺序。例如:

        spec:
          priorities:
          - machineType: t2d-standard-48 # Cheapest in this region
            spot: true
          - machineType: n2d-standard-48 # Fallback Spot option
            spot: true
          - machineType: n2d-standard-48 # On-demand fallback
            spot: false
        

集群自动扩缩器的总体健康状况

本部分可帮助您检查可能与自定义 ComputeClass 配置不直接相关但可能影响其运行的问题。

检查是否存在并发操作

验证没有其他集群或节点池操作同时在进行。GKE 对并发操作有限制,这可能会阻止自动扩缩。

列出未处于 DONE 状态的正在进行的操作:

gcloud container operations list \
    --location=LOCATION \
    --filter='targetLink~"/clusters/CLUSTER_NAME" AND status!=DONE'

如果该命令返回任何操作,则可能正在进行集群升级、节点池创建或其他修改等操作。在完成此操作之前,自动扩缩事件可能会被阻止。

评估结果

  • 没有并发操作:如果 list 命令返回一个空列表,则表示集群自动扩缩器未受到任何操作的阻塞。
  • 发现的并发操作次数:

    • 解读:如果该命令列出了状态为 RUNNING 或 PENDING 的操作,则可能正在进行并发操作(例如集群升级或节点池修改),从而阻止自动扩缩。
    • 解决方法:等待正在进行的操作完成。您可以使用操作 ID 监控状态,方法如下:

      gcloud container operations wait OPERATION_ID --location LOCATION
      

      将 OPERATION_ID 替换为 list 命令输出中的 ID。阻塞操作完成后,集群自动扩缩器应恢复正常功能。

查看正在进行的迁移

如果您发现工作负载在优先级较高的节点可用时仍留在优先级较低的节点上,请验证是否已启用主动迁移。如果 ComputeClass 中的 activeMigration.optimizeRulePriority 字段设置为 false 或被省略,则当优先级较高的节点可用时,GKE 不会自动将工作负载迁移到这些节点。

  1. 如需检查 Pod 容忍度,请查看 spec.tolerations 字段。如果 Pod 具有与不同优先级多个节点池上的污点匹配的容忍度,则调度器可能会将其放置在优先级较低的节点上(如果该节点首先可用)。

    kubectl get pod POD_NAME -n NAMESPACE -o jsonpath='{.spec.tolerations[*]}{"\n"}'
    
  2. 如需检查是否已启用主动迁移,请检查 ComputeClass 清单中是否存在 spec.activeMigration.optimizeRulePriority 字段。

    kubectl get computeclass CUSTOM_COMPUTECLASS_NAME -o yaml
    

评估结果

  • 已启用主动迁移:如果 activeMigration.optimizeRulePriority 字段为 true,GKE 会尝试在优先级更高的节点可用时将工作负载迁移到这些节点。
  • 活跃迁移已停用或无效:

    • 解读:如果 activeMigration.optimizeRulePriority 字段为 false 或被省略,或者 Pod 容忍度过高,则当有更高优先级的节点可用时,工作负载仍会留在较低优先级的节点上。这样一来,工作负载便可调度到最先可用的较低优先级节点上。
    • 解决方法:如果您希望工作负载移至优先级较高的节点,请执行以下操作之一:

      • 使用更具体的调度限制(例如 nodeAffinity)来优先选择优先级较高的节点池。
      • 修改 ComputeClass 清单以设置 activeMigration.optimizeRulePriority: true,并应用 YAML 文件:

        spec:
          activeMigration:
            optimizeRulePriority: true
        

获取支持

后续步骤