2、基础设施准备:GPU节点要求与Kubernetes集群搭建

好,咱们直接进入正题。这一章要解决的核心问题就一个:怎么让Kubernetes认识你的GPU。说白了,vLLM推理环境跑在K8s上,GPU就是它的心脏。心脏都接不上,后面全是白搭。

我个人习惯把基础设施准备拆成三个步骤:GPU节点环境 → K8s集群搭建 → NVIDIA Device Plugin安装。每一步都有坑,我踩过不少,咱们一个个说。

核心逻辑图:下面这张图展示了从硬件到K8s识别GPU的完整链路。

GPU节点 → K8s集群 → 设备插件 链路图 NVIDIA GPU硬件 (A100 / V100 / L40s等) NVIDIA驱动 + CUDA (驱动版本 ≥ 525) 容器运行时 (nvidia-container-toolkit) Kubernetes集群 (kubeadm / minikube) NVIDIA Device Plugin (让K8s识别GPU资源) 每一层都依赖上一层,缺一个环节GPU就用不了

2.1 GPU节点环境:驱动、CUDA、容器运行时

先说说GPU节点本身。你想想看,一台裸机服务器,插着A100或者V100,系统装好了,然后呢?

第一步:装NVIDIA驱动。 这个没啥好说的,去NVIDIA官网下载对应型号的驱动。我个人建议用nvidia-smi命令验证一下。跑一下这个命令:

nvidia-smi

如果能看到GPU列表、驱动版本、显存信息,说明驱动装好了。嗯,这里要注意:驱动版本最好 ≥ 525。为什么?因为vLLM依赖的CUDA版本对驱动有要求。我遇到过有人用470的老驱动,结果CUDA 12死活装不上,折腾了半天。

第二步:安装CUDA Toolkit。 其实对于容器化部署来说,宿主机上不一定要装完整的CUDA Toolkit。但我的习惯是装一个,方便调试。你可以用nvcc --version检查版本。

这里有个小技巧:驱动和CUDA的版本要匹配。比如驱动525对应CUDA 12.0,驱动535对应CUDA 12.2。不匹配的话,nvidia-smi能认卡,但nvcc会报错。

我的经验: 如果你用的是Ubuntu 22.04,直接用apt安装nvidia-driver-535最省事。别自己从官网下.run文件,容易把系统搞乱。我曾经手贱装了个.run,结果和系统自带的nouveau驱动冲突,黑屏了...嗯,从那以后我学乖了。

第三步:安装容器运行时。 这一步很多人会忽略。Docker默认用的是runc,它不认识NVIDIA GPU。你需要装nvidia-container-toolkit

安装命令很简单:

# 添加NVIDIA容器工具包仓库
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

# 配置Docker运行时
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

装完之后,验证一下:

docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi

如果能看到GPU信息,说明容器运行时配置成功了。这一步我建议你反复确认,因为后面K8s调用GPU也是走这个运行时。

2.2 Kubernetes集群搭建:kubeadm vs minikube

集群搭建这块,我分两种情况说。

情况一:生产环境或有多台GPU服务器 → 用kubeadm

kubeadm是官方推荐的集群搭建工具。步骤稍微多一点,但可控性强。我简单列一下核心步骤:

  1. 所有节点安装容器运行时(上面已经搞定了)
  2. 安装kubeadm、kubelet、kubectl
  3. 初始化控制平面sudo kubeadm init --pod-network-cidr=10.244.0.0/16
  4. 安装网络插件:推荐Flannel或Calico
  5. 加入工作节点:用kubeadm join命令

这里有个坑:kubelet和容器运行时的cgroup驱动必须一致。我遇到过有人用systemd驱动,但Docker用的是cgroupfs,结果节点一直NotReady。解决办法是在kubelet配置里指定--cgroup-driver=systemd

注意: 如果你用的是containerd而不是Docker,记得在containerd配置里启用nvidia容器运行时。具体做法是修改/etc/containerd/config.toml,在plugins."io.containerd.grpc.v1.cri".containerd.runtimes下添加nvidia配置。这个坑我踩过,不配的话Pod永远拿不到GPU。

情况二:单机测试或学习环境 → 用minikube

minikube就简单多了。一条命令启动一个单节点集群:

minikube start --driver=docker --gpus all

注意那个--gpus all参数,它会让minikube自动配置NVIDIA GPU支持。我个人觉得minikube适合快速验证,但生产环境还是老老实实用kubeadm。

2.3 NVIDIA Device Plugin安装

好,现在集群搭好了,节点也装了驱动和运行时。但K8s还不知道节点上有GPU。你运行kubectl describe node,看不到nvidia.com/gpu这个资源。

这时候就需要NVIDIA Device Plugin了。它本质上是一个DaemonSet,运行在每个GPU节点上,负责向Kubelet汇报GPU资源。

安装方式很简单:

# 创建DaemonSet
kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.0/nvidia-device-plugin.yml

# 验证是否安装成功
kubectl get pods -n kube-system | grep nvidia-device-plugin

如果Pod状态是Running,再检查一下节点资源:

kubectl describe node <your-gpu-node> | grep -A5 "Capacity"

你应该能看到类似这样的输出:

nvidia.com/gpu:  8
nvidia.com/gpu:  8

看到这个,说明K8s已经认识你的GPU了。后面部署vLLM的时候,只需要在Pod的resources里声明nvidia.com/gpu: 1,K8s就会自动调度到有GPU的节点上。

一个小细节: Device Plugin默认会暴露所有GPU。如果你只想暴露部分GPU(比如8卡机器只暴露4卡),可以设置环境变量NVIDIA_VISIBLE_DEVICES。我有个项目就是这么干的,把GPU分给不同的租户用。

2.4 验证整个链路

最后,咱们跑一个测试Pod,验证整个链路是否通畅:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: gpu-test
spec:
  containers:
  - name: cuda-test
    image: nvidia/cuda:12.2.0-base-ubuntu22.04
    command: ["nvidia-smi"]
    resources:
      limits:
        nvidia.com/gpu: 1
EOF

查看Pod日志:

kubectl logs gpu-test

如果能看到GPU信息,恭喜你,基础设施准备完毕!

说实话,这一套流程我前前后后搭过不下20次。每次换新集群、换新驱动版本,总会冒出一些新问题。但核心逻辑不变:驱动 → 运行时 → K8s → Device Plugin,一层层验证,别跳步。


公众号:蓝海资料掘金营,微信deep3321