1. 理解Kubernetes中的GPU管理基础
在云原生环境中管理GPU资源,首先需要理解几个核心概念。GPU与CPU在Kubernetes中的管理方式有本质区别——GPU是独占式设备资源,无法像CPU那样进行时间片分割和共享调度。这决定了我们在Kubernetes中使用GPU时必须遵循的特殊规则。
设备文件映射原理是理解这一切的基础。当我们在Linux系统中安装NVIDIA驱动后,系统会在/dev目录下为每块物理GPU生成对应的设备文件。例如:
- /dev/nvidia0 → 第一块物理GPU
- /dev/nvidia1 → 第二块物理GPU
- ...
这些设备文件是程序访问GPU硬件的门户。在容器化环境中,我们需要将这些文件正确地挂载到容器内部,同时确保容器只能访问被分配到的特定GPU设备。这种映射关系是静态且一对一的,这也是为什么Kubernetes要求GPU资源必须在limits中声明且不支持超卖(oversubscription)。
关键提示:在Kubernetes中,GPU资源的最小调度单位是"整块GPU"。目前主流方案还不支持单个GPU的多任务分片使用(如MIG技术),这意味着申请1个GPU资源单位就等于独占整块物理GPU卡。
2. 宿主机环境准备:构建GPU-ready系统
2.1 驱动安装与验证
正确的驱动安装是GPU可用的前提条件。以下是经过生产验证的安装步骤:
- 禁用nouveau驱动(必须步骤):
bash复制sudo tee /etc/modprobe.d/blacklist-nouveau.conf <<EOF
blacklist nouveau
options nouveau modeset=0
EOF
sudo update-initramfs -u
sudo reboot
重启后验证:
bash复制lsmod | grep nouveau # 应该无任何输出
- 安装NVIDIA官方驱动:
bash复制sudo apt-get install -y gcc make linux-headers-$(uname -r)
wget https://us.download.nvidia.com/tesla/470.82.01/NVIDIA-Linux-x86_64-470.82.01.run
sudo sh NVIDIA-Linux-x86_64-470.82.01.run --silent --dkms
- 验证驱动安装:
bash复制nvidia-smi # 应该显示GPU列表和驱动版本
ls /dev/nvidia* # 应该看到nvidia0-nvidiaN(每个GPU一个)以及控制文件
2.2 容器运行时配置
为了让容器能够访问GPU设备,需要安装nvidia-container-toolkit:
bash复制distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
对于containerd运行时,需要额外配置:
bash复制sudo nvidia-ctk runtime configure --runtime=containerd --set-as-default
sudo systemctl restart containerd
验证配置是否生效:
bash复制sudo ctr run --rm --gpus 0 nvidia/cuda:12.2.0-runtime nvidia-smi
3. Kubernetes节点配置与资源注册
3.1 节点标签与污点管理
GPU节点需要特殊标记以确保调度正确性:
bash复制# 标记GPU型号和数量(自定义标签)
kubectl label nodes <node-name> gpu.vendor=nvidia gpu.count=4 gpu.model=Tesla-T4
# 添加Kubernetes标准GPU标签(设备插件依赖)
kubectl label nodes <node-name> feature.node.kubernetes.io/pci-10de.present=true
# 设置污点防止普通Pod调度
kubectl taint nodes <node-name> nvidia.com/gpu=present:NoSchedule
3.2 设备插件部署
NVIDIA设备插件负责向Kubernetes API Server注册GPU资源:
bash复制kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.0/nvidia-device-plugin.yml
部署后需要验证:
bash复制kubectl get pods -n kube-system -l name=nvidia-device-plugin-ds
kubectl describe node <node-name> | grep nvidia.com/gpu # 应该显示GPU容量
4. Pod配置实战:GPU资源申请与使用
4.1 基础GPU Pod示例
yaml复制apiVersion: v1
kind: Pod
metadata:
name: gpu-pod-demo
spec:
containers:
- name: cuda-container
image: nvidia/cuda:12.2.0-runtime
command: ["nvidia-smi"]
env:
- name: NVIDIA_DRIVER_CAPABILITIES
value: "compute,utility"
resources:
limits:
nvidia.com/gpu: 2 # 申请2块GPU
nodeSelector:
feature.node.kubernetes.io/pci-10de.present: "true"
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
4.2 高级配置技巧
指定特定GPU设备:
yaml复制env:
- name: NVIDIA_VISIBLE_DEVICES
value: "0,2" # 只使用第1和第3块GPU
多容器共享GPU(需要MIG支持):
yaml复制containers:
- name: container-1
resources:
limits:
nvidia.com/gpu: 1
env:
- name: NVIDIA_VISIBLE_DEVICES
value: "0"
- name: container-2
resources:
limits:
nvidia.com/gpu: 1
env:
- name: NVIDIA_VISIBLE_DEVICES
value: "1"
5. 运维与故障排查指南
5.1 常见问题排查表
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| Pod处于Pending状态 | 节点资源不足 | kubectl describe pod |
| nvidia-smi报错 | 驱动不兼容 | 检查驱动版本与CUDA版本匹配 |
| 容器无法识别GPU | 设备插件未运行 | 检查nvidia-device-plugin pod日志 |
| GPU利用率异常 | 显存泄漏 | 定期重启工作负载或使用资源监控 |
5.2 监控与日志收集
部署GPU监控组件:
bash复制helm install gpu-monitor nvidia/gpu-operator --set monitoring.enabled=true
关键监控指标:
- nvidia_gpu_duty_cycle
- nvidia_gpu_memory_total_bytes
- nvidia_gpu_memory_used_bytes
6. 生产环境最佳实践
- 资源配额管理:
yaml复制apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota
spec:
hard:
nvidia.com/gpu: "4"
- Pod优先级与抢占:
yaml复制apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: gpu-high-priority
value: 1000000
description: "用于关键GPU工作负载"
- 节点维护模式:
bash复制kubectl cordon <gpu-node> # 停止新Pod调度
kubectl drain <gpu-node> --ignore-daemonsets # 安全排空节点
7. 性能优化技巧
- GPU亲和性调度:
yaml复制affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: gpu.model
operator: In
values: ["Tesla-T4"]
- 多实例GPU配置(MIG):
bash复制nvidia-smi mig -i 0 -cgi 19 # 在GPU0上创建MIG实例
- CUDA线程配置优化:
yaml复制env:
- name: CUDA_DEVICE_MAX_CONNECTIONS
value: "32"
8. 安全加固措施
- 设备访问控制:
yaml复制securityContext:
capabilities:
add: ["DAC_OVERRIDE"] # 必要的最小权限
- Pod安全策略:
yaml复制apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: gpu-psp
spec:
allowedHostPaths:
- pathPrefix: "/dev/nvidia"
readOnly: true
- 网络隔离:
yaml复制annotations:
k8s.v1.cni.cncf.io/networks: gpu-network