技术博客

昇腾NPU Kubernetes集成实战:Device Plugin、资源调度与Prometheus监控

详解华为昇腾NPU在Kubernetes中的完整集成方案:Ascend Device Plugin安装与配置、NPU资源调度(单卡/多卡/虚拟化vNPU)、NPU Exporter接入Prometheus监控、MindX DL训练任务调度、NPU隔离与健康检查,以及常见调度问题排查。

昇腾AscendKubernetesDevice PluginNPU监控云原生AI基础设施

将昇腾 NPU 集成到 Kubernetes 集群,需要安装 Device Plugin(让 K8s 发现和调度 NPU 资源)、配置监控(NPU Exporter + Prometheus),以及处理昇腾特有的资源模型(Chip 级别的资源隔离)。本文覆盖完整的集成流程。

昇腾 K8s 集成架构

Kubernetes API Server

   Scheduler(调度器)
       ↓ 分配 NPU 资源
  kubelet(节点代理)
       ↓ 通过 Device Plugin API
  Ascend Device Plugin(DaemonSet)
       ↓ 管理和分配设备
  NPU 硬件(/dev/davinci0, /dev/davinci1, ...)

监控链路:
  NPU 硬件 → NPU Exporter → Prometheus → Grafana

一、安装 Ascend Device Plugin

准备工作

# 1. 确保所有节点已安装驱动和 CANN
# 2. 打 NPU 节点标签
kubectl label node gpu-node-01 accelerator=huawei-npu
kubectl label node gpu-node-02 accelerator=huawei-npu

# 3. 查看节点 NPU 信息(安装 Device Plugin 前,K8s 不认识 NPU)
kubectl describe node gpu-node-01 | grep -A5 "Capacity"
# 安装前:只显示 cpu/memory/pods 等标准资源

安装 Device Plugin

# 华为官方 Device Plugin(MindX DL 组件)
# 下载地址:https://gitee.com/ascend/ascend-device-plugin

# ascend-device-plugin.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ascend-device-plugin
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: ascend-device-plugin
  template:
    metadata:
      labels:
        name: ascend-device-plugin
    spec:
      nodeSelector:
        accelerator: huawei-npu   # 只在昇腾节点部署
      tolerations:
        - key: "npu.huawei.com"
          operator: "Exists"
          effect: "NoSchedule"
      hostNetwork: true
      hostPID: true
      containers:
        - name: device-plugin
          image: ascend-device-plugin:latest
          imagePullPolicy: Never   # 使用本地镜像
          command: ["/usr/local/bin/ascend-device-plugin"]
          args:
            - "--mode=ascend910"   # 910B/910C 使用 ascend910
            - "--fdFlag=false"
          resources:
            limits:
              cpu: 500m
              memory: 512Mi
          securityContext:
            privileged: true       # 必须特权模式访问 NPU 设备
          volumeMounts:
            - name: device-plugin
              mountPath: /var/lib/kubelet/device-plugins
            - name: driver
              mountPath: /usr/local/Ascend/driver
              readOnly: true
            - name: log
              mountPath: /var/log/mindx-dl
      volumes:
        - name: device-plugin
          hostPath:
            path: /var/lib/kubelet/device-plugins
        - name: driver
          hostPath:
            path: /usr/local/Ascend/driver
        - name: log
          hostPath:
            path: /var/log/mindx-dl
kubectl apply -f ascend-device-plugin.yaml

# 等待 DaemonSet 就绪
kubectl rollout status daemonset/ascend-device-plugin -n kube-system

# 验证:安装后 NPU 资源出现在节点 Capacity 中
kubectl describe node gpu-node-01 | grep -A10 "Capacity"
# Capacity:
#   cpu:                      128
#   huawei.com/Ascend910:     8   ← NPU 资源
#   memory:                   1056Gi
#   pods:                     110

二、在 Pod 中使用 NPU

基础单卡 Pod

apiVersion: v1
kind: Pod
metadata:
  name: npu-test-pod
spec:
  containers:
    - name: npu-container
      image: ascendai/cann:8.0.RC3-ubuntu22.04-aarch64
      command: ["python3", "-c"]
      args:
        - |
          import torch
          import torch_npu
          print(f"NPU 可用: {torch.npu.is_available()}")
          print(f"NPU 数量: {torch.npu.device_count()}")
          x = torch.randn(1000, 1000).npu()
          print(f"运算成功: {x.shape}")
      resources:
        limits:
          huawei.com/Ascend910: 1     # 申请 1 个 NPU
        requests:
          huawei.com/Ascend910: 1
      volumeMounts:
        - name: driver
          mountPath: /usr/local/Ascend/driver
          readOnly: true
  volumes:
    - name: driver
      hostPath:
        path: /usr/local/Ascend/driver

多卡分布式训练 Job

apiVersion: batch/v1
kind: Job
metadata:
  name: llm-training-job
spec:
  template:
    spec:
      nodeSelector:
        accelerator: huawei-npu
      containers:
        - name: trainer
          image: my-llm-training:v1.0
          command:
            - "torchrun"
            - "--nproc_per_node=8"       # 每节点 8 个 NPU
            - "--master_addr=$(MASTER_ADDR)"
            - "--master_port=29500"
            - "train_llm.py"
          resources:
            limits:
              huawei.com/Ascend910: 8   # 申请整机 8 个 NPU
          env:
            - name: MASTER_ADDR
              value: "llm-training-job-0"
            - name: ASCEND_VISIBLE_DEVICES
              value: "0,1,2,3,4,5,6,7"
          volumeMounts:
            - name: driver
              mountPath: /usr/local/Ascend/driver
              readOnly: true
            - name: training-data
              mountPath: /data
      volumes:
        - name: driver
          hostPath:
            path: /usr/local/Ascend/driver
        - name: training-data
          persistentVolumeClaim:
            claimName: training-data-pvc
      restartPolicy: OnFailure

