使用 Kueue 管理 Ascend NPU 配额

本页介绍如何使用 Alauda Build of Kueue 来管理由 Ascend Device Plugin(作为 NPU Operator 的一部分随附)暴露的 Ascend NPU 资源配额。Kueue 将 huawei.com/Ascend910 及类似的 device-plugin 资源视为普通的可计数资源,因此适用于 CPU、内存和 Nvidia GPU 的同一 ClusterQueue / ResourceFlavor / LocalQueue 模型可以不加修改地应用于此场景。

前提条件

  • 你已安装 Alauda Build of Kueue cluster plugin。
  • 你已安装 Alauda Build of NPU Operator cluster plugin,并在部署表单中启用了 DriverAscend Device PluginAscend Docker Runtime 组件(默认情况下它们是启用的)。这三个开关会让集群将 huawei.com/Ascend910(或 huawei.com/Ascend310P)暴露为 Ascend 节点上的可调度扩展资源。有关完整操作步骤以及每个部署表单开关的含义,请参见 安装 NPU Operator
  • Ascend Device Plugin 正在报告节点上的 NPU 容量,例如 kubectl describe node <ascend-node> 会在 CapacityAllocatable 下同时显示 huawei.com/Ascend910: <N>
  • Alauda Container Platform Web CLI 已与你的集群建立通信。

操作步骤

1. 确定 NPU 节点标签

ResourceFlavor 通过 spec.nodeLabels 选择配额适用的节点池。NPU Operator 会向其管理的每个节点添加以下标签——请选择最适合你集群的一个:

标签示例适用场景
acceleratorhuawei-Ascend910所有 Ascend 910 节点共享同一个 flavor
accelerator-typemodule-910b-8你希望区分不同外形规格
node.kubernetes.io/npu.chip.name910B4你希望区分不同芯片代际

本页后续示例均使用 accelerator: huawei-Ascend910

2. 创建 Kueue 对象

创建一个绑定到 NPU 节点池的 ResourceFlavor、一个声明 NPU 配额的 ClusterQueue,以及一个位于用户提交作业命名空间中的 LocalQueue

apiVersion: kueue.x-k8s.io/v1beta2
kind: ResourceFlavor
metadata:
  name: ascend910-flavor
spec:
  nodeLabels:
    accelerator: huawei-Ascend910
---
apiVersion: kueue.x-k8s.io/v1beta2
kind: ClusterQueue
metadata:
  name: ascend910-cq
spec:
  namespaceSelector: {}
  resourceGroups:
  - coveredResources: ["huawei.com/Ascend910", "cpu", "memory"] 
    flavors:
    - name: ascend910-flavor
      resources:
      - name: "huawei.com/Ascend910"
        nominalQuota: 2
      - name: "cpu"
        nominalQuota: 8
      - name: "memory"
        nominalQuota: 16Gi
---
apiVersion: kueue.x-k8s.io/v1beta2
kind: LocalQueue
metadata:
  namespace: team-ascend
  name: ascend910-lq
spec:
  clusterQueue: ascend910-cq
  1. nodeLabels:将该 flavor 限定到由 NPU Operator 标记为 Ascend 910 的节点。请替换为与你的集群匹配的标签(参见上表)。
  2. coveredResources:将 device-plugin 资源与 CPU 和内存一起列出,以便在准入决策中对三者一并计入。
  3. nominalQuota:该队列在任意时刻可分配的 NPU 卡总数。请将其设置为等于或低于该 flavor 所选节点上可分配 NPU 总数。

使用 kubectl apply -f <filename>.yaml 应用该清单。

3. 通过队列提交 NPU 作业

添加 kueue.x-k8s.io/queue-name 标签,并在容器 resources 块中请求 NPU。Kueue 内置的 batch/job 集成会以挂起状态创建 Job,并且仅在配额检查通过后才取消挂起。

apiVersion: batch/v1
kind: Job
metadata:
  name: ascend-train
  namespace: team-ascend
  labels:
    kueue.x-k8s.io/queue-name: ascend910-lq
spec:
  parallelism: 1
  completions: 1
  suspend: true
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: worker
        image: <your-ascend-image>
        command: ["sh", "-c", "echo training; sleep 600"]
        resources:
          requests: { cpu: 100m, memory: 256Mi, "huawei.com/Ascend910": 2 } 
          limits:   { cpu: "1",  memory: 1Gi,   "huawei.com/Ascend910": 2 }
  1. queue-name 标签:将 Job 路由到你上面创建的 LocalQueue
  2. suspend: true:这是必需的,这样 Kueue 才能在配额可用之前持有该 Job。Kueue 在准入时会将其重新设置为 false
  3. NPU 请求:使用 huawei.com/Ascend910(或 huawei.com/Ascend910B4 等)以匹配 Ascend Device Plugin 在节点上报告的资源名称。request 和 limit 必须相等——这是一个扩展资源。

4. 观察准入情况

向一个 nominalQuota 为 2 的队列提交两个这样的 Job,每个 Job 请求 2 个 NPU。

kubectl -n team-ascend get jobs,workloads

第一个 Job 会被准入,作为一个 Pod 运行,并从 Ascend Device Plugin 获得 /dev/davinci* 设备和 ASCEND_VISIBLE_DEVICES;第二个 Job 会保持 Suspended,其 Workload 会报告配额不足:

NAME                STATUS      COMPLETIONS   DURATION   AGE
job/ascend-train    Running     0/1           5s         12s
job/ascend-train-2  Suspended   0/1                      12s

NAME                                       QUEUE          RESERVED IN    ADMITTED
workload/job-ascend-train-xxxxx            ascend910-lq   ascend910-cq   True
workload/job-ascend-train-2-yyyyy          ascend910-lq

查看被持有的 Workload 可以更明确地看到原因:

kubectl -n team-ascend get workload job-ascend-train-2-yyyyy \
  -o yaml

status.conditions 字段会报告配额不足:

status:
  conditions:
  - type: QuotaReserved
    status: "False"
    reason: Pending
    message: "couldn't assign flavors to pod set main: insufficient unused quota for huawei.com/Ascend910 in flavor ascend910-flavor, 2 more needed"

当第一个 Job 完成或被删除后,Kueue 会自动准入被持有的 Workload,取消第二个 Job 的挂起状态,并由 Ascend Device Plugin 将释放出来的 NPU 设备分配给其 Pod。

注意事项

  • ClusterQueuehuawei.com/Ascend910nominalQuota 是独立于节点 Allocatable 强制执行的。如果 Allocatable 低于该配额(例如因为 device plugin 将某些芯片标记为不健康),已准入的 Pod 在 kube-scheduler 层仍可能处于 Pending,并显示 Insufficient huawei.com/Ascend910。请保持 nominalQuota ≤ 所选节点上 Allocatable 的总和。
  • 同样的模式也适用于 device plugin 暴露的其他 Ascend 资源名称(huawei.com/Ascend910B4huawei.com/Ascend310P,等等)。按需将它们添加到 coveredResources 和容器的 resources 块中。
  • Kueue 的其他特性——fair sharing、cohorts、gang scheduling、preemption——无需额外配置即可与 NPU 资源配合使用。