K8S集群GPU调度优化与运维

适用场景:AI 训练 / 推理 / 模型微调 / Jupyter Notebook / 多租户 GPU 共享
核心组件:NVIDIA GPU Operator | Device Plugin | Volcano | Kueue | DCGM Exporter
GPU 型号:A100 / H100 / H200 / A10 / L40S / RTX 4090 等

一、总体架构

K8s GPU 调度从底层到上层分为五层模型:工作负载层(PyTorchJob / TFJob / 推理 Deployment 等)→ 调度器层(kube-scheduler / Volcano / Kueue / KAI)→ GPU 共享策略层(MIG / Time-Slicing / MPS / vGPU)→ 设备管理层(GPU Operator / Device Plugin / GFD / Network Operator / Topology Manager)→ GPU 硬件层(NVLink / InfiniBand / NUMA 拓扑)。

核心原则

  • 先 Operator 再调度器:GPU Operator 是一切的前提,负责驱动、CUDA、设备插件的自动化部署
  • 隔离性优先于利用率:生产环境用 MIG,开发环境用 Time-Slicing
  • Gang 调度是分布式训练的刚需:防止部分 Pod 调度成功导致资源死锁
  • 拓扑感知:NVLink / NUMA 对齐对多卡训练性能影响 5-10 倍

Kubernetes GPU 调度总体架构(五层模型)

图1 Kubernetes GPU 调度总体架构 —— 工作负载→调度器→共享策略→设备管理→GPU 硬件 五层模型

二、GPU 调度组件详解

2.1 NVIDIA GPU Operator

GPU Operator 是 K8s GPU 管理的基石,通过 DaemonSet 自动化部署完整 GPU 软件栈。

组件功能部署形态
NVIDIA DriverGPU 内核驱动DaemonSet(每 GPU 节点 1 个)
Container Toolkit容器运行时 GPU 支持DaemonSet
Device Plugin向 K8s 注册 GPU 资源DaemonSet
GPU Feature Discovery (GFD)节点标签(GPU 型号/CUDA/MIG)DaemonSet
DCGM ExporterGPU Prometheus 指标DaemonSet
MIG ManagerMIG 分区管理DaemonSet
Node Status ExporterGPU 健康状态DaemonSet
安装 GPU Operato

2.2 NVIDIA Device Plugin

Device Plugin 负责将 GPU 注册为 K8s 可调度资源(nvidia.com/gpu),并管理 GPU 共享配置。

Time-Slicing 配置(ConfigMap 方式)
# time-slicing-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: time-slicing-config
  namespace: gpu-operator
data:
  # 全局默认配置:每张 GPU 切 4 份
  any: |-
    version: v1
    flags:
      migStrategy: none
    sharing:
      timeSlicing:
        renameByDefault: false
        failRequestsGreaterThanOne: false
        resources:
          - name: nvidia.com/gpu
            replicas: 4
  
  # A100 专用配置:MIG + Time-Slicing 混合
  a100-80gb: |-
    version: v1
    flags:
      migStrategy: mixed
    sharing:
      timeSlicing:
        resources:
          - name: nvidia.com/gpu
            replicas: 8
          - name: nvidia.com/mig-1g.5gb
            replicas: 2
          - name: nvidia.com/mig-2g.10gb
            replicas: 2
          - name: nvidia.com/mig-3g.20gb
            replicas: 3
          - name: nvidia.com/mig-7g.40gb
            replicas: 7
  
  # T4 / L4 轻量级配置
  tesla-t4: |-
    version: v1
    flags:
      migStrategy: none
    sharing:
      timeSlicing:
        resources:
          - name: nvidia.com/gpu
            replicas: 2
# 应用配置
kubectl apply -f time-slicing-config.yaml

# 更新 ClusterPolicy 使用此配置
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
    -n gpu-operator --type merge \
    --patch '{"spec": {"devicePlugin": {"config": {"name": "time-slicing-config"}}}}'

# 为节点打标签,指定使用哪个配置
kubectl label nodes gpu-node-1 nvidia.com/device-plugin.config=a100-80gb
kubectl label nodes gpu-node-2 nvidia.com/device-plugin.config=tesla-t4
kubectl label nodes gpu-node-3 nvidia.com/device-plugin.config=any

# 验证:节点 GPU 资源应变为 replicas 倍
kubectl describe node gpu-node-1 | grep -A5 "nvidia.com/gpu"
# 期望:Capacity 中 nvidia.com/gpu 从 8 变为 64 (8卡 × 8 replicas)
MPS 配置(可选,高吞吐场景)
# mps-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mps-config
  namespace: gpu-operator
data:
  a100-80gb: |-
    version: v1
    sharing:
      mps:
        resources:
          - name: nvidia.com/gpu
            replicas: 5

2.3 MIG(Multi-Instance GPU)分区

MIG 是 A100 / H100 / H200 的硬件级 GPU 分区能力,每个分区有独立的计算核心、显存和 L2 缓存。

