环境准备:K8s集群搭建与GPU节点配置
各位同学好,这一章我们聊聊最基础也最容易踩坑的部分——环境准备。说实话,我见过太多人在这一步翻车了,集群搭好了驱动装不上,或者驱动装上了K8s不认GPU,折腾一整天最后发现是内核版本不匹配。嗯,咱们今天就把这些坑一个个填平。
一、K8s集群搭建:Minikube还是Kubeadm?
先回答一个经典问题:学习阶段用Minikube还是Kubeadm?我个人习惯是——本地开发用Minikube,生产环境用Kubeadm。你想想看,Minikube一键启动,适合快速验证;但如果你要跑vLLM推理任务,GPU直通、节点亲和性这些功能,Minikube支持得并不好。
所以我建议:本教程统一使用Kubeadm搭建。为什么?因为vLLM推理需要真实的GPU资源,Minikube的虚拟化层会引入额外性能损耗。我在项目中遇到过,同样的模型在Minikube上推理延迟高了30%,排查了半天才发现是GPU穿透的问题。
1.1 Kubeadm搭建步骤(精简版)
这里我直接给出一套我验证过的脚本,你照着跑就行。注意:所有节点都需要执行基础环境配置。
# 所有节点执行:关闭swap、配置内核参数
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
# 安装containerd(推荐,别用docker了)
sudo apt-get update
sudo apt-get install -y containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd
# 安装kubeadm、kubelet、kubectl
sudo apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet=1.28.0-1.1 kubeadm=1.28.0-1.1 kubectl=1.28.0-1.1
sudo apt-mark hold kubelet kubeadm kubectl
apt-mark hold 锁死版本,这是血的教训。
1.2 初始化控制平面节点
# 在master节点执行
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.1.100
# 配置kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 安装网络插件(我推荐Calico)
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml
这里有个小技巧:--pod-network-cidr 的值要和网络插件匹配。Calico默认用10.244.0.0/16,Flannel用10.244.0.0/16也行,但如果你用Weave,就得改成10.32.0.0/12。说白了,网络CIDR和插件必须一一对应,否则Pod之间不通。
二、GPU节点配置与NVIDIA驱动安装
好,集群起来了,接下来是重头戏——GPU节点。vLLM推理没有GPU就是空谈,对吧?
2.1 检查GPU硬件
首先确认你的节点上有NVIDIA GPU。我建议用 lspci 看一眼:
lspci | grep -i nvidia
# 输出示例:01:00.0 VGA compatible controller: NVIDIA Corporation GA102 [GeForce RTX 3080] (rev a1)
如果没有输出,先检查物理插槽,别急着装驱动。我记得有一次帮同事排查,他折腾了两小时驱动装不上,最后发现显卡没插紧……嗯,这种低级错误咱们尽量避免。
2.2 安装NVIDIA驱动
驱动安装我推荐两种方式:
- 官方runfile安装(最稳定,但手动操作多)
- apt仓库安装(方便,但版本可能不是最新的)
我个人倾向用apt仓库,省心。但如果你需要特定版本(比如vLLM对CUDA版本有要求),那就用runfile。
# 方法一:apt仓库安装(推荐)
sudo apt-get update
sudo apt-get install -y nvidia-driver-535 # 535是目前最稳定的版本
# 方法二:runfile安装(需要先禁用nouveau)
sudo bash NVIDIA-Linux-x86_64-535.154.05.run --no-opengl-files
验证驱动是否安装成功:
nvidia-smi
# 应该能看到GPU型号、驱动版本、CUDA版本等信息
2.3 安装NVIDIA Container Toolkit
这一步很多人会漏掉。K8s要调度GPU,光有驱动不够,还需要容器运行时能识别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
# 配置containerd使用nvidia运行时
sudo nvidia-ctk runtime configure --runtime=containerd
sudo systemctl restart containerd
这里有个关键点:如果你用的是containerd(现在K8s默认就是),一定要执行 nvidia-ctk runtime configure。我见过有人装完toolkit就以为完事了,结果Pod里根本看不到GPU,因为containerd的配置里没加上nvidia运行时。
2.4 安装NVIDIA Device Plugin
最后一步,让K8s知道节点上有GPU资源。NVIDIA官方提供了device plugin,以DaemonSet形式部署:
kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.1/nvidia-device-plugin.yml
# 验证是否成功
kubectl get pods -n kube-system | grep nvidia
# 应该看到 nvidia-device-plugin-daemonset-xxxxx 处于Running状态
# 查看节点GPU资源
kubectl describe node <your-gpu-node> | grep -i nvidia
# 输出示例:nvidia.com/gpu: 1
nvidia-smi能正常输出GPU信息kubectl describe node显示nvidia.com/gpu资源- 运行测试Pod:
kubectl run gpu-test --image=nvidia/cuda:12.2.0-base-ubuntu22.04 -- nvidia-smi
三、知识体系总览
说了这么多,我画了一张图帮你理清思路。整个环境准备的核心逻辑就是:硬件 → 驱动 → 运行时 → 调度,一层层往上走,缺一不可。
四、避坑指南(我踩过的雷)
最后,我把自己这些年踩过的坑总结一下,你遇到了直接对照排查:
| 问题现象 | 根本原因 | 解决方案 |
|---|---|---|
| nvidia-smi报错"Failed to initialize NVML" | 驱动未正确加载,或内核模块冲突 | 重启节点,检查nouveau是否禁用 |
| Pod里看不到GPU设备 | containerd未配置nvidia运行时 | 执行 nvidia-ctk runtime configure --runtime=containerd |
| kubectl describe node没有nvidia.com/gpu | device plugin未部署或版本不兼容 | 检查DaemonSet日志,确认K8s版本匹配 |
| Pod调度到GPU节点后一直Pending | 资源请求格式错误,或节点标签缺失 | 确认Pod中 resources.limits.nvidia.com/gpu: 1 写法正确 |
kubectl run test --image=nvidia/cuda:12.2.0-base-ubuntu22.04 -- nvidia-smi。如果这个能跑通,后面vLLM的部署基本不会出GPU相关的问题。
好了,环境准备这部分就到这里。记住一句话:基础不牢,地动山摇。GPU环境配置虽然繁琐,但每一步都有它的道理。你按照上面的流程走一遍,应该半小时内就能搞定。如果遇到问题,先看nvidia-smi能不能用,再看kubectl describe node有没有GPU资源,这两步能解决90%的问题。