大家好,我是V哥。

话说AI运维工程师的成长路径,GPU集群到底怎么搭?公司让我搞这个,我连从哪下手都不知道啊!

行,今天V哥就把这事儿给你掰开了、揉碎了讲清楚。不整那些高大上的概念轰炸,就用大白话,带你一步步把GPU训练集群搭起来。

先说好,这篇文章适合谁:

  • 公司刚买了几台GPU服务器,让你"整一下"的运维兄弟
  • 想自己攒个小集群玩深度学习的技术爱好者
  • 面试前想搞清楚这套东西到底是啥的求职者

马上开整。


一、先搞懂:GPU集群到底是个啥?

在动手之前,V哥先给你打个比方,把概念捋顺。

1. 什么是GPU集群?

你可以把它理解成一个**“GPU网吧”**。

单台服务器就像一台电脑,上面插着1-8张显卡(GPU)。但训练大模型的时候,一台机器不够用,你就需要把好几台机器连起来,让它们一起干活。

这堆机器连在一起,就叫集群(Cluster)

2. 为什么要搞集群?

很简单,大模型太胖了,一张卡装不下

举个例子:

  • 训练一个7B参数的大模型,至少需要4张A100(80G显存)
  • 训练一个70B的模型,可能需要几十张卡一起上
  • 要是训练GPT-4那种级别的……别想了,那是几千张卡的事儿

所以,集群的本质就是把多张卡、多台机器的算力"拧成一股绳"

3. 集群里的几个关键角色

V哥画个简单的图给你:

┌─────────────────────────────────────────────────┐
│                   集群架构                        │
├─────────────────────────────────────────────────┤
│                                                 │
│   ┌─────────┐                                  │
│   │ Master  │ ← 管理节点,负责调度任务           │
│   │  Node   │                                  │
│   └────┬────┘                                  │
│        │                                       │
│        ▼                                       │
│   ┌─────────┐  ┌─────────┐  ┌─────────┐       │
│   │ Worker  │  │ Worker  │  │ Worker  │       │
│   │ Node 1  │  │ Node 2  │  │ Node 3  │       │
│   │ GPU x 8 │  │ GPU x 8 │  │ GPU x 8 │       │
│   └─────────┘  └─────────┘  └─────────┘       │
│        ↑            ↑            ↑             │
│        └────────────┴────────────┘             │
│              高速网络互联                        │
│         (InfiniBand / RoCE)                   │
│                                                 │
└─────────────────────────────────────────────────┘

用人话解释一下:

角色 干啥的 生活中的比喻
Master Node 管理调度,分配任务 包工头
Worker Node 真正干活的,跑训练任务 搬砖工人
GPU 计算核心,算力担当 工人手里的电钻
高速网络 让机器之间快速通信 工地上的对讲机
共享存储 存放数据和模型 工地上的材料仓库

二、搭建前的准备工作

1. 硬件清单

V哥假设你有3台GPU服务器,配置如下:

项目 配置
GPU 每台8张 NVIDIA A100 80G(或4090、H100都行)
CPU AMD EPYC 7742 或 Intel Xeon
内存 512GB 以上
系统盘 1TB NVMe SSD
数据盘 4TB NVMe SSD(存数据集)
网卡 100Gbps InfiniBand 或 RoCE

没这么豪华的配置?没关系!

V哥后面也会讲怎么用几张消费级显卡(比如4090)搭个小集群练手。原理是一样的,只是规模不同。

2. 网络规划

这个很重要,很多人翻车就翻在网络上。

网络架构:

┌──────────────────────────────────────────┐
│              管理网络(1Gbps)             │
│     用于SSH登录、系统管理、监控等           │
│                                          │
│  Master ──── Worker1 ──── Worker2 ────   │
└──────────────────────────────────────────┘

┌──────────────────────────────────────────┐
│            计算网络(100Gbps)             │
│     用于GPU之间通信、分布式训练             │
│                                          │
│  Worker1 ═══ Worker2 ═══ Worker3 ═══     │
│         InfiniBand / RoCE                │
└──────────────────────────────────────────┘