MIG 策略选择
策略说明适用场景
single所有 GPU 使用同一 MIG 配置同构推理集群
mixed不同 GPU 使用不同 MIG 配置混合负载集群
none禁用 MIG训练集群
MIG 配置与启用
# mig-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mig-config
  namespace: gpu-operator
data:
  # 7×1g.5gb:最大并发,适合轻量推理
  all-1g.5gb: |-
    version: v1
    mig-configs:
      all-1g.5gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            1g.5gb: 7
  
  # 3×2g.10gb:平衡型,中等模型推理
  all-2g.10gb: |-
    version: v1
    mig-configs:
      all-2g.10gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            2g.10gb: 3
  
  # 2×3g.20gb:大型模型推理
  all-3g.20gb: |-
    version: v1
    mig-configs:
      all-3g.20gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            3g.20gb: 2
  
  # 混合配置:多种分区共存
  mixed-config: |-
    version: v1
    mig-configs:
      mixed-config:
        - devices: [0]
          mig-enabled: true
          mig-devices:
            1g.5gb: 2
            2g.10gb: 1
            3g.20gb: 1
        - devices: [1]
          mig-enabled: true
          mig-devices:
            7g.40gb: 1
# 应用 MIG 配置
kubectl apply -f mig-config.yaml

# 设置默认 MIG 策略
kubectl patch clusterpolicies.nvidia.com/cluster-policy \
    -n gpu-operator --type merge \
    --patch '{"spec": {"migManager": {"config": {"name": "mig-config", "default": "all-2g.10gb"}}}}'

# 为节点指定 MIG 配置
kubectl label nodes gpu-node-1 nvidia.com/mig.config=all-2g.10gb
kubectl label nodes gpu-node-2 nvidia.com/mig.config=mixed-config

# 验证 MIG 实例
nvidia-smi mig -lgi  # 列出 MIG GPU 实例
kubectl describe node gpu-node-1 | grep -E "nvidia.com/mig"
请求 MIG 设备的 Pod 示例
apiVersion: v1
kind: Pod
metadata:
  name: mig-inference
spec:
  restartPolicy: Never
  tolerations:
    - key: nvidia.com/gpu
      operator: Exists
      effect: NoSchedule
  nodeSelector:
    nvidia.com/mig.config: all-2g.10gb
  containers:
    - name: inference
      image: nvcr.io/nvidia/tritonserver:24.01-py3
      resources:
        limits:
          nvidia.com/mig-2g.10gb: 1  # 请求一个 2g.10gb MIG 实例
        requests:
          nvidia.com/mig-2g.10gb: 1
      env:
        - name: NVIDIA_VISIBLE_DEVICES
          value: "0:0"  # GPU 0 的 MIG 实例 0

2.4 GPU 共享策略对比

维度MIGTime-SlicingMPSvGPU
隔离级别硬件级SM 级硬件级
显存隔离独立共享(无限制)共享独立
故障隔离是(单分区故障不影响其他)否(一个 Pod 崩溃影响同 GPU 所有 Pod)
性能影响无干扰上下文切换开销协作型,吞吐高轻微虚拟化开销
GPU 要求A100 / A30 / H100 / H200任意 NVIDIA GPUVolta 架构以上需商业 License
最大分区数7(A100) / 8(H100)无上限(建议 ≤10)无上限取决于 License
最佳场景生产多租户推理开发 / Notebook / 轻量推理协作型小任务批量推理VM 虚拟化场景
不适用多卡训练(NCCL 受限)SLO 敏感推理故障敏感场景K8s 原生 Pod

最佳实践:MIG + Time-Slicing 混合——在 MIG 切片内再启用 Time-Slicing,实现硬件隔离 + 灵活超分。例如 A100 7×1g.5gb MIG 切片,每个切片再切 2 份 Time-Slicing,等效 14 个调度单元。

图2 GPU 共享策略对比与选型决策树 —— MIG / Time-Slicing / MPS / vGPU 四种策略对比和选型路径

三、批量调度器

3.1 Volcano(Gang 调度首选)

Volcano 是 CNCF 孵化项目,专为批量计算场景设计,支持 Gang 调度、队列管理和公平分享。

安装 Volcano
helm repo add volcano-sh https://volcano-sh.github.io/helm-charts
helm repo update

helm install volcano volcano-sh/volcano \
    --namespace volcano-system \
    --create-namespace \
    --set basic.webhook_enable=true \
    --set basic.metrics_enable=true

# 验证
kubectl get pods -n volcano-system
队列配置
# volcano-queue.yaml
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
  name: training-queue
spec:
  weight: 3              # 权重(3 表示占总资源 3/总权重)
  reclaimable: true      # 允许资源回收
  capability:
    nvidia.com/gpu: 8
    cpu: "32"
    memory: "128Gi"
---
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
  name: inference-queue
spec:
  weight: 1
  reclaimable: true
  capability:
    nvidia.com/gpu: 4
    cpu: "16"
    memory: "64Gi"
