环境准备: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
⚠️ 注意:版本号一定要锁定!我曾经因为自动升级导致集群版本不一致,kubelet和apiserver版本差了一个小版本,Pod调度直接报错。用 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驱动

驱动安装我推荐两种方式:

  1. 官方runfile安装(最稳定,但手动操作多)
  2. 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报错,排查了半小时才发现是内核模块没加载。

验证驱动是否安装成功:

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

三、知识体系总览

说了这么多,我画了一张图帮你理清思路。整个环境准备的核心逻辑就是:硬件 → 驱动 → 运行时 → 调度,一层层往上走,缺一不可。

K8s GPU推理环境搭建核心流程 第1层:硬件层 NVIDIA GPU(检查lspci、物理插槽) 第2层:驱动层 NVIDIA驱动(apt安装或runfile,验证nvidia-smi) 第3层:容器运行时层 NVIDIA Container Toolkit(配置containerd运行时) 第4层:调度层 NVIDIA Device Plugin(DaemonSet部署,暴露nvidia.com/gpu资源) 常见问题 ❌ 驱动版本不匹配 ❌ 未重启导致模块未加载 ❌ containerd未配置nvidia运行时 ❌ device plugin版本与K8s不兼容 ❌ 内核参数未配置 ❌ swap未关闭

四、避坑指南(我踩过的雷)

最后,我把自己这些年踩过的坑总结一下,你遇到了直接对照排查:

问题现象 根本原因 解决方案
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 写法正确
💡 我的个人习惯:每次搭建完环境,我都会跑一个最小的CUDA容器测试:kubectl run test --image=nvidia/cuda:12.2.0-base-ubuntu22.04 -- nvidia-smi。如果这个能跑通,后面vLLM的部署基本不会出GPU相关的问题。

好了,环境准备这部分就到这里。记住一句话:基础不牢,地动山摇。GPU环境配置虽然繁琐,但每一步都有它的道理。你按照上面的流程走一遍,应该半小时内就能搞定。如果遇到问题,先看nvidia-smi能不能用,再看kubectl describe node有没有GPU资源,这两步能解决90%的问题。


专注资料整理