┌──────────────────────────────────────────┐
│              存储网络(25Gbps)            │
│         用于访问共享存储(NFS/Lustre)      │
│                                          │
│  所有节点 ──── 存储服务器                   │
└──────────────────────────────────────────┘

V哥划重点:

  • 管理网络和计算网络一定要分开,不然训练的时候SSH都连不上
  • 计算网络带宽越大越好,这是分布式训练的命脉
  • 预算有限的话,至少保证计算网络用万兆网(10Gbps)

3. 软件版本选择

V哥推荐的组合(截至2024年):

软件 版本 说明
操作系统 Ubuntu 22.04 LTS 稳定,驱动兼容性好
NVIDIA Driver 535.x 或更高 匹配CUDA版本
CUDA 12.1 主流框架都支持
cuDNN 8.9.x 深度学习加速库
Docker 24.x 容器运行时
NVIDIA Container Toolkit 最新版 让Docker能用GPU
Kubernetes 1.28.x 容器编排
Python 3.10 PyTorch/TensorFlow兼容性好

三、实操:一步步搭建集群

第一步:操作系统安装与基础配置

所有节点都要做的事情:

1.1 安装Ubuntu 22.04

这个就不赘述了,用U盘做个启动盘,装就完事儿。

注意几点:

  • 分区时给 / 至少200GB
  • /home 或单独挂载数据盘给足空间
  • 安装时选择OpenSSH Server
1.2 配置静态IP和主机名

编辑网络配置:

sudo vim /etc/netplan/00-installer-config.yaml

内容示例:

network:
  version: 2
  ethernets:
    eno1:  # 管理网络网卡
      addresses:
        - 192.168.1.10/24
      gateway4: 192.168.1.1
      nameservers:
        addresses:
          - 8.8.8.8
          - 114.114.114.114
    ens10f0:  # 计算网络网卡(InfiniBand/RoCE)
      addresses:
        - 10.0.0.10/24

应用配置:

sudo netplan apply

设置主机名(三台分别设置):

# 第一台
sudo hostnamectl set-hostname master

# 第二台
sudo hostnamectl set-hostname worker1

# 第三台
sudo hostnamectl set-hostname worker2
1.3 配置hosts文件

所有节点都要配置,让它们能通过主机名互相找到:

sudo vim /etc/hosts

添加:

192.168.1.10  master
192.168.1.11  worker1
192.168.1.12  worker2

# 计算网络
10.0.0.10  master-ib
10.0.0.11  worker1-ib
10.0.0.12  worker2-ib
1.4 配置SSH免密登录

在master节点上:

# 生成密钥
ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa

# 复制到所有节点(包括自己)
ssh-copy-id master
ssh-copy-id worker1
ssh-copy-id worker2

测试一下:

ssh worker1 "hostname"
# 如果输出 worker1,就成功了
1.5 关闭防火墙和SELinux(实验环境)
# 关闭防火墙
sudo systemctl stop ufw
sudo systemctl disable ufw

# Ubuntu默认没有SELinux,如果有的话:
sudo setenforce 0
sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

V哥提醒: 生产环境别这么干,要配置好防火墙规则。实验环境为了省事儿可以先关掉。


第二步:安装NVIDIA驱动和CUDA

这一步是重头戏,也是最容易翻车的地方。V哥教你最稳的方法。

2.1 安装依赖
sudo apt update
sudo apt install -y build-essential dkms
2.2 禁用开源驱动nouveau
sudo bash -c "echo 'blacklist nouveau' >> /etc/modprobe.d/blacklist.conf"
sudo bash -c "echo 'options nouveau modeset=0' >> /etc/modprobe.d/blacklist.conf"
sudo update-initramfs -u
sudo reboot
2.3 安装NVIDIA驱动

方法一:使用官方仓库(推荐)

# 添加仓库
sudo apt install -y software-properties-common
sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt update

# 查看可用驱动版本
ubuntu-drivers devices

# 安装推荐版本
sudo apt install -y nvidia-driver-535

# 重启
sudo reboot