Volcano Job 示例(Gang 调度)
# volcano-training-job.yaml
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: distributed-pytorch-training
spec:
  minAvailable: 4          # Gang: 必须同时调度 4 个 Pod,否则全部等待
  schedulerName: volcano
  queue: training-queue
  policies:
    - event: PodEvicted
      action: RestartJob
  tasks:
    - replicas: 1
      name: master
      template:
        spec:
          containers:
            - image: nvcr.io/nvidia/pytorch:24.01-py3
              name: pytorch-master
              command:
                - torchrun
                - --nproc_per_node=1
                - --nnodes=4
                - --node_rank=$VC_TASK_INDEX
                - train.py
              resources:
                limits:
                  nvidia.com/gpu: 1
                  cpu: "4"
                  memory: "16Gi"
          restartPolicy: OnFailure
    - replicas: 3
      name: worker
      template:
        spec:
          containers:
            - image: nvcr.io/nvidia/pytorch:24.01-py3
              name: pytorch-worker
              command:
                - torchrun
                - --nproc_per_node=1
                - --nnodes=4
                - --node_rank=$VC_TASK_INDEX
                - train.py
              resources:
                limits:
                  nvidia.com/gpu: 1
                  cpu: "4"
                  memory: "16Gi"
          restartPolicy: OnFailure
  plugins:
    env: []
    svc: []
    ssh: []
kubectl apply -f volcano-queue.yaml
kubectl apply -f volcano-training-job.yaml

# 查看 Job 状态
kubectl get vcjob -o wide
kubectl describe vcjob distributed-pytorch-training

3.2 Kueue(配额管理)

Kueue 是 K8s 原生的 Job 排队层,管理配额和准入控制,不替换默认调度器。

# 安装 Kueue
kubectl apply -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.9.0/manifests.yaml

# 验证
kubectl get pods -n kueue-system
# kueue-resource-flavor.yaml
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: gpu-h100
spec:
  nodeLabels:
    nvidia.com/gpu.product: "NVIDIA-H100-80GB"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: gpu-cluster-queue
spec:
  namespaceSelector: {}
  queueingStrategy: BestEffortFIFO
  resourceGroups:
    - coveredResources: ["nvidia.com/gpu", "cpu", "memory"]
      flavors:
        - name: gpu-h100
          resources:
            - name: nvidia.com/gpu
              nominalQuota: 8
            - name: cpu
              nominalQuota: "64"
            - name: memory
              nominalQuota: "256Gi"
            - name: nvidia.com/gpu
              borrowingLimit: 4   # 允许借调 4 个
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  name: team-ml-queue
  namespace: ml-team
spec:
  clusterQueue: gpu-cluster-queue

3.3 调度器选型对比

维度kube-schedulerVolcanoKueueKAI Scheduler
Gang 调度不支持原生支持不原生支持支持
队列/配额ResourceQuotaQueue CRDClusterQueue/LocalQueue层级公平队列
公平分享不支持DRF简单配额层级 DRF
抢占PriorityClass高级抢占跨配额抢占多级抢占
拓扑感知有限有限原生支持
分数 GPU不支持不支持不支持支持
K8s 原生替换调度器叠加默认调度器替换调度器
最佳场景简单推理分布式训练多团队配额管理大规模 AI 平台

推荐组合:Volcano(Gang 调度)+ Kueue(配额管理)+ GPU Operator(设备管理)是当前生产环境的标准组合。


四、拓扑感知调度

4.1 NUMA / NVLink 对齐

多卡训练中,GPU 之间的互连拓扑对性能影响巨大。NVLink 互联的 GPU 间 NCCL 带宽可达 300+ GB/s,而跨 NUMA 走 PCIe 仅 50-80 GB/s。

# 查看节点 GPU 拓扑
nvidia-smi topo -m

# 期望输出(8 卡 H100 NVLink):
#       GPU0  GPU1  GPU2  GPU3  GPU4  GPU5  GPU6  GPU7
# GPU0   X   NV12  NV12  NV12  NV12  NV12  NV12  NV12
# GPU1  NV12   X   NV12  NV12  NV12  NV12  NV12  NV12
# ...(NV12 = 12 NVLink 互联)
# SYS / PIX 表示跨 PCIe / 跨 NUMA
Topology Manager 配置
# kubelet 配置(/var/lib/kubelet/config.yaml)
topologyManagerPolicy: single-numa-node
# 可选策略:
# none          — 不做拓扑对齐
# best-effort   — 尽力对齐,不满足也不拒绝
# restricted   — 必须对齐,不满足则调度失败
# single-numa-node — GPU+NIC+CPU 在同一 NUMA 节点

4.2 Network Operator(RDMA / GPUDirect)

# 安装 NVIDIA Network Operator
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm install network-operator nvidia/network-operator \
    --namespace network-operator \
    --create-namespace \
    --set deploySRIOV=true \
    --set rdma.enabled=true
# 验证 Pod 可访问 RDMA 设备
# Pod 需要请求 RDMA 资源
apiVersion: v1
kind: Pod
metadata:
  name: rdma-test
