GPU 调度原理(nvidia-device-plugin)+ 弹性扩缩容

一句话:GPU调度是K8s中管理GPU资源的关键技术,通过nvidia-device-plugin可以将GPU资源暴露给K8s调度器。弹性扩缩容可以根据负载动态调整GPU Pod数量。

1. GPU调度基础

1.1 什么是GPU调度?


graph LR

    A[GPU调度] --> B[资源管理]

    A --> C[设备插件]

    A --> D[弹性扩缩]

    A --> E[负载均衡]

    style A fill:#e1f5fe

GPU调度:K8s中管理GPU资源的技术,包括资源发现、分配、监控和扩缩容。

1.2 nvidia-device-plugin

 
# nvidia-device-plugin DaemonSet
 
apiVersion: apps/v1
 
kind: DaemonSet
 
metadata:
 
  name: nvidia-device-plugin-daemonset
 
  namespace: kube-system
 
spec:
 
  selector:
 
    matchLabels:
 
      name: nvidia-device-plugin-ds
 
  template:
 
    metadata:
 
      labels:
 
        name: nvidia-device-plugin-ds
 
    spec:
 
      tolerations:
 
      - key: nvidia.com/gpu
 
        operator: Exists
 
        effect: NoSchedule
 
      containers:
 
      - name: nvidia-device-plugin-ctr
 
        image: nvcr.io/nvidia/k8s-device-plugin:v0.14.0
 
        securityContext:
 
          allowPrivilegeEscalation: false
 
        volumeMounts:
 
        - name: device-plugin
 
          mountPath: /var/lib/kubelet/device-plugins
 
      volumes:
 
      - name: device-plugin
 
        hostPath:
 
          path: /var/lib/kubelet/device-plugins
 

2. GPU资源管理

2.1 GPU资源请求

 
apiVersion: apps/v1
 
kind: Deployment
 
metadata:
 
  name: gpu-app
 
spec:
 
  replicas: 2
 
  selector:
 
    matchLabels:
 
      app: gpu-app
 
  template:
 
    metadata:
 
      labels:
 
        app: gpu-app
 
    spec:
 
      containers:
 
      - name: gpu-app
 
        image: gpu-app:latest
 
        resources:
 
          limits:
 
            nvidia.com/gpu: 1  # 请求1个GPU
 
          requests:
 
            memory: "4Gi"
 
            cpu: "2"
 

2.2 GPU资源类型

资源类型说明
nvidia.com/gpuGPU设备
nvidia.com/gpu-memoryGPU显存
nvidia.com/gpu-coreGPU核心

3. 弹性扩缩容

3.1 HPA自动扩缩

 
apiVersion: autoscaling/v2
 
kind: HorizontalPodAutoscaler
 
metadata:
 
  name: gpu-app-hpa
 
spec:
 
  scaleTargetRef:
 
    apiVersion: apps/v1
 
    kind: Deployment
 
    name: gpu-app
 
  minReplicas: 1
 
  maxReplicas: 10
 
  metrics:
 
  - type: Resource
 
    resource:
 
      name: nvidia.com/gpu
 
      target:
 
        type: Utilization
 
        averageUtilization: 80
 
  - type: Resource
 
    resource:
 
      name: cpu
 
      target:
 
        type: Utilization
 
        averageUtilization: 70
 

3.2 GPU使用率监控

 
import subprocess
 
import json
 
def get_gpu_usage():
 
    """获取GPU使用率"""
 
    try:
 
        result = subprocess.run(
 
            ['nvidia-smi', '--query-gpu=utilization.gpu,memory.used,memory.total', '--format=csv,nounits,noheader'],
 
            capture_output=True,
 
            text=True
 
        )
 
        lines = result.stdout.strip().split('\n')
 
        gpus = []
 
        for line in lines:
 
            parts = line.split(', ')
 
            gpus.append({
 
                'utilization': int(parts[0]),
 
                'memory_used': int(parts[1]),
 
                'memory_total': int(parts[2])
 
            })
 
        return gpus
 
    except Exception as e:
 
        print(f"获取GPU信息失败: {e}")
 
        return []
 

4. 实际案例

4.1 AI模型服务部署

 
# ai-model-deployment.yaml
 
apiVersion: apps/v1
 
kind: Deployment
 
metadata:
 
  name: ai-model-service
 
spec:
 
  replicas: 2
 
  selector:
 
    matchLabels:
 
      app: ai-model
 
  template:
 
    metadata:
 
      labels:
 
        app: ai-model
 
    spec:
 
      containers:
 
      - name: model
 
        image: ai-model:latest
 
        ports:
 
        - containerPort: 8000
 
        resources:
 
          limits:
 
            nvidia.com/gpu: 1
 
            memory: "8Gi"
 
            cpu: "4"
 
          requests:
 
            memory: "4Gi"
 
            cpu: "2"
 
        env:
 
        - name: MODEL_PATH
 
          value: "/models/llama-7b"
 
---
 
# ai-model-service.yaml
 
apiVersion: v1
 
kind: Service
 
metadata:
 
  name: ai-model-service
 
spec:
 
  selector:
 
    app: ai-model
 
  ports:
 
  - port: 80
 
    targetPort: 8000
 
  type: LoadBalancer
 