方法二:使用runfile(更可控)

# 下载驱动(去官网找对应版本)
wget https://us.download.nvidia.com/XFree86/Linux-x86_64/535.129.03/NVIDIA-Linux-x86_64-535.129.03.run

# 安装
sudo chmod +x NVIDIA-Linux-x86_64-535.129.03.run
sudo ./NVIDIA-Linux-x86_64-535.129.03.run --silent --dkms

# 重启
sudo reboot
2.4 验证驱动安装
nvidia-smi

看到类似这样的输出就成功了:

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 535.129.03   Driver Version: 535.129.03   CUDA Version: 12.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  NVIDIA A100-SXM...  On   | 00000000:07:00.0 Off |                    0 |
| N/A   30C    P0    52W / 400W |      0MiB / 81920MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
2.5 安装CUDA Toolkit
# 下载CUDA(注意版本要和驱动匹配)
wget https://developer.download.nvidia.com/compute/cuda/12.1.1/local_installers/cuda_12.1.1_530.30.02_linux.run

# 安装(注意:不要再装驱动了,选择不安装Driver)
sudo ./cuda_12.1.1_530.30.02_linux.run --silent --toolkit --override

# 配置环境变量
echo 'export PATH=/usr/local/cuda-12.1/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc

验证:

nvcc --version
# 应该显示 Cuda compilation tools, release 12.1
2.6 安装cuDNN
# 去NVIDIA官网下载cuDNN(需要注册账号)
# 假设下载了 cudnn-linux-x86_64-8.9.7.29_cuda12-archive.tar.xz