spec:
  containers:
    - name: test
      image: nvcr.io/nvidia/pytorch:24.01-py3
      resources:
        limits:
          nvidia.com/gpu: 1
          rdma/ib: 1       # 请求 RDMA 设备
      securityContext:
        capabilities:
          add: ["IPC_LOCK"]
      volumeMounts:
        - name: ib-shared
          mountPath: /dev/infiniband
  volumes:
    - name: ib-shared
      hostPath:
        path: /dev/infiniband
# 验证 NCCL 使用 RDMA(而非 TCP 回退)
# Pod 内执行 NCCL 测试
kubectl exec -it rdma-test -- python -c "
import torch.distributed as dist
print('Backend:', dist.get_backend())
"

# 查看 NCCL 日志确认使用 IB
export NCCL_DEBUG=INFO
# 日志中应出现 "NET/IB" 而非 "NET/Sock"

4.3 节点池划分与标签

# 按 GPU 型号和用途划分节点池
kubectl label nodes gpu-train-01 gpu-type=h100-full gpu-pool=training
kubectl label nodes gpu-train-02 gpu-type=h100-full gpu-pool=training
kubectl label nodes gpu-infer-01 gpu-type=a100-mig gpu-pool=inference
kubectl label nodes gpu-dev-01 gpu-type=t4-ts gpu-pool=development

# 污点设置(仅 GPU 工作负载调度到 GPU 节点)
kubectl taint nodes gpu-train-01 nvidia.com/gpu=true:NoSchedule
kubectl taint nodes gpu-infer-01 nvidia.com/gpu=true:NoSchedule

# 工作负载通过 toleration + nodeSelector 精确调度

五、监控体系

5.1 DCGM Exporter 核心指标

GPU Operator 自动部署 DCGM Exporter,在每台 GPU 节点的 9400 端口暴露 Prometheus 指标。

指标类型说明关注重点
DCGM_FI_DEV_GPU_UTILGaugeGPU 核心利用率<30% 浪费,>95% 饱和
DCGM_FI_DEV_MEM_COPY_UTILGauge显存带宽利用率与 GPU_UTIL 对比判断瓶颈
DCGM_FI_DEV_FB_USEDGauge已用显存 (MB)配合 FB_FREE 算水位
DCGM_FI_DEV_FB_FREEGauge剩余显存 (MB)
DCGM_FI_DEV_GPU_TEMPGaugeGPU 温度 (°C)>85°C 告警,>90°C 严重
DCGM_FI_DEV_POWER_USAGEGaugeGPU 功耗 (W)对比 TDP 评估能效
DCGM_FI_PROF_PIPE_TENS_ACTIVEGaugeTensor Core 活跃率真正反映计算密度
DCGM_FI_DEV_SM_CLOCKGaugeSM 时钟频率降频 = 散热问题
DCGM_FI_DEV_XID_ERRORSCounterXid 错误计数>0 = 硬件故障
DCGM_FI_DEV_ECC_SBE_VOL_TOTALCounterECC 单比特错误累积增长 = 显存老化
DCGM_FI_DEV_ECC_DBE_VOL_TOTALCounterECC 双比特错误>0 = 显存损坏
DCGM_FI_DEV_REMOVED_REPSCounterGPU 被移除次数>0 = GPU 不可达

5.2 Prometheus 采集配置

# prometheus-config.yaml
scrape_configs:
  # DCGM GPU 指标
  - job_name: 'dcgm-exporter'
    kubernetes_sd_configs:
      - role: daemonset
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        regex: dcgm-exporter
        action: keep
    metrics_path: /metrics
  
  # Kubelet cAdvisor(容器级 GPU 使用)
  - job_name: 'kubernetes-cadvisor'
    kubernetes_sd_configs:
      - role: node
    scheme: https
    tls_config:
      ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
    relabel_configs:
      - target_label: __address__
        replacement: kubernetes.default.svc:443
      - source_labels: [__meta_kubernetes_node_name]
        regex: (.+)
        target_label: __metrics_path__
        replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor
  
  # Volcano 调度器指标
  - job_name: 'volcano-scheduler'
    kubernetes_sd_configs:
      - role: pod
        namespaces:
          names: ['volcano-system']

5.3 Prometheus 告警规则

# gpu-alerts.yaml
groups:
# ===== P0 紧急 =====
- name: gpu-critical
  rules:
  # GPU Xid 硬件故障
  - alert: GPUXidError
    expr: increase(DCGM_FI_DEV_XID_ERRORS[5m]) > 0
    for: 0m
    labels:
      severity: critical
    annotations:
      summary: "GPU {{ $labels.gpu }} on {{ $labels.node }} 发生 Xid 硬件错误"
      description: "Xid 错误码见 NVIDIA 官方文档,常见:Xid=31 GPU 内存页错误 / Xid=43 GPU 停止响应 / Xid=48 双比特 ECC 错误"
  
  # GPU 被系统移除
  - alert: GPURemoved
    expr: increase(DCGM_FI_DEV_REMOVED_REPS[5m]) > 0
    for: 0m
    labels:
      severity: critical
    annotations:
      summary: "GPU {{ $labels.gpu }} 被从系统中移除"
  
  # 双比特 ECC 错误(显存损坏)
  - alert: GPUECCDoubleBit
    expr: increase(DCGM_FI_DEV_ECC_DBE_VOL_TOTAL[1h]) > 0
    for: 0m
    labels:
      severity: critical
    annotations:
      summary: "GPU {{ $labels.gpu }} 双比特 ECC 错误,显存已损坏"
  
  # GPU 温度过高
  - alert: GPUTempCritical
    expr: DCGM_FI_DEV_GPU_TEMP > 90
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "GPU {{ $labels.gpu }} 温度 {{ $value }}°C"
  
  # GPU 不可达(DCGM Exporter 宕机)
  - alert: DCGMExporterDown
    expr: up{job="dcgm-exporter"} == 0
    for: 2m
    labels:
      severity: critical
    annotations:
      summary: "DCGM Exporter 不可达: {{ $labels.instance }}"

