上一篇 下一篇 分享链接 返回 返回顶部

香港机房服务器:基于GPU负载感知调度器与MIG的多租户高效训练与推理部署指南

发布人:Minchunlin 发布时间:2025-08-04 21:45 阅读量:709


我在香港机房管理的 AI 推理集群是典型的高密度 GPU 场景:

  • 节点规模:20 台裸金属服务器,全部是 H100 SXM GPU(每台 8 卡)
  • 业务场景:多租户混合负载,包括大模型推理(Llama 70B)、图像生成和金融 NLP

初始问题:

  • Kubernetes 默认调度器仅按 nvidia.com/gpu 数量调度,忽略 GPU 实时利用率,导致部分卡满载,部分卡空闲。
  • 多租户任务共享 GPU 容易出现显存争抢,尤其是推理和微调混布时。
  • 用户请求灵活,任务生命周期短,静态分配 GPU 导致资源浪费。

为了解决这些问题,我在生产环境中部署了一个 GPU 负载感知调度器(Extender),结合 NVIDIA MIG 进行多租户隔离,实现了基于实时利用率的动态负载均衡和高效 GPU 共享。

1. GPU 负载感知调度器的设计思路

核心思路:

  • 监控 GPU 实时指标(利用率、显存占用)
  • 调度 Extender 将 GPU 负载纳入调度打分逻辑
  • 结合 MIG 将一张 GPU 划分为多个实例,避免显存争抢
  • 低负载时合并任务,高负载时触发 动态 Pod 迁移(配合 Descheduler)

架构图(生产环境示意)

        +-------------------------+
        |  K8s Default Scheduler  |
        +-------------------------+
                    |
                    v
        +-------------------------+
        |  GPU Load Extender      |  <-- 实时查询 Prometheus / DCGM
        +-------------------------+
                    |
            +----------------+
            |   Node List    |
            +----------------+
                    |
        Pod --> GPU Node --> MIG Instances

2. GPU 调度 Extender 配置

我使用了 调度 Extender 来扩展默认调度逻辑,核心是对 Node 打分,选择低负载 GPU。

Extender Deployment YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gpu-scheduler-extender
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gpu-scheduler-extender
  template:
    metadata:
      labels:
        app: gpu-scheduler-extender
    spec:
      containers:
        - name: extender
          image: myrepo/gpu-scheduler-extender:latest
          ports:
            - containerPort: 8000
          env:
            - name: PROMETHEUS_URL
              value: "http://prometheus-k8s.monitoring:9090"
            - name: GPU_UTIL_THRESHOLD
              value: "0.8"
          resources:
            requests:
              cpu: "500m"
              memory: "256Mi"

Scheduler 配置文件(scheduler-config.yaml)

apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: default-scheduler
    plugins:
      score:
        enabled:
          - name: GPUScore
    pluginConfig:
      - name: GPUScore
        args:
          prometheusURL: "http://prometheus-k8s.monitoring:9090"
          weightGPUUtil: 0.7
          weightMemUtil: 0.3
extenders:
  - urlPrefix: "http://gpu-scheduler-extender.kube-system.svc.cluster.local:8000"
    filterVerb: filter
    prioritizeVerb: prioritize
    weight: 1
    enableHTTPS: false
    nodeCacheCapable: false

我在生产中通过 kubectl edit configmap kube-scheduler 动态加载这个配置,无需重启整个集群。

3. MIG 实现多租户隔离

香港机房的 GPU 以 H100 为主,我在生产中将一张 GPU 分为多个 MIG 实例(7x10GB 或 3x20GB):

节点 GPU MIG 配置示例

# 启用 MIG 模式
sudo nvidia-smi -i 0 -mig 1

# 创建 3 个 20GB MIG 实例
sudo nvidia-smi mig -cgi 19,19,19 -C

# 查看 MIG 实例
nvidia-smi -L

在 K8s 中,通过 NVIDIA Device Plugin 支持 MIG,Pod 可以直接申请 MIG 资源:

apiVersion: v1
kind: Pod
metadata:
  name: llm-inference
spec:
  containers:
    - name: llm
      image: myrepo/llama-infer:latest
      resources:
        limits:
          nvidia.com/mig-2g.20gb: 1

我在生产环境中为不同租户分配不同的 MIG Profile,保证显存隔离,同时调度器只会选择负载低的 MIG 实例。

4. 实战中遇到的坑与优化

问题:Prometheus 指标延迟

GPU 利用率从 DCGM 到 Prometheus 有 15~20s 延迟

解决:调度 Extender 内部缓存最近 30s 的滑动平均值,防止抖动调度

问题:MIG 实例热拆分影响任务

MIG 配置变更会重置 GPU 上的所有 Pod

解决:我在生产环境中固定 MIG 配置,结合 Extender 动态迁移 Pod,而不频繁调整 MIG

问题:多租户 Pod 抢占显存

在没有 MIG 的节点上,PyTorch 会默认抢显存

解决:强制开启 CUDA_MPS + MIG,结合 Extender 避免高负载节点继续调度

5. 复现步骤总结

部署 NVIDIA Device Plugin(开启 MIG 支持)

配置 MIG 实例并固定 Profile

部署 Prometheus + DCGM Exporter

部署 GPU 负载感知调度 Extender

修改 K8s Scheduler 配置文件加载 Extender

使用 Pod 申请 MIG 资源并观察调度分布

这套方案在我香港机房的生产环境运行了半年以上,平均 GPU 利用率从 54% 提升到 82%,并且多租户任务之间几乎没有资源争抢问题。

目录结构
全文