三、NPU Exporter + Prometheus 监控

# 安装 NPU Exporter(收集 NPU 指标发送到 Prometheus)
# 下载:https://gitee.com/ascend/ascend-npu-exporter
# npu-exporter-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: npu-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      name: npu-exporter
  template:
    metadata:
      labels:
        name: npu-exporter
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8082"
    spec:
      nodeSelector:
        accelerator: huawei-npu
      hostNetwork: true
      hostPID: true
      containers:
        - name: npu-exporter
          image: npu-exporter:6.0.RC1
          ports:
            - containerPort: 8082
              name: metrics
          command: ["/usr/local/bin/npu-exporter"]
          args:
            - "-port=8082"
            - "-updateTime=5"     # 每 5 秒更新一次
            - "-logFile=/var/log/npu-exporter/npu-exporter.log"
            - "-logLevel=0"
          securityContext:
            privileged: true
          volumeMounts:
            - name: log
              mountPath: /var/log/npu-exporter
      volumes:
        - name: log
          hostPath:
            path: /var/log/npu-exporter

Prometheus 采集配置

# 在 prometheus.yml 中添加
scrape_configs:
  - job_name: 'ascend-npu'
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: (.+)
        replacement: ${1}:8082
      - source_labels: [__meta_kubernetes_pod_label_name]
        action: keep
        regex: npu-exporter

关键监控指标

# NPU 利用率(AI Core 使用率)
container_npu_utilization{job="ascend-npu"}

# NPU 显存使用
container_npu_memory_used_bytes{job="ascend-npu"}

# NPU 显存使用率
container_npu_memory_used_bytes / container_npu_memory_total_bytes * 100

# NPU 温度
container_npu_temperature{job="ascend-npu"}

# NPU 功耗
container_npu_power_draw{job="ascend-npu"}

# NPU 健康状态(0=健康,非0=故障)
container_npu_health_status{job="ascend-npu"} != 0

# Grafana 告警:NPU 利用率长期过低(可能任务卡住了)
avg_over_time(container_npu_utilization[10m]) < 5

# 告警:NPU 温度过高
container_npu_temperature > 85

Grafana Dashboard 核心面板

NPU 集群 Dashboard 布局:

第一行(集群概览):
  [健康 NPU 数] [故障 NPU 数] [集群平均利用率] [集群总显存使用率]

第二行(节点详情 - 变量下钻):
  [各节点 NPU 利用率热力图]
  [各节点 NPU 显存使用趋势]

第三行(任务视图):
  [每个训练任务的 NPU 利用率(by pod_name)]
  [MFU 趋势(模型利用率 = 实际FLOPS / 峰值FLOPS)]

第四行(健康状态):
  [NPU 温度趋势] [功耗趋势] [错误计数]

四、NPU 节点污点与调度策略

# 给 NPU 节点打污点(防止普通 Pod 调度到 NPU 节点浪费资源)
kubectl taint node gpu-node-01 npu.huawei.com=:NoSchedule
kubectl taint node gpu-node-02 npu.huawei.com=:NoSchedule

# NPU 任务 Pod 中需要配置容忍(toleration)
tolerations:
  - key: "npu.huawei.com"
    operator: "Exists"
    effect: "NoSchedule"
# 使用 NodeAffinity 实现 NPU 任务调度到特定节点池
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: accelerator
              operator: In
              values:
                - huawei-npu
            - key: npu-model
              operator: In
              values:
                - 910b     # 只调度到 910B 节点(区分 910B 和 910C)

五、常见问题排查

# 问题1:Pod 一直 Pending,NPU 资源不足
kubectl describe pod <pod-name>
# Events: 0/3 nodes are available: 3 Insufficient huawei.com/Ascend910
# 解决:检查节点 NPU 资源是否被其他 Pod 占用
kubectl get pods --all-namespaces -o custom-columns="NAME:.metadata.name,NPU:.spec.containers[*].resources.limits.huawei\.com/Ascend910" | grep -v none

# 问题2:Pod 启动后 NPU 不可用
kubectl exec -it <pod-name> -- npu-smi info
# 如果报错,检查设备文件挂载
kubectl exec -it <pod-name> -- ls /dev/davinci*

# 问题3:Device Plugin 无法发现 NPU
kubectl logs -n kube-system daemonset/ascend-device-plugin
# 常见:驱动未安装或版本不匹配

# 问题4:多卡训练 HCCS 通信失败
# 检查 HCCS 链路
npu-smi info -i 0 -t link-info
# 检查 P2P 通信
python3 -c "
import torch, torch_npu
x = torch.randn(1000).npu(0)
y = x.npu(1)  # 跨卡传输测试
print('P2P OK')
"

# 问题5:NPU Exporter 采集不到数据
kubectl logs -n monitoring daemonset/npu-exporter | tail -20
# 检查权限:Exporter 需要特权模式
kubectl get pod -n monitoring -o yaml | grep privileged

小结

昇腾 K8s 集成的关键点:Device Plugin 负责让 K8s 感知和调度 NPU 资源(huawei.com/Ascend910);NPU Exporter 负责将 npu-smi 指标暴露给 Prometheus;Pod 必须以特权模式运行并挂载驱动目录。生产部署建议:NPU 节点统一打污点,训练任务用 Toleration + NodeAffinity 精确调度;Prometheus 告警要覆盖 NPU 温度(>85°C)、健康状态(非0)和利用率长期过低(可能任务阻塞)三个维度。