# ===== P1 重要 =====
- name: gpu-warning
  rules:
  # GPU 显存水位过高
  - alert: GPUMemoryHigh
    expr: DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE) * 100 > 90
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "GPU {{ $labels.gpu }} 显存使用率 >90%"
  
  # GPU 持续高利用率
  - alert: GPUUtilSaturated
    expr: avg_over_time(DCGM_FI_DEV_GPU_UTIL[10m]) > 95
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "GPU {{ $labels.gpu }} 利用率持续 >95%,需扩容"
  
  # GPU 利用率持续偏低(资源浪费)
  - alert: GPUUtilLow
    expr: avg_over_time(DCGM_FI_DEV_GPU_UTIL[30m]) < 20
    for: 15m
    labels:
      severity: info
    annotations:
      summary: "GPU {{ $labels.gpu }} 利用率持续 <20%,可能资源过剩"
  
  # 单比特 ECC 错误增长(显存老化预警)
  - alert: GPUECCSingleBitGrowing
    expr: rate(DCGM_FI_DEV_ECC_SBE_VOL_TOTAL[1h]) > 10
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "GPU {{ $labels.gpu }} 单比特 ECC 错误快速增长,显存老化中"
  
  # GPU 降频(散热问题)
  - alert: GPUClockThrottling
    expr: DCGM_FI_DEV_SM_CLOCK < 1000
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "GPU {{ $labels.gpu }} SM 时钟降至 {{ $value }}MHz,可能在降频保护"
  
  # Volcano Job 调度失败
  - alert: VolcanoJobPending
    expr: volcano_job_pending > 5
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "{{ $value }} 个 Volcano Job 处于 Pending 状态"

5.4 Grafana PromQL 核心查询

# 1. GPU 利用率(按节点汇总)
avg by (node) (DCGM_FI_DEV_GPU_UTIL)

# 2. 显存使用率
DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE) * 100

# 3. Tensor Core 活跃率(真正的计算密度)
DCGM_FI_PROF_PIPE_TENS_ACTIVE * 100

# 4. GPU 温度趋势
DCGM_FI_DEV_GPU_TEMP

# 5. 功耗效率(tokens/W 或推理/W)
DCGM_FI_DEV_POWER_USAGE

# 6. 容器级 GPU 使用(kubelet cAdvisor)
rate(container_accelerator_duty_cycle[1m]) * 100

# 7. Xid 错误事件
increase(DCGM_FI_DEV_XID_ERRORS[1h])

# 8. GPU 利用率分布(P50/P90/P99)
quantile_over_time(0.50, DCGM_FI_DEV_GPU_UTIL[1h])
quantile_over_time(0.90, DCGM_FI_DEV_GPU_UTIL[1h])
quantile_over_time(0.99, DCGM_FI_DEV_GPU_UTIL[1h])

# 9. 集群 GPU 总量 vs 已分配
sum(kube_node_status_capacity{resource="nvidia_com_gpu"})
sum(kube_pod_container_resource_limits{resource="nvidia_com_gpu"})

# 10. GPU 空闲率(可用于缩容评估)
1 - (count(DCGM_FI_DEV_GPU_UTIL < 30) / count(DCGM_FI_DEV_GPU_UTIL))

六、故障自愈方案

6.1 故障分级与自愈策略

级别故障类型检测方式自愈动作目标 MTTR
P0GPU Xid 硬件故障DCGM Xid 指标L2 节点隔离 + L1 Pod 重启 + 通知<5min
P0GPU 被移除DCGM RemovedRepsL2 节点隔离 + L4 节点替换<15min
P0双比特 ECC 错误DCGM ECC_DBEL2 节点隔离(永久隔离)+ 通知<5min
P1GPU 温度过高DCGM GPU_TEMP降频 + 告知 + 检查散热<10min
P1显存不足DCGM FB_USEDPod 重启 + 调整 gpu-memory-utilization<3min
P2GPU 利用率低DCGM GPU_UTIL标记缩容候选 + 容量优化建议人工评估
P2Volcano Job PendingVolcano 指标资源回收 + 队列优先级调整<10min

6.2 GPU 故障自愈 Controller