tar -xvf cudnn-linux-x86_64-8.9.7.29_cuda12-archive.tar.xz
sudo cp cudnn-linux-x86_64-8.9.7.29_cuda12-archive/include/* /usr/local/cuda-12.1/include/
sudo cp cudnn-linux-x86_64-8.9.7.29_cuda12-archive/lib/* /usr/local/cuda-12.1/lib64/
sudo chmod a+r /usr/local/cuda-12.1/include/cudnn*.h
sudo chmod a+r /usr/local/cuda-12.1/lib64/libcudnn*

V哥小提示: 以上步骤在所有Worker节点都要做!建议写成脚本,批量执行。


第三步:安装Docker和NVIDIA Container Toolkit

有了Docker,以后跑训练任务就方便多了,不用在每台机器上装一堆Python环境。

3.1 安装Docker
# 卸载旧版本
sudo apt remove docker docker-engine docker.io containerd runc

# 安装依赖
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release

# 添加Docker官方GPG密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 添加仓库
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 启动并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 把当前用户加入docker组(免sudo)
sudo usermod -aG docker $USER
newgrp docker
3.2 安装NVIDIA Container Toolkit

这玩意儿是让Docker能调用GPU的关键。

# 添加仓库
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 update
sudo apt install -y nvidia-container-toolkit

# 配置Docker使用NVIDIA运行时
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
3.3 验证GPU Docker
docker run --rm --gpus all nvidia/cuda:12.1.1-base-ubuntu22.04 nvidia-smi

如果能看到GPU信息,恭喜你,Docker + GPU环境搞定了!


第四步:配置共享存储(NFS)

训练数据和模型需要所有节点都能访问,最简单的方案就是NFS。

4.1 在Master节点上配置NFS服务端
# 安装NFS服务
sudo apt install -y nfs-kernel-server

# 创建共享目录
sudo mkdir -p /data/shared
sudo chown -R nobody:nogroup /data/shared
sudo chmod 777 /data/shared

# 配置导出
sudo vim /etc/exports

添加以下内容:

/data/shared  192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

启动服务:

sudo exportfs -ra
sudo systemctl restart nfs-kernel-server
sudo systemctl enable nfs-kernel-server
4.2 在Worker节点上挂载NFS
# 安装NFS客户端
sudo apt install -y nfs-common

# 创建挂载点
sudo mkdir -p /data/shared

# 挂载
sudo mount master:/data/shared /data/shared

# 验证
df -h | grep shared

# 设置开机自动挂载
echo "master:/data/shared /data/shared nfs defaults 0 0" | sudo tee -a /etc/fstab

现在,你在任何一个节点的 /data/shared 目录下放文件,其他节点都能看到了。


第五步:安装Kubernetes(K8s)

K8s是集群管理的核心,有了它,你就能像管理一台电脑一样管理整个集群。

5.1 所有节点的准备工作
# 关闭swap(K8s要求)
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /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
5.2 安装kubelet、kubeadm、kubectl

所有节点执行:

# 添加K8s仓库
sudo apt-get update
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 kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

# 配置containerd使用systemd cgroup
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
sudo systemctl restart containerd
5.3 初始化Master节点

只在Master节点执行:

sudo kubeadm init \
  --pod-network-cidr=10.244.0.0/16 \
  --apiserver-advertise-address=192.168.1.10

初始化成功后,会输出一个 kubeadm join 命令,一定要保存好!

配置kubectl:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
5.4 安装网络插件(Flannel)
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
5.5 Worker节点加入集群

在Worker节点执行之前保存的join命令:

sudo kubeadm join 192.168.1.10:6443 --token xxxx \
    --discovery-token-ca-cert-hash sha256:xxxx
5.6 验证集群状态

回到Master节点:

kubectl get nodes

应该看到:

NAME      STATUS   ROLES           AGE   VERSION
master    Ready    control-plane   10m   v1.28.0
worker1   Ready    <none>          5m    v1.28.0
worker2   Ready    <none>          5m    v1.28.0

第六步:安装NVIDIA GPU Operator

这是让K8s能识别和调度GPU的关键组件。

6.1 安装Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
6.2 安装GPU Operator
# 添加NVIDIA Helm仓库
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update

# 安装GPU Operator
helm install --wait --generate-name \
     -n gpu-operator --create-namespace \
     nvidia/gpu-operator \
     --set driver.enabled=false  # 因为我们已经手动装了驱动

等待几分钟,所有Pod都Running后:

kubectl get pods -n gpu-operator
6.3 验证GPU资源
kubectl describe nodes worker1 | grep nvidia.com/gpu

应该能看到:

nvidia.com/gpu:     8

这就说明K8s已经能识别到8张GPU了!


第七步:跑一个测试任务

终于到了激动人心的时刻,让我们跑一个GPU测试任务。

7.1 创建测试Pod

创建文件 gpu-test.yaml

apiVersion: v1
kind: Pod
metadata:
  name: gpu-test
spec:
  restartPolicy: Never
  containers:
  - name: cuda-container
    image: nvidia/cuda:12.1.1-base-ubuntu22.04
    command: ["nvidia-smi"]
    resources:
      limits:
        nvidia.com/gpu: 1  # 申请1张GPU

运行:

kubectl apply -f gpu-test.yaml
kubectl logs gpu-test

能看到GPU信息就成功了!

7.2 跑一个真正的训练任务

创建 pytorch-test.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pytorch-train
spec:
  restartPolicy: Never
  containers:
  - name: pytorch
    image: pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime
    command: 
    - python
    - -c
    - |
      import torch
      print(f"PyTorch version: {torch.__version__}")
      print(f"CUDA available: {torch.cuda.is_available()}")
      print(f"GPU count: {torch.cuda.device_count()}")
      print(f"GPU name: {torch.cuda.get_device_name(0)}")
      
      # 简单的矩阵运算测试
      x = torch.randn(10000, 10000).cuda()
      y = torch.randn(10000, 10000).cuda()
      z = torch.mm(x, y)
      print(f"Matrix multiplication done! Result shape: {z.shape}")
    resources:
      limits:
        nvidia.com/gpu: 1
    volumeMounts:
    - name: shared-data
      mountPath: /data
  volumes:
  - name: shared-data
    nfs:
      server: master
      path: /data/shared

运行:

kubectl apply -f pytorch-test.yaml
kubectl logs -f pytorch-train

四、进阶:分布式训练配置

如果你想让多张卡、多台机器一起训练,还需要一些额外配置。

1. 安装Kubeflow Training Operator

kubectl apply -k "github.com/kubeflow/training-operator/manifests/overlays/standalone"

2. 提交一个PyTorchJob(多GPU分布式训练)

创建 distributed-train.yaml

apiVersion: "kubeflow.org/v1"
kind: PyTorchJob
metadata:
  name: pytorch-distributed
spec:
  pytorchReplicaSpecs:
    Master:
      replicas: 1
      restartPolicy: OnFailure
      template:
        spec:
          containers:
          - name: pytorch
            image: pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime
            command:
            - python
            - -m
            - torch.distributed.launch
            - --nproc_per_node=8
            - --nnodes=3
            - --node_rank=0
            - --master_addr=$(MASTER_ADDR)
            - --master_port=$(MASTER_PORT)
            - /data/train.py
            resources:
              limits:
                nvidia.com/gpu: 8
            volumeMounts:
            - name: shared-data
              mountPath: /data
          volumes:
          - name: shared-data
            nfs:
              server: master
              path: /data/shared
    Worker:
      replicas: 2
      restartPolicy: OnFailure
      template:
        spec:
          containers:
          - name: pytorch
            image: pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime
            command:
            - python
            - -m
            - torch.distributed.launch
            - --nproc_per_node=8
            - --nnodes=3
            - --master_addr=$(MASTER_ADDR)
            - --master_port=$(MASTER_PORT)
            - /data/train.py
            resources:
              limits:
                nvidia.com/gpu: 8
            volumeMounts:
            - name: shared-data
              mountPath: /data
          volumes:
          - name: shared-data
            nfs:
              server: master
              path: /data/shared

五、常见坑点和解决方案

V哥踩过的坑,你就别踩了:

坑1:驱动和CUDA版本不匹配

症状nvidia-smi 能用,但CUDA程序报错

解决:查看驱动支持的最高CUDA版本(nvidia-smi右上角显示),安装对应或更低版本的CUDA Toolkit

坑2:容器里看不到GPU

症状:宿主机nvidia-smi正常,Docker里看不到

解决

# 检查nvidia-container-toolkit是否安装
dpkg -l | grep nvidia-container

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

坑3:K8s节点NotReady

症状kubectl get nodes显示NotReady

解决

# 查看具体原因
kubectl describe node worker1

# 常见原因:containerd没配好、网络插件没装
sudo systemctl restart containerd
kubectl apply -f kube-flannel.yml

坑4:多机训练NCCL超时

症状:分布式训练卡住,报NCCL timeout

解决

# 检查计算网络是否通畅
ping worker1-ib

# 设置NCCL环境变量
export NCCL_DEBUG=INFO
export NCCL_IB_DISABLE=0  # 如果用InfiniBand
export NCCL_SOCKET_IFNAME=ens10f0  # 指定网卡

六、总结

好了兄弟们,到这里一个完整的GPU训练集群就搭建完成了。

让我们回顾一下整个流程:

1. 操作系统安装 + 基础配置
         ↓
2. NVIDIA驱动 + CUDA + cuDNN
         ↓
3. Docker + NVIDIA Container Toolkit
         ↓
4. 共享存储(NFS)
         ↓
5. Kubernetes集群
         ↓
6. GPU Operator
         ↓
7. 训练框架(PyTorch/TensorFlow)
         ↓
8. 提交训练任务,开始炼丹!

V哥最后说几句:

搭建集群这事儿,看着步骤多,其实就是个熟练工种。第一次可能要折腾一两天,熟练之后半天就能搞定。

关键是要理解每一步在干什么。驱动是让系统认识GPU,Docker是让环境可复制,K8s是让资源能调度,Operator是让K8s认识GPU……

把这条链路想通了,你就不只是个"会照着文档敲命令的",而是真正理解GPU集群的人。

有问题评论区见,V哥看到都会回复。

下期咱们聊聊如何用vLLM部署大模型推理服务,不见不散!


V哥碎碎念: 这篇文章写了快8000字,够我喝三杯咖啡的。如果对你有帮助,点个赞、收个藏,让更多兄弟看到!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