---
 
# ai-model-hpa.yaml
 
apiVersion: autoscaling/v2
 
kind: HorizontalPodAutoscaler
 
metadata:
 
  name: ai-model-hpa
 
spec:
 
  scaleTargetRef:
 
    apiVersion: apps/v1
 
    kind: Deployment
 
    name: ai-model-service
 
  minReplicas: 2
 
  maxReplicas: 8
 
  metrics:
 
  - type: Resource
 
    resource:
 
      name: nvidia.com/gpu
 
      target:
 
        type: Utilization
 
        averageUtilization: 70
 

4.2 多GPU任务

 
# multi-gpu-deployment.yaml
 
apiVersion: apps/v1
 
kind: Deployment
 
metadata:
 
  name: multi-gpu-app
 
spec:
 
  replicas: 1
 
  selector:
 
    matchLabels:
 
      app: multi-gpu
 
  template:
 
    metadata:
 
      labels:
 
        app: multi-gpu
 
    spec:
 
      containers:
 
      - name: app
 
        image: multi-gpu-app:latest
 
        resources:
 
          limits:
 
            nvidia.com/gpu: 4  # 请求4个GPU
 
            memory: "32Gi"
 
            cpu: "8"
 

5. 常用命令

5.1 GPU资源查看

 
# 查看节点GPU资源
 
kubectl describe node <node-name> | grep nvidia.com/gpu
 
# 查看Pod GPU使用
 
kubectl top pod
 
# 查看nvidia-smi
 
kubectl exec -it <pod-name> -- nvidia-smi
 

5.2 GPU调试

 
# 查看nvidia-device-plugin日志
 
kubectl logs -n kube-system <nvidia-device-plugin-pod>
 
# 检查GPU设备
 
kubectl exec -it <pod-name> -- ls /dev/nvidia*
 

6. 常见坑点

1. GPU资源未暴露

 
# 解决:检查nvidia-device-plugin是否运行
 
kubectl get pods -n kube-system | grep nvidia
 

2. GPU显存不足

 
# 解决:减少GPU显存请求或增加显存
 
resources:
 
  limits:
 
    nvidia.com/gpu: 1
 
    memory: "8Gi"  # 增加显存
 

3. GPU利用率低

 
# 解决:调整HPA策略,减少副本数
 
spec:
 
  minReplicas: 1
 
  maxReplicas: 5
 

核心要点

 
# GPU资源请求
 
resources:
 
  limits:
 
    nvidia.com/gpu: 1
 
    memory: "8Gi"
 
# HPA配置
 
apiVersion: autoscaling/v2
 
kind: HorizontalPodAutoscaler
 
spec:
 
  scaleTargetRef:
 
    apiVersion: apps/v1
 
    kind: Deployment
 
    name: gpu-app
 
  minReplicas: 1
 
  maxReplicas: 10
 
  metrics:
 
  - type: Resource
 
    resource:
 
      name: nvidia.com/gpu
 
      target:
 
        type: Utilization
 
        averageUtilization: 80
 

速记卡(面试闪卡)

Q1:一句话讲清「GPU 调度原理(nvidia-device-plugin)+ 弹性扩缩容」到底是什么?

A:K8s 靠 nvidia-device-plugin 把 GPU 暴露成可调度资源,再用 HPA 按负载弹性扩缩 Pod。

Q2:device-plugin 原理 —— 怎么理解?

A:device-plugin 是个 DaemonSet,跑在每个 GPU 节点上,把 /dev/nvidia* 设备”上报”给 K8s 调度器,让 Pod 能用 nvidia.com/gpu: 1 来申请卡。就像小区物业把每栋楼的停车位登记到调度中心,你要用车位就先跟中心报备——这叫 device plugin(设备插件)机制。

Q3:GPU 资源请求 —— 怎么理解?

A:在 Pod 的 resources.limits 里写 nvidia.com/gpu: 1 就是”要一张卡”,还能细分 gpu-memorygpu-core。但 GPU 不能像 CPU 那样切半张——要么整卡,要么多卡。这叫 resource request(资源请求),调度器靠它做节点亲和与 bin-packing。

Q4:弹性扩缩容 HPA —— 怎么理解?

A:HPA 盯着 GPU 利用率(比如平均 80%)自动增减 Pod 副本,min/maxReplicas 兜住上下限。像电梯根据人流自动加开班次——忙了多开几部,闲了收几部。这叫 horizontal pod autoscaler(水平 Pod 自动扩缩)。

Q5:常见坑点 —— 怎么理解?

A:三大坑:①插件没跑→节点根本没 GPU 资源可调度;②显存不够→Pod 起不来,得调 limits;③利用率低→副本太多白烧钱。记住 device-plugin 是”有卡能被看见”的前提,HPA 是”用多少开多少”的油门。

Q6:核心速记主线有哪些?

  • device-plugin:DaemonSet 上报 GPU 给调度器

  • 资源:limits 写 nvidia.com/gpu,整卡分配

  • HPA:按 GPU 利用率自动扩缩副本

  • 坑:插件未跑、显存不足、利用率低烧钱

口诀

A:GPU 调度靠插件,

设备上报才可见;

HPA 按需副本变,

利用率高最省钱。

相关链接