# gpu-failure-operator.yaml — 自动隔离故障 GPU 节点
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gpu-health-controller
  namespace: gpu-operator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gpu-health-controller
  template:
    metadata:
      labels:
        app: gpu-health-controller
    spec:
      serviceAccountName: gpu-health-controller
      containers:
        - name: controller
          image: registry.local/gpu-health-controller:latest
          env:
            - name: PROMETHEUS_URL
              value: "http://prometheus:9090"
            - name: XID_ALERT_EXPR
              value: 'increase(DCGM_FI_DEV_XID_ERRORS[5m]) > 0'
            - name: ECC_DBE_EXPR
              value: 'increase(DCGM_FI_DEV_ECC_DBE_VOL_TOTAL[1h]) > 0'
            - name: TEMP_THRESHOLD
              value: "90"
            - name: AUTO_CORDON
              value: "true"     # 自动 cordon 故障节点
            - name: AUTO_DRAIN
              value: "true"     # 自动 drain
            - name: DRAIN_GRACE_PERIOD
              value: "300"      # 5 分钟优雅退出

6.3 自动隔离脚本

#!/bin/bash
# gpu-auto-isolate.sh — GPU 故障自动隔离
# 被 Prometheus AlertManager webhook 调用

ALERT_NAME="$1"
NODE_NAME="$2"
GPU_ID="$3"

case "$ALERT_NAME" in
  "GPUXidError"|"GPUECCDoubleBit"|"GPURemoved")
    echo "[$(date)] P0 故障: $ALERT_NAME on $NODE_NAME GPU $GPU_ID"
    
    # 1. Cordon 节点(阻止新 Pod 调度)
    kubectl cordon "$NODE_NAME"
    
    # 2. Drain 节点(驱逐现有 GPU Pod)
    kubectl drain "$NODE_NAME" \
        --grace-period=300 \
        --timeout=600s \
        --ignore-daemonsets \
        --delete-emptydir-data \
        --force
    
    # 3. 添加故障标签
    kubectl label nodes "$NODE_NAME" \
        gpu-fault="$ALERT_NAME" \
        gpu-fault-time="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
        gpu-quarantine="true"
    
    # 4. 污点标记(永久隔离,直到人工修复)
    kubectl taint nodes "$NODE_NAME" \
        gpu-fault=true:NoSchedule --overwrite
    
    # 5. 通知(钉钉/企业微信 Webhook)
    curl -s -X POST "$DINGTALK_WEBHOOK" \
      -H "Content-Type: application/json" \
      -d "{
        \"msgtype\": \"markdown\",
        \"markdown\": {
          \"title\": \"GPU 故障自动隔离\",
          \"text\": \"### GPU P0 故障\n\n**节点**: $NODE_NAME\n**GPU**: $GPU_ID\n**故障**: $ALERT_NAME\n**动作**: 已 Cordon + Drain + 隔离\n**时间**: $(date)\n\n请立即检查并更换故障 GPU。\n\"
        }
      }"
    
    echo "[$(date)] 节点 $NODE_NAME 已隔离"
    ;;
    
  "GPUTempCritical")
    echo "[$(date)] P1 告警: GPU 温度过高 on $NODE_NAME GPU $GPU_ID"
    
    # 温度过高不直接隔离,而是降频 + 告知
    # 1. 设置 GPU 功率限制(降低频率减少发热)
    ssh "$NODE_NAME" "nvidia-smi -i $GPU_ID -pl 250"  # 限制到 250W
    
    # 2. 标记为温度告警
    kubectl label nodes "$NODE_NAME" \
        gpu-temp-warning="true" --overwrite
    
    echo "[$(date)] 已降低 GPU $GPU_ID 功率限制"
    ;;
    
  "GPUMemoryHigh")
    echo "[$(date)] P1 告警: 显存过高 on $NODE_NAME GPU $GPU_ID"
    # 显存过高通常由 Pod 异常导致,重启 Pod 即可
    # 获取占用此 GPU 的 Pod
    POD_NAME=$(kubectl get pods --all-namespaces -o json | \
      jq -r ".items[] | select(.spec.containers[].resources.limits.\"nvidia.com/gpu\" != null) | \
      select(.status.phase==\"Running\") | .metadata.name" | head -1)
    
    if [ -n "$POD_NAME" ]; then
      echo "重启 Pod: $POD_NAME"
      kubectl delete pod "$POD_NAME" --grace-period=30
    fi
    ;;
esac

6.4 AlertManager Webhook 路由

# alertmanager-config.yaml
route:
  receiver: default
  group_by: ['alertname', 'node']
  group_wait: 10s
  group_interval: 30s
  repeat_interval: 5m
  routes:
    # GPU P0 故障 → 立即触发自愈
    - matchers: ['alertname=~"GPUXidError|GPUECCDoubleBit|GPURemoved"']
      receiver: gpu-auto-isolate
      group_wait: 0s
      repeat_interval: 1h
    # GPU P1 告警 → 告知 + 部分自愈
    - matchers: ['alertname=~"GPUTempCritical|GPUMemoryHigh"']
      receiver: gpu-warning-handler
      group_wait: 30s
    # 其他告警 → 钉钉通知
    - matchers: ['severity=info']
      receiver: dingtalk-info

