1. 为什么要在Ubuntu 22.04上构建Kubernetes AI训练集群?
去年我在为一家AI初创公司搭建训练平台时,传统的手动管理方式在模型规模扩大到20个GPU节点后彻底崩溃了。每天有30%的计算资源因调度问题闲置,工程师们花费大量时间排队等待GPU分配。这正是Kubernetes的用武之地——它能让AI训练任务像集装箱一样被高效调度。
Ubuntu 22.04 LTS作为当前最稳定的Linux发行版之一,其长期支持周期与Kubernetes的版本迭代完美匹配。我们实测发现,相比其他系统,在Ubuntu上部署Kubernetes的依赖冲突减少约40%,特别是对NVIDIA GPU的支持更为友好。当你的集群需要同时运行TensorFlow、PyTorch等不同框架的训练任务时,Kubernetes的命名空间隔离和资源配额能避免"邻居应用"抢资源的情况。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础环境准备:从裸机到Kubernetes就绪节点
2.1 系统安装与基础配置
首先下载Ubuntu 22.04 LTS服务器版镜像(推荐使用netinstall版本)。在安装界面选择"最小化安装"并勾选OpenSSH server组件。完成安装后立即执行:
bash复制sudo apt update && sudo apt upgrade -y
sudo apt install -y vim tmux net-tools git curl
关键的GPU驱动安装(以RTX 5000系列为例):
bash复制sudo ubuntu-drivers autoinstall
sudo reboot
验证驱动安装:
bash复制nvidia-smi # 应显示GPU信息
注意:如果使用数据中心级GPU如A100,需要下载NVIDIA官方驱动包手动安装,避免ubuntu-drivers安装的版本功能受限。
2.2 容器运行时与Kubernetes组件安装
Kubernetes 1.24+已移除对Docker的直接支持,我们选择containerd作为运行时:
bash复制sudo apt install -y containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd
修改containerd配置以支持GPU:
toml复制[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "nvidia"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
privileged_without_host_devices = false
runtime_engine = ""
runtime_root = ""
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
BinaryName = "/usr/bin/nvidia-container-runtime"
安装kubeadm、kubelet和kubectl:
bash复制sudo apt 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 update && sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
3. Kubernetes集群初始化与GPU插件部署
3.1 控制平面节点初始化
在主节点执行(根据实际网络环境替换apiserver-advertise-address):
bash复制sudo kubeadm init --pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=192.168.1.100 \
--cri-socket=unix:///var/run/containerd/containerd.sock
配置kubectl:
bash复制mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
安装Flannel网络插件:
bash复制kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
3.2 工作节点加入集群
在每个工作节点执行kubeadm join命令(命令来自主节点初始化输出):
bash复制sudo kubeadm join 192.168.1.100:6443 --token xxxx \
--discovery-token-ca-cert-hash sha256:xxxx
3.3 NVIDIA GPU插件部署
安装NVIDIA设备插件以实现GPU资源调度:
bash复制kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.1/nvidia-device-plugin.yml
验证GPU资源可见性:
bash复制kubectl get nodes -o json | jq '.items[].status.allocatable'
# 应显示nvidia.com/gpu资源
4. 构建自动化ML训练流水线
4.1 训练任务容器化
以PyTorch训练为例的Dockerfile:
dockerfile复制FROM nvcr.io/nvidia/pytorch:23.10-py3
WORKDIR /workspace
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY train.py .
ENTRYPOINT ["python", "train.py"]
构建并推送到镜像仓库:
bash复制docker build -t your-registry/pytorch-train:v1 .
docker push your-registry/pytorch-train:v1
4.2 Kubernetes Job资源定义
创建训练任务Job(gpu-job.yaml):
yaml复制apiVersion: batch/v1
kind: Job
metadata:
name: pytorch-mnist
spec:
template:
spec:
containers:
- name: train
image: your-registry/pytorch-train:v1
resources:
limits:
nvidia.com/gpu: 2 # 申请2个GPU
volumeMounts:
- mountPath: /data
name: dataset
volumes:
- name: dataset
persistentVolumeClaim:
claimName: nfs-pvc
restartPolicy: Never
backoffLimit: 0
4.3 持久化存储配置
使用NFS作为共享存储(所有节点需安装nfs-common):
bash复制sudo apt install -y nfs-common
创建PVC(nfs-pvc.yaml):
yaml复制apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Ti
storageClassName: nfs-client
4.4 训练任务监控与日志收集
部署Prometheus Operator监控GPU利用率:
bash复制kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/bundle.yaml
配置GPU指标采集:
yaml复制apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: gpu-monitor
spec:
endpoints:
- port: metrics
interval: 15s
selector:
matchLabels:
app: nvidia-dcgm-exporter
5. 高级调度策略与性能优化
5.1 使用NodeSelector定向调度GPU节点
标记GPU节点:
bash复制kubectl label nodes <node-name> accelerator=nvidia
在Job配置中添加:
yaml复制spec:
template:
spec:
nodeSelector:
accelerator: nvidia
5.2 实现弹性伸缩
安装Cluster Autoscaler:
bash复制helm repo add autoscaler https://kubernetes.github.io/autoscaler
helm install my-autoscaler autoscaler/cluster-autoscaler \
--set autoDiscovery.clusterName=<YOUR_CLUSTER_NAME>
5.3 多租户资源配额管理
创建ResourceQuota:
yaml复制apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota
spec:
hard:
requests.nvidia.com/gpu: "4"
limits.nvidia.com/gpu: "8"
6. 实战中的经验与避坑指南
- GPU内存泄漏排查:我们发现PyTorch的CUDA缓存不会自动释放,导致长时间运行后OOM。解决方案是在训练脚本中添加定期清理:
python复制import torch
def clear_cuda_cache():
torch.cuda.empty_cache()
torch.cuda.ipc_collect()
- NVIDIA驱动版本冲突:某次升级后出现"CUDA unknown error",原因是内核模块版本不匹配。现在我们会固定驱动版本:
bash复制sudo apt-mark hold nvidia-driver-535
-
共享存储性能瓶颈:当50个Pod同时读取NFS时,IOPS成为瓶颈。我们最终改用CephFS,吞吐量提升8倍。
-
Kubernetes DNS解析超时:Flannel与某些Ubuntu网络配置冲突,导致DNS查询随机失败。解决方法是在kubelet添加:
bash复制--resolv-conf=/run/systemd/resolve/resolv.conf
- 训练任务中断恢复:使用Volcano等批处理调度器支持的任务检查点功能,可以在节点故障时从最近保存点恢复训练。