receivers:
  - name: gpu-auto-isolate
    webhook_configs:
      - url: 'http://gpu-health-controller:8080/webhook'
        send_resolved: true
  - name: gpu-warning-handler
    webhook_configs:
      - url: 'http://gpu-health-controller:8080/warning'
        send_resolved: true
  - name: dingtalk-info
    webhook_configs:
      - url: 'http://dingtalk-notifier:8080/alert'
  - name: default
    webhook_configs:
      - url: 'http://dingtalk-notifier:8080/alert'

6.5 Pod 级自愈(Readiness / Liveness Probe)

# GPU 推理 Pod 健康探针配置
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gpu-inference-service
spec:
  replicas: 2
  template:
    spec:
      containers:
        - name: vllm
          image: vllm/vllm-openai:latest
          # Readiness Probe:模型加载完成后才接收流量
          readinessProbe:
            httpGet:
              path: /health
              port: 8000
            initialDelaySeconds: 300   # 模型加载需要 5-15 分钟
            periodSeconds: 30
            timeoutSeconds: 10
            failureThreshold: 3
          # Liveness Probe:服务卡死后自动重启
          livenessProbe:
            httpGet:
              path: /health
              port: 8000
            initialDelaySeconds: 600   # 启动后 10 分钟才开始检查
            periodSeconds: 60
            timeoutSeconds: 10
            failureThreshold: 5         # 连续 5 次失败 = ~5 分钟后重启
          # Startup Probe:启动期间不杀 Pod
          startupProbe:
            httpGet:
              path: /health
              port: 8000
            initialDelaySeconds: 60
            periodSeconds: 30
            failureThreshold: 30         # 允许 15 分钟启动

七、日常运维

7.1 每日检查清单

检查项命令正常标准
GPU 节点状态kubectl get nodes -l nvidia.com/gpu.present=true全部 Ready
GPU Pod 状态kubectl get pods -A -l nvidia.com/gpu.present=true无 CrashLoop
DCGM Exporterkubectl get ds -n gpu-operator -l app=dcgm-exporter全部 Running
Xid 错误curl prometheus:9090/api/v1/query?query=DCGM_FI_DEV_XID_ERRORS全部为 0
GPU 温度PromQL: DCGM_FI_DEV_GPU_TEMP<80°C
GPU 利用率PromQL: avg(DCGM_FI_DEV_GPU_UTIL)40-85%
Volcano 队列kubectl get vcqueue无积压
节点污点kubectl get nodes -o json | jq '.items[].spec.taints'无意外污点

7.2 每周检查清单

检查项命令/操作说明
GPU 驱动版本一致性kubectl get nodes -o custom-columns=NAME:.metadata.name,DRIVER:.metadata.labels['nvidia\.com/gpu\.driver']确认无版本漂移
GPU 互连带宽节点上执行 all_reduce_perf对比基线
MIG 配置一致性nvidia-smi mig -lgi(每节点)与 ConfigMap 一致
告警审查AlertManager 历史分析误报/漏报
容量趋势GPU 利用率周度趋势评估扩容/缩容
日志归档logrotate /etc/logrotate.d/kube-gpu压缩归档
污点清理检查 gpu-quarantine 标签的节点修复后清除

7.3 常用运维命令速查

# ===== GPU 节点管理 =====
kubectl get nodes -l nvidia.com/gpu.present=true           # 列出所有 GPU 节点
kubectl describe node <node> | grep -A10 "Allocated"       # 查看 GPU 分配
kubectl cordon <node>                                       # 暂停调度
kubectl uncordon <node>                                     # 恢复调度
kubectl drain <node> --ignore-daemonsets --force            # 驱逐 Pod
kubectl taint nodes <node> gpu-fault=true:NoSchedule         # 添加隔离污点

# ===== GPU 状态检查 =====
nvidia-smi                                                   # GPU 概览
nvidia-smi -l 1                                              # 每秒刷新
nvidia-smi topo -m                                           # 互连拓扑
nvidia-smi mig -lgi                                          # MIG 实例
nvidia-smi -q -d MEMORY                                      # 显存详情
nvidia-smi -q -d ECC                                         # ECC 错误
nvidia-smi -q -d POWER                                       # 功耗
dcgmi dmon -e 1001,1002,1003,1004,1005                      # DCGM 实时

# ===== Volcano 管理 =====
kubectl get vcjob                                             # 查看 Job
kubectl get vcqueue                                           # 查看队列
kubectl describe vcjob <job-name>                             # Job 详情
kubectl get podgroups                                         # PodGroup

# ===== MIG 管理 =====
nvidia-smi mig -lgi                                          # 列出 GPU 实例
nvidia-smi mig -lci                                          # 列出计算实例
nvidia-smi mig -cgi 1g.5gb,1g.5gb -C                         # 创建 MIG 实例
nvidia-smi mig -dgi                                          # 销毁 GPU 实例

# ===== GPU Operator 管理 =====
kubectl get clusterpolicies -n gpu-operator                  # 查看集群策略
kubectl get ds -n gpu-operator                                # 查看 DaemonSet
kubectl logs -n gpu-operator ds/nvidia-device-plugin          # 设备插件日志
kubectl logs -n gpu-operator ds/nvidia-driver-daemonset       # 驱动日志

# ===== 清理隔离节点 =====
# 1. 确认 GPU 已修复
nvidia-smi  # 在节点上确认 GPU 正常

# 2. 清除故障标签和污点
kubectl label nodes <node> gpu-fault- gpu-fault-time- gpu-quarantine-
kubectl taint nodes <node> gpu-fault:NoSchedule-

# 3. 恢复调度
kubectl uncordon <node>

# 4. 验证 Pod 恢复
kubectl get pods -o wide --field-selector spec.nodeName=<node>

7.4 性能优化要点

优化项方法预期收益
MIG + Time-Slicing 混合MIG 切片内再 Time-SlicingGPU 利用率 +40-60%
Gang 调度Volcano minAvailable消除资源死锁,集群利用率 +20%
拓扑感知Topology Manager single-numa-nodeNCCL 带宽 +3-5x
RDMA/GPUDirectNetwork Operator + RDMA 设备插件NCCL 带宽 +10x vs TCP
节点池隔离按型号和用途分池减少调度冲突,可预测性提升
配额管理Kueue + ResourceQuota防止团队抢占,公平分享
Binpack 策略Volcano binpack 调度减少碎片化,提升装箱率
弹性伸缩Karpenter + Cluster Autoscaler按需扩缩容,成本 -30%
优先级抢占PriorityClass + Volcano高优训练抢占低优推理
Spot/竞价实例Spot 节点池 + 容错成本 -60-70%

7.5 注意事项

#注意点说明风险等级
1Time-Slicing 无隔离共享 GPU 的 Pod 可能互相影响,一个 OOM 会影响所有
2MIG 不支持 NCCLMIG 实例间不能直接 NVLink 通信,分布式训练受限
3驱动版本兼容K8s 升级后 CUDA 版本可能不匹配,需 pin 驱动版本
4首次加载慢模型权重加载 5-15 分钟,K8s 探针需设大 initialDelaySeconds
5MIG 策略变更需重启修改 MIG 配置会销毁所有 GPU 实例,需 drain 节点
6--shm-size 不足NCCL 多卡通信需要共享内存,Docker 默认 64MB 太小
7DRA 迁移Dynamic Resource Allocation 是未来方向(K8s 1.34+),但当前 Device Plugin 仍稳定
8GFD 标签格式不同 GPU Operator 版本的标签可能不同,升级前验证
9GPU 驱动冲突宿主机已安装驱动 + GPU Operator 也会安装,可能冲突
10Volcano 版本兼容Volcano 替换默认调度器,K8s 版本升级需验证兼容性
11资源碎片化大量小 Pod 占满节点,大 Job 无法调度
12Spot 中断Spot 节点被回收时训练 Job 会失败,需 Checkpoint 机制

八、附录

8.1 节点池规划参考

节点池GPU 型号MIG/TS污点用途配额
gpu-trainH100 80GBnvidia.com/gpu=true:NoSchedule分布式训练8 GPU/节点
gpu-infer-prodA100 80GBMIG 2g.10gbnvidia.com/gpu=true:NoSchedule生产推理7 MIG/卡
gpu-infer-devA10 24GBTime-Slicing x4nvidia.com/gpu=true:PreferNoSchedule开发推理4 副本/卡
gpu-notebookT4 16GBTime-Slicing x2notebook=true:NoScheduleJupyter2 副本/卡
gpu-spotL4 24GBspot=true:NoSchedule批处理/测试按需

8.2 参考资源

资源地址
NVIDIA GPU OperatorGitHub - NVIDIA/gpu-operator: NVIDIA GPU Operator creates, configures, and manages GPUs in Kubernetes · GitHub
NVIDIA Device PluginGitHub - NVIDIA/k8s-device-plugin: NVIDIA device plugin for Kubernetes · GitHub
VolcanoGitHub - volcano-sh/volcano: A Cloud Native Batch System (Project under CNCF) · GitHub
KueueGitHub - kubernetes-sigs/kueue: Kubernetes-native Job Queueing · GitHub
KAI SchedulerGitHub - kai-scheduler/KAI-Scheduler: KAI Scheduler is an open source Kubernetes Native scheduler for AI workloads at large scale · GitHub
NVIDIA DCGM ExporterGitHub - NVIDIA/dcgm-exporter: NVIDIA GPU metrics exporter for Prometheus leveraging DCGM · GitHub
Network OperatorGitHub - Mellanox/network-operator: NVIDIA Network Operator · GitHub

文档说明:本文档基于 2025-2026 年 K8s GPU 生态最新实践编写,覆盖从 GPU Operator 安装到故障自愈的全流程。GPU 调度在 2026 年已进入生产成熟期,核心在于根据工作负载选择合适的共享策略和调度器组合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

miaocbin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值