主题
从零到一搭建企业级 K8s GPU 集群完整教程
RKE2 + Rancher + Harbor + GPU 虚拟化 + 分布式训练/推理
目标规模:30 台 GPU 物理机 × 8 × NVIDIA RTX PRO 6000 Blackwell(96GB)= 240 卡,约 23TB 显存平台:Ubuntu 24.04 + RKE2(K8s v1.35.6)+ Rancher 托管 + Harbor 私有仓库(纯内网) 能力:GPU 虚拟化(MIG/Time-Slicing)、RoCE RDMA 分布式训练、vLLM 大模型推理、Kueue 队列调度、多租户配额 本文覆盖:硬件选型推荐 → 机房组网布线 → 交换机配置 → BIOS/虚拟机 → OS → 平台部署 → 大模型上线 → 验收运维
目录
- 第 1 章 总体方案与硬件配置推荐
- 第 2 章 机房组网基础(拓扑/布线/交换机配置/RoCE 无损网络)
- 第 3 章 服务器初始化(BIOS/固件/RAID/虚拟机创建)
- 第 4 章 Ubuntu 24.04 安装与系统基线
- 第 5 章 Harbor 私有镜像仓库(独立 VM)
- 第 6 章 管理集群与 Rancher 安装
- 第 7 章 GPU 集群 RKE2 部署
- 第 8 章 GPU 能力接入与虚拟化(节点池化最佳实践)
- 第 9 章 多租户体系(配额/RBAC/网络隔离)
- 第 10 章 计算网接入(Multus + RDMA)
- 第 11 章 Kueue 队列调度
- 第 12 章 分布式训练(Kubeflow + NCCL)
- 第 13 章 vLLM 推理服务与生产力大模型部署推荐
- 第 14 章 监控告警体系
- 第 15 章 整体验收 Checklist
- 第 16 章 常见问题速查
- 附录 A 镜像同步清单 / 附录 B 调池与运维速记 / 附录 C 术语表
第 1 章 总体方案与硬件配置推荐
1.1 总体架构
┌─────────────────────────── 管理面(虚拟化区) ──────────────────────────┐
│ Harbor VM(8C16G/2TB) 管理 RKE2 ×3(8C16G) 跑 Rancher 堡垒机/NTP/DNS │
│ 10.10.0.10 10.10.0.11~13 10.10.0.5 │
└────────────────────────────────┬───────────────────────────────────────┘
│ Rancher 纳管 / Harbor 镜像分发
┌───────────────────────── GPU 集群(RKE2 v1.35.6) ─────────────────────┐
│ 控制面 VM ×3(16C32G): 10.10.1.11~13,API VIP 10.10.1.10 │
│ │
│ GPU Worker ×30,节点池化: │
│ ┌──────────────────┬──────────────────┬──────────────────┐ │
│ │ 训练池 ×20 │ 推理池 ×8 │ 开发池 ×2 │ │
│ │ 整卡 + RDMA │ MIG 4×24GB/卡 │ Time-Slicing ×8 │ │
│ └──────────────────┴──────────────────┴──────────────────┘ │
│ │
│ 网络三平面: │
│ ① 管理/K8s/存储网:双 100G bond0 (LACP) —— 10.10.0.0/16 │
│ ② 计算网:ConnectX-7 独立口 RoCEv2 —— 192.168.100.0/24(无损) │
│ ③ IPMI/BMC 带外管理网 —— 172.16.0.0/24(独立低速交换机) │
└────────────────────────────────────────────────────────────────────────┘1.2 硬件配置推荐(可在此基线上加减)
1.2.1 GPU 服务器(30 台)推荐配置
| 部件 | 推荐配置 | 说明 |
|---|---|---|
| GPU | 8 × RTX PRO 6000 Blackwell 96GB(PCIe 版) | 已确定;PCIe 版双宽风冷,确认机型散热/供电支持 8 卡 600W |
| CPU | 2 × AMD EPYC 9355/9455(32~48 核)或 2 × Intel Xeon 8570 | 关键:每卡至少 8~12 物理核,8 卡建议 ≥64 核/机;PCIe 5.0 通道数 ≥128(8 卡 ×16 + 网卡 ×16) |
| 内存 | 1.5~2TB DDR5(24 × 64GB) | 经验值:显存总量 ×1.5~2 倍(8×96=768GB 显存 → 1.5TB 内存),vLLM KV offload、数据加载、页面缓存都吃内存 |
| 系统盘 | 2 × 960GB SATA/NVMe SSD RAID1 | OS + 容器镜像 |
| 数据盘 | 4 × 7.68TB NVMe U.2(≥15TB) | 模型权重本地预置(推荐方案)、训练数据集缓存、vLLM prefix cache;单盘读 ≥6GB/s |
| 管理网卡 | 1 × 双口 100G(CX-6/7 DX) | 做 bond0(LACP),承载 K8s/存储/管理 |
| 计算网卡 | 1 × ConnectX-7 100G 单口(独立卡,不 bond) | RoCEv2 RDMA 计算网,NCCL 专用;固件保持最新 GA |
| 带外 | 独立 IPMI/BMC(iDRAC/iLO/Redfish) | 接带外管理交换机,远程开关机/KVM/固件升级 |
| 电源 | 2+2 冗余,单机满载约 6~7kW | 机柜供电按 8kW/柜规划(每柜 1 台)或 16kW/柜(2 台) |
| 机型参考 | 超微 AS-4125GS / 浪潮 NF5688 类 8 卡 PCIe 机型 | 4U,确认 GPU 拓扑为 单 PCIe switch 平面或双 socket 均衡(nvidia-smi topo -m 验证) |
CPU/内存不足的代价:数据加载瓶颈(GPU 空转)、vLLM 权重加载慢、容器镜像解压缩慢。240 卡集群不要在这些部件上省钱。
1.2.2 虚拟化宿主机(跑 9 台 VM)
| 用途 | 推荐 | 说明 |
|---|---|---|
| 宿主机 | 2 台通用服务器(每台 2×16 核 / 512GB / 2×3.84TB NVMe RAID1 / 双 25G) | 跑 KVM(libvirt) 或 VMware ESXi |
| VM 清单 | GPU CP ×3(16C32G/200G盘)、管理 RKE2 ×3(8C16G/100G盘)、Harbor ×1(8C16G/2TB 数据盘)、堡垒机 ×1(4C8G) | 跨 2 台宿主机反亲和放置,控制面不挤一台 |
1.2.3 网络设备推荐
| 设备 | 推荐 | 数量 | 说明 |
|---|---|---|---|
| 管理/存储接入交换机 | 100G 交换机(如 NVIDIA SN3700 / 华为 CE6857 / H3C S6850),支持 MLAG + LACP + jumbo | 2 台(堆叠/MLAG) | 30 台 × 2 口 = 60 个 100G 口 + 上联 |
| 计算网交换机 | NVIDIA Spectrum-3/4(SN4000 系列)或同级支持 RoCE 无损的 100G/400G 交换机 | 1~2 台 | 30 个 100G 下联网口,1:1 无阻塞;必须支持 PFC + ECN |
| 带外管理交换机 | 48 口千兆 | 1 台 | IPMI 专用 |
| 线缆 | 100G DAC(同柜)/ AOC(跨柜) | 60 + 30 条 | DAC ≤3m 省钱稳定;跨排用 AOC 或光模块+多模光纤 |
1.2.4 存储(可选但推荐)
| 方案 | 推荐场景 |
|---|---|
| 节点本地 NVMe(本教程默认) | 模型权重预置、数据集缓存;零额外成本,速度最快 |
| 分布式存储 Ceph(3~5 台存储节点) | 需要 PVC 动态供给、模型版本共享、 checkpoint 集中保存时增加;独立 25G/100G 网 |
| NFS 一体机 | 轻量共享(配置文件、小模型),最简单 |
预算允许建议加 3 台 Ceph 存储节点(每台 2×16核/256GB/10×7.68TB NVMe/双 100G),否则用本地 NVMe + NFS 组合即可跑通全流程。
1.2.5 版本基线(最佳实践定稿)
| 组件 | 版本 | 组件 | 版本 |
|---|---|---|---|
| Ubuntu | 24.04 LTS(内核 6.8+) | NVIDIA 驱动 | 570.x(PRO/数据中心分支) |
| RKE2 | v1.35.6+rke2r1 | CUDA / NCCL | 12.8 / 2.26.x |
| Rancher | v2.12.x | PyTorch | NGC 25.05-py3(2.7.x) |
| Harbor | v2.12.x | vLLM | v0.9.x |
| GPU Operator | v25.3.x | LWS | v0.6.x |
| Network Operator | v25.4.x | Kueue | v0.12.x |
| Kubeflow Training Op. | v1.9.x | Multus | v4.2.x |
第 2 章 机房组网基础
2.1 三张网的设计理念(为什么要分网)
| 网络平面 | 流量特征 | 设计要点 |
|---|---|---|
| ① 管理/K8s/存储网 | 突发、混合(API、镜像拉取、etcd、模型分发) | 双口 bond 提高可用性;可容忍拥塞 |
| ② 计算网(RDMA) | 大流量、延迟敏感、丢包零容忍(NCCL AllReduce/AllGather) | 独立物理网络、无阻塞、无损(PFC+ECN),与管理网故障域隔离 |
| ③ 带外管理网 | 极小流量(IPMI) | 物理隔离,带内网络挂掉也能救机器 |
混在一起的典型事故:拉取 20GB 训练镜像时 NCCL 超时、训练任务挂死。分网是 GPU 集群的第一原则。
2.2 物理拓扑与布线
┌──────────┐ ┌──────────┐
│ 管理SW-A │──│ 管理SW-B │ (MLAG 对,双活)
└────┬─────┘ └─────┬────┘
┌────────────┼──────────────┼────────────┐
│ │ │ │ 每台 GPU 服务器双 100G 口
┌──┴──┐ ┌──┴──┐ ┌──┴──┐ ┌──┴──┐ 分别接 SW-A / SW-B(bond0 LACP)
│GPU-1│ ... │GPU-15 GPU-16 ... │GPU-30│
└──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘
│ │ │ │
└────────────┴──────┬───────┴────────────┘ 每台 CX-7 计算口单线
┌──────┴───────┐ 接入计算交换机
│ 计算网 SW │ (100G×30 下联,无阻塞)
└──────────────┘布线规范:
- 管理网双口分别接两台交换机(跨机箱链路聚合),单交换机故障不断网。
- 计算网单口接计算交换机;30 台全在同一台交换机(单跳)性能最优;若两台则做 spine-leaf 且保证同池同 leaf。
- 同柜用 100G DAC(≤3m),跨柜用 AOC;线缆两端打标签(机柜-端口号)。
- 服务器上架:8 卡 GPU 机 4U/6~7kW,每机柜最多 2 台(16kW 供电),注意机房承重与冷热通道。
- IPMI 全部接带外交换机,DHCP 或静态 172.16.0.x。
2.3 VLAN 与 IP 规划
| VLAN | 网段 | 用途 |
|---|---|---|
| 10 | 10.10.0.0/24 | 管理面(Harbor/Rancher/堡垒机) |
| 11 | 10.10.1.0/24 | GPU 集群控制面 + VIP |
| 12 | 10.10.2.0/24 | GPU Worker(bond0) |
| 100 | 192.168.100.0/24 | 计算网(纯二层,无需 VLAN 也可独立物理网) |
| 200 | 172.16.0.0/24 | IPMI 带外 |
节点 IP 分配(固定规则,便于脚本生成):
| 角色 | 主机名 | bond0 IP | 计算网 IP |
|---|---|---|---|
| 堡垒机/NTP/DNS | bastion | 10.10.0.5 | - |
| Harbor | harbor | 10.10.0.10 | - |
| 管理 RKE2 ×3 | mgmt-01~03 | 10.10.0.11~13 | - |
| Rancher VIP | - | 10.10.0.14 | - |
| GPU CP ×3 | gpu-cp-01~03 | 10.10.1.11~13 | - |
| GPU API VIP | - | 10.10.1.10 | - |
| 训练池 ×20 | gpu-train-01~20 | 10.10.2.11~30 | 192.168.100.11~30 |
| 推理池 ×8 | gpu-infer-01~08 | 10.10.2.31~38 | 192.168.100.31~38 |
| 开发池 ×2 | gpu-dev-01~02 | 10.10.2.39~40 | 192.168.100.39~40 |
2.4 交换机配置(关键,逐条照做)
2.4.1 管理网交换机(双机 MLAG + LACP)
通用配置要求:
1. 两台交换机配置 MLAG(华为 iStack/CE M-LAG,H3C IRF,NVIDIA Cumulus clag)
2. 每台服务器一个 port-channel(LACP mode active),成员口为两个交换机上同编号口
3. VLAN:10/11/12 放行(trunk 或 access 按规划)
4. 全局 MTU ≥ 9216(jumbo)
5. 上联口:接核心/出口(或纯内网只接防火墙管理区)华为 CE 系列示例(一台服务器接 SW-A 的 GE1/0/1 和 SW-B 的 GE1/0/1):
# SW-A 与 SW-B 都执行(M-LAG 双活网关场景)
interface Eth-Trunk11
mode lacp-static
lacp timeout fast
port link-type access
port default vlan 12
stp edged-port enable
#
interface 100GE1/0/1
eth-trunk 11
mtu 92162.4.2 计算网交换机(RoCEv2 无损 —— 最重要的配置)
RoCEv2 无损三件套:PFC + ECN + 大 buffer 队列。不配置 = NCCL 性能腰斩甚至超时挂死。
NVIDIA Spectrum(Cumulus/ONYX)示例:
# ONYX(Mellanox 交换机)
interface ethernet 1/1-1/30 mtu 9216 force
# 全局开启 RoCE 无损(ONYX 有一键配置)
roce mode lossless
# 或手工等价配置:
lldp dcbx enable
interface ethernet 1/1-1/30 traffic-class 3 pfc enable
interface ethernet 1/1-1/30 traffic-class 3 buffer strict-priority
interface ethernet 1/1-1/30 ecn minimum-threshold 150000 maximum-threshold 1500000华为 CE 示例:
dcb pfc enable
interface 100GE1/0/1
mtu 9216
dcb pfc enable mode manual
dcb pfc 3 enable # 优先级 3 开 PFC
dcb ets enable
qos queue 3 ecn low-limit 150 high-limit 1500 # ECN 门限服务器侧对应(第 10 章 NCCL 环境变量):
NCCL_IB_GID_INDEX=3(RoCEv2)- 网卡 DSCP/PFC 优先级映射与交换机一致(默认 priority 3)
验收方法:配置完成后两台服务器跑
ib_write_bw应 ≥95Gb/s;训练池 NCCL AllReduce busbw ≥9GB/s。不达标先查这里。
第 3 章 服务器初始化
3.1 GPU 服务器 BIOS 设置(30 台逐台)
| 项目 | 推荐值 | 原因 |
|---|---|---|
| Above 4G Decoding | Enabled | 8 卡 BAR 空间大,必须开,否则显卡点不亮/识别不全 |
| Resizable BAR (Re-Size BAR) | Enabled | 提升显存映射性能 |
| SR-IOV | Enabled | 网卡 VF 与虚拟化需要 |
| IOMMU / VT-d | Disabled(裸金属 GPU 推荐关) | 裸金属 + 容器场景开启会增加 DMA 开销;若后续要 GPU 直通 VM 再开 |
| CPU Performance Profile | Maximum Performance | 关闭节能,降低 jitter |
| C-States / C1E | Disabled | 训练同步敏感 |
| NUMA | Enabled(默认) | 记住拓扑,训练时做 NUMA 绑定 |
| PCIe 链路速率 | Gen5 x16(确认 8 卡全部协商成功) | 装完系统用 lspci -vv 验证 LnkSta |
| Boot 模式 | UEFI | — |
| BMC/IPMI | 静态 IP 172.16.0.x,开 Redfish | 带外批量管理 |
3.2 固件升级清单
- 主板 BIOS、BMC 固件 → 厂商最新稳定版
- ConnectX-7 固件:
mlxfwmanager(MFT 工具包)升级到最新 GA - RTX PRO 6000 VBIOS:随机型厂商基线即可,驱动安装后
nvidia-smi -q | grep -i vbios
3.3 虚拟化宿主机与 VM 创建(KVM 示例)
宿主机装 Ubuntu 24.04 + KVM:
bash
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst
# 桥接到管理网 VLAN(例:宿主机 ens3 在 VLAN10)
# netplan 建 br0 桥,VM 挂 br0
# 创建一台控制面 VM(其余改名字/资源/MAC 重复执行)
virt-install \
--name gpu-cp-01 --vcpus 16 --memory 32768 \
--disk path=/var/lib/libvirt/images/gpu-cp-01.qcow2,size=200,bus=virtio \
--network bridge=br0,model=virtio,mac=52:54:00:10:01:11 \
--cdrom /iso/ubuntu-24.04-live-server-amd64.iso \
--cpu host-passthrough --os-variant ubuntu24.04 \
--graphics vnc,listen=0.0.0.0 --noautoconsoleVM 规划与反亲和:
| VM | vCPU/内存/磁盘 | 宿主机 |
|---|---|---|
| gpu-cp-01 / mgmt-01 / harbor | 16C32G/200G,8C16G/100G,8C16G/2TB | 宿主机 A |
| gpu-cp-02 / mgmt-02 / bastion | 同上 | 宿主机 B |
| gpu-cp-03 / mgmt-03 | 同上 | 宿主机 A(或第三台) |
Harbor 的 2TB 数据盘单独挂一个 virtio 盘(
/dev/vdb挂/data/harbor),与系统盘分离。
3.4 Ubuntu 24.04 安装要点(所有节点)
- Subiquity 安装,最小化(minimized),只勾选 OpenSSH Server。
- 分区:系统盘 LVM 默认即可;数据 NVMe 盘先不分,装完系统再格式化。
- 主机名严格按规划(
gpu-train-01等),安装时直接填对。 - 安装源:内网环境建议先搭一个临时 apt 源(外网机器
apt-mirror或用 ubuntu ISO 做本地源),否则apt install会失败。最小必需包列表:net-tools iproute2 ethtool rdma-core ibverbs-utils perftest keepalived ca-certificates curl。
第 4 章 Ubuntu 24.04 系统基线(所有节点)
4.1 基线脚本
bash
#!/bin/bash
# base-init.sh —— 所有节点(CP VM + 30 台 Worker)
set -e
sudo timedatectl set-timezone Asia/Shanghai
# NTP 指向内网堡垒机
sudo sed -i 's/^#NTP=.*/NTP=10.10.0.5/' /etc/systemd/timesyncd.conf
sudo systemctl restart systemd-timesyncd
# 关 swap
sudo swapoff -a && sudo sed -i '/swap/d' /etc/fstab
# 内核模块与转发
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/99-k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
vm.max_map_count = 262144
EOF
sudo sysctl --system
# 禁用 nouveau
cat <<EOF | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0
EOF
sudo update-initramfs -u
# hosts 内网解析(无内网 DNS 时)
cat <<EOF | sudo tee -a /etc/hosts
10.10.0.10 harbor.example.com
10.10.0.14 rancher.example.com
10.10.1.10 api.gpu-cluster.example.com
EOF
# 常用工具
sudo apt install -y net-tools ethtool curl wget htop iotop nvme-cli
echo "完成,请重启: sudo reboot"4.2 数据盘格式化(GPU Worker,本地 NVMe 模型盘)
bash
# 4 块 NVMe 做 RAID0(追求容量+带宽;要求可靠性可换 RAID10)
sudo apt install -y mdadm
sudo mdadm --create /dev/md0 --level=0 --raid-devices=4 /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1
sudo mkfs.xfs /dev/md0
sudo mkdir -p /data
echo '/dev/md0 /data xfs defaults,noatime 0 0' | sudo tee -a /etc/fstab
sudo mount -a
df -h /data # 约 30TB(4×7.68)
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf
sudo update-initramfs -u4.3 netplan:bond0 + 计算口(GPU Worker)
yaml
# /etc/netplan/50-cluster.yaml(gpu-train-01 示例,口名按 ip link 实际改)
network:
version: 2
ethernets:
ens1f0np0: {mtu: 9000} # 管理网 100G 口1 → 管理SW-A
ens1f1np0: {mtu: 9000} # 管理网 100G 口2 → 管理SW-B
ens2f0np0: # CX-7 计算口 → 计算网SW
mtu: 9000
addresses: [192.168.100.11/24]
bonds:
bond0:
interfaces: [ens1f0np0, ens1f1np0]
mtu: 9000
addresses: [10.10.2.11/24]
routes: [{to: default, via: 10.10.2.1}]
nameservers: {addresses: [10.10.0.5]}
parameters:
mode: 802.3ad
lacp-rate: fast
mii-monitor-interval: 100
transmit-hash-policy: layer3+4bash
sudo netplan apply
cat /proc/net/bonding/bond0 | grep -E "Mode|MII Status|Speed" # 双口 up、200G控制面 VM/管理 VM:单网卡 netplan 配静态 IP 即可(无需 bond)。
4.4 RDMA 环境验证(GPU Worker 计算口)
bash
sudo apt install -y rdma-core ibverbs-utils perftest infiniband-diags
ibv_devices # 应列出 mlx5_x(CX-7)
show_gids # 确认 RoCEv2 的 GID index(通常 3)
ibstat | grep -E "State|Rate" # Active / 100 Gb/sec
# 两台互测带宽(一台做服务端,另一台做客户端)
ib_write_bw -d mlx5_0 --report_gbits # 服务端
ib_write_bw -d mlx5_0 --report_gbits 192.168.100.12 # 客户端 → 期望 ≥95 Gb/s不达标排查顺序:MTU 是否端到端 9000 → 交换机 PFC/ECN → 线缆/光模块 → 固件版本。
4.5 防火墙端口(如启用 ufw)
| 组件 | 端口 |
|---|---|
| RKE2 server | 9345/tcp、6443/tcp、etcd 2379-2380/tcp |
| RKE2 全节点 | 8472/udp(cilium vxlan)、10250/tcp |
| NodePort | 30000-32767/tcp |
| 建议 | 集群内网段全放通,仅限制外部访问 6443/30080 等 |
第 5 章 Harbor 私有镜像仓库(独立 VM)
5.1 安装 Docker + Harbor
bash
# Harbor VM(10.10.0.10),数据盘挂 /data/harbor
sudo mkfs.xfs /dev/vdb && sudo mkdir -p /data/harbor
echo '/dev/vdb /data/harbor xfs defaults 0 0' | sudo tee -a /etc/fstab && sudo mount -a
# Docker 离线包安装(外网机器提前下载 deb 拷入)
sudo dpkg -i containerd.io_*.deb docker-ce_*.deb docker-ce-cli_*.deb docker-compose-plugin_*.deb
sudo systemctl enable --now docker
# Harbor 离线安装包
tar xf harbor-offline-installer-v2.12.*.tgz && cd harbor
cp harbor.yml.tmpl harbor.ymlharbor.yml 关键配置:
yaml
hostname: harbor.example.com
http:
port: 80 # 内网起步用 http;建议后期配内网 CA 切 https(改动见下)
harbor_admin_password: 'xxx'
database:
password: 'xxx'
data_volume: /data/harbor
trivy:
ignore_unfixed: false
skip_update: true # 内网无法更新漏洞库,跳过bash
sudo ./install.sh --with-trivy
docker compose ps # 约 10 个容器 Up
# 浏览器访问 http://harbor.example.com,admin 登录5.2 项目与机器人账户规划
| Harbor 项目 | 内容 |
|---|---|
gpu-cluster | 业务镜像(pytorch、vllm、nccl-tests、模型镜像) |
platform | 平台组件镜像(gpu-operator、rancher、kueue、lws、multus、monitoring 全套) |
library | 基础镜像(cuda、ubuntu、busybox) |
创建机器人账户:系统管理 → 机器人账户 → 新建 robot$puller,权限:所有项目只读拉取,永不过期(或按安全策略定期轮换),记下 token。
5.3 镜像同步(内网成败的关键一步)
5.3.1 流程
外网中转机:拉取镜像 → docker save / skopeo 打包 → 拷入内网 Harbor VM → docker load → 打 tag → push5.3.2 中转机批量导出脚本
bash
# 外网中转机执行;images.txt 见附录 A
mkdir -p /export/images
while read img; do
docker pull "$img"
done < images.txt
docker save -o /export/gpu-images.tar $(cat images.txt | tr '\n' ' ')
# helm chart 同步(需要 helm 与 helm-push 插件或直接下载 tgz)
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia && helm repo update
helm pull nvidia/gpu-operator --version 25.3.2 -d /export/charts/
# 同理 pull: rancher、network-operator、kueue、kube-prometheus-stack 等5.3.3 Harbor VM 导入推送脚本
bash
# push-images.sh —— 在 Harbor VM 执行
set -e
docker load -i /export/gpu-images.tar
HARBOR=harbor.example.com
docker login $HARBOR -u admin -p '<密码>'
# 规则:docker.io/x/y:tag → $HARBOR/library/y:tag(或按附录 A 的映射表)
# nvcr.io/nvidia/y:tag → $HARBOR/platform/y:tag(或 gpu-cluster)
while read img; do
repo=$(echo "$img" | sed -E 's#^(docker.io/|nvcr.io/nvidia/|quay.io/|registry.k8s.io/|ghcr.io/)##')
# 按需指定目标项目(示例统一进 platform,业务镜像单独处理)
dst="$HARBOR/platform/$repo"
docker tag "$img" "$dst"
docker push "$dst"
done < images.txthelm chart 推送:开启 Harbor Chart 仓库(ChartMuseum)或用 OCI:
helm push xxx.tgz oci://harbor.example.com/platform。本文命令中harbor-chartmuseum/platform/xxx表示 ChartMuseum 路径。
5.4 RKE2 全节点 registries.yaml(统一镜像入口)
所有 CP VM 和 30 台 Worker 都要配置(在安装 RKE2 之前放好):
yaml
# /etc/rancher/rke2/registries.yaml
mirrors:
docker.io:
endpoint: ["http://harbor.example.com"]
nvcr.io:
endpoint: ["http://harbor.example.com"]
quay.io:
endpoint: ["http://harbor.example.com"]
registry.k8s.io:
endpoint: ["http://harbor.example.com"]
configs:
"harbor.example.com":
auth:
username: xxx
password: <机器人token>切 https 后:在 configs 加
tls.ca_file: /etc/rancher/rke2/harbor-ca.crt,并把 CA 拷到每个节点/usr/local/share/ca-certificates/后update-ca-certificates。
第 6 章 管理集群与 Rancher 安装
6.1 管理 RKE2 集群(mgmt-01~03)
bash
# 三台管理 VM 通用(离线 artifact 方式:外网机器下载以下文件拷入 /opt/rke2-artifacts)
# rke2.linux-amd64.tar.gz、rke2-images.linux-amd64.tar.zst、sha256sum-amd64.txt、install.sh
sudo mkdir -p /opt/rke2-artifacts /etc/rancher/rke2
# mgmt-01(首节点)
sudo INSTALL_RKE2_VERSION="v1.35.6+rke2r1" \
INSTALL_RKE2_ARTIFACT_PATH=/opt/rke2-artifacts sh install.sh
sudo tee /etc/rancher/rke2/config.yaml <<EOF
token: "xxx"
tls-san:
- 10.10.0.14
- rancher.example.com
EOF
# registries.yaml 按 5.4 放置
sudo systemctl enable --now rke2-server
sudo journalctl -u rke2-server -f # 等待 "rke2 is up and running"
mkdir -p ~/.kube && sudo cp /etc/rancher/rke2/rke2.yaml ~/.kube/config && sudo chown $USER ~/.kube/config
echo 'export PATH=$PATH:/var/lib/rancher/rke2/bin' >> ~/.bashrc && source ~/.bashrc
kubectl get nodesbash
# mgmt-02 / mgmt-03:相同安装,config.yaml 改为:
sudo tee /etc/rancher/rke2/config.yaml <<EOF
server: https://10.10.0.11:9345
token: "xxx"
tls-san:
- 10.10.0.14
- rancher.example.com
EOF
sudo systemctl enable --now rke2-server三台 keepalived 提供 Rancher VIP 10.10.0.14(配置模板见 7.4,改 IP 与网卡即可)。
6.2 安装 Rancher
bash
# helm 二进制离线拷入管理集群
curl -Lo helm.tar.gz https://get.helm.sh/helm-v3.17.0-linux-amd64.tar.gz # 外网机器下载后拷入
tar xf helm.tar.gz && sudo install linux-amd64/helm /usr/local/bin/
helm install rancher harbor-chartmuseum/platform/rancher \
-n cattle-system --create-namespace \
--version 2.12.x \
--set hostname=rancher.example.com \
--set replicas=3 \
--set rancherImage=harbor.example.com/platform/rancher \
--set systemDefaultRegistry=harbor.example.com \
--set useBundledSystemChart=true
kubectl -n cattle-system rollout status deploy/rancher
# 访问 https://rancher.example.com(或 http 按 bootstrap 配置),设置 admin 密码
--set systemDefaultRegistry=harbor.example.com是内网关键:Rancher 下发到被纳管集群的 agent 镜像全部从 Harbor 拉。
6.3 Rancher 纳管 GPU 集群
第 7 章建好 GPU 集群后:
- Rancher UI → Cluster Management → Import Existing → 任意集群
- 拷贝生成的注册命令,在 GPU 集群执行:
bash
kubectl apply -f https://rancher.example.com/v3/import/<token>_<clusterid>.yaml
kubectl -n cattle-system get pods # cattle-cluster-agent Running 即纳管成功纳管后可在 Rancher UI 完成:节点查看/驱逐、Project/命名空间与 RBAC、监控告警开启、集群快照备份。
第 7 章 GPU 集群 RKE2 部署
7.1 首控制面节点(gpu-cp-01)
bash
sudo mkdir -p /opt/rke2-artifacts /etc/rancher/rke2
# artifact 与 registries.yaml 就位后:
sudo INSTALL_RKE2_VERSION="v1.35.6+rke2r1" \
INSTALL_RKE2_ARTIFACT_PATH=/opt/rke2-artifacts sh install.sh
sudo tee /etc/rancher/rke2/config.yaml <<EOF
token: "xxx"
tls-san:
- 10.10.1.10
- api.gpu-cluster.example.com
cni: cilium
disable:
- rke2-ingress-nginx # 不用 ingress(NodePort 方案),减少组件
cluster-cidr: 10.42.0.0/16
service-cidr: 10.43.0.0/16
EOF
sudo systemctl enable --now rke2-server
mkdir -p ~/.kube && sudo cp /etc/rancher/rke2/rke2.yaml ~/.kube/config && sudo chown $USER ~/.kube/config
echo 'export PATH=$PATH:/var/lib/rancher/rke2/bin' >> ~/.bashrc && source ~/.bashrc
kubectl get nodes7.2 控制面扩容(gpu-cp-02/03)
bash
sudo tee /etc/rancher/rke2/config.yaml <<EOF
server: https://10.10.1.11:9345
token: "xxx"
tls-san: ["10.10.1.10"]
EOF
sudo systemctl enable --now rke2-server
kubectl get nodes # 3 台 Ready7.3 etcd 快照(控制面数据备份,重要)
bash
# 每天定时快照到 NFS/管理机
sudo tee /etc/cron.d/rke2-etcd-snapshot <<'EOF'
0 2 * * * root /var/lib/rancher/rke2/bin/rke2 etcd-snapshot save --name daily-$(date +\%F) --etcd-snapshot-retention 14
EOF7.4 API 高可用 VIP(三台 CP 装 keepalived)
bash
sudo apt install -y keepalived
sudo tee /etc/keepalived/keepalived.conf <<EOF
vrrp_instance VI_1 {
state MASTER # cp-02/03 改为 BACKUP
interface ens3 # VM 网卡名(ip link 确认)
virtual_router_id 51
priority 100 # BACKUP: 90 / 80
advert_int 1
authentication { auth_type PASS auth_pass 11111111 }
virtual_ipaddress { 10.10.1.10/24 }
}
EOF
sudo systemctl enable --now keepalived
ip a | grep 10.10.1.10
# ~/.kube/config 的 server 改为 https://10.10.1.10:64437.5 30 台 GPU Worker 加入(节点池标签 + taint)
bash
# 每台 Worker(以训练池 gpu-train-01 为例)
sudo mkdir -p /opt/rke2-artifacts /etc/rancher/rke2
# registries.yaml 按 5.4 就位
sudo INSTALL_RKE2_VERSION="v1.35.6+rke2r1" INSTALL_RKE2_TYPE="agent" \
INSTALL_RKE2_ARTIFACT_PATH=/opt/rke2-artifacts sh install.sh
sudo tee /etc/rancher/rke2/config.yaml <<EOF
server: https://10.10.1.10:9345
token: "xxx"
node-label:
- "node-role.kubernetes.io/gpu-worker=true"
- "gpu.nvidia.com/model=rtx-pro-6000"
- "gpu-cluster.io/pool=train" # 推理池=infer,开发池=dev
node-taint:
- "gpu-cluster.io/pool=train:NoSchedule"
EOF
sudo systemctl enable --now rke2-agent控制面验证:
bash
kubectl get nodes -L gpu-cluster.io/pool
kubectl describe node gpu-train-01 | grep -A2 Taints业务 Pod 进池的标准写法(平台模板统一注入):
yaml
tolerations:
- {key: gpu-cluster.io/pool, operator: Equal, value: train, effect: NoSchedule}
nodeSelector: {gpu-cluster.io/pool: train}批量部署 30 台:建议用 Ansible(inventory 按 train/infer/dev 分组),playbook 内容就是 4.1/4.2/4.3/7.5 的命令模板化;或用 Rancher 纳管后以 Fleet 下发。
第 8 章 GPU 能力接入与虚拟化(节点池化最佳实践)
8.1 虚拟化方案对比与选型结论
| 方案 | 隔离级别 | 粒度 | 适用场景 | 结论 |
|---|---|---|---|---|
| 整卡 | 最强 | 1 卡 | 训练、超大模型推理 | 训练池 20 台 |
| MIG | 硬件级硬隔离(显存/算力/SM) | RTX PRO 6000:每卡最多 4 个 1g.24gb | 多租户推理(≤70B 单实例放不下的模型用整卡) | 推理池 8 台 |
| Time-Slicing | 无隔离(共享显存,时间片轮转) | 任意份数 | 开发调试、Notebook、CI | 开发池 2 台 |
| NVIDIA vGPU | 硬件级 | 需企业 License + vGPU Manager | 虚拟化桌面场景 | 本方案不用 |
| HAMi | 软件显存/算力限流 | MB/百分比级 | 需要按显存精确计费切分 | 备选,默认不装 |
核心原则:一张卡只用一种切分方式,一类节点只服务一类业务,用 label + taint 隔离。
8.2 安装 GPU Operator
bash
# 镜像已全部同步 Harbor platform 项目
helm install gpu-operator harbor-chartmuseum/platform/gpu-operator \
-n gpu-operator --create-namespace --version 25.3.x \
--set operator.repository=harbor.example.com/platform \
--set driver.enabled=true \
--set driver.version=570.133.20 \
--set driver.repository=harbor.example.com/platform \
--set toolkit.enabled=true \
--set devicePlugin.enabled=true \
--set dcgmExporter.enabled=true \
--set migManager.enabled=true \
--set validator.repository=harbor.example.com/platform
kubectl -n gpu-operator get pods -w # 等待全部 Running(driver 编译安装需 5~15 分钟)验证 GPU 可见:
bash
kubectl run gpu-test --rm -it --restart=Never \
--image=harbor.example.com/library/cuda:12.8.0-base-ubuntu24.04 \
--overrides='{
"spec":{
"tolerations":[{"key":"gpu-cluster.io/pool","operator":"Equal","value":"train","effect":"NoSchedule"}],
"nodeSelector":{"gpu-cluster.io/pool":"train"},
"containers":[{
"name":"gpu-test",
"image":"harbor.example.com/library/cuda:12.8.0-base-ubuntu24.04",
"command":["nvidia-smi","-L"],
"resources":{"limits":{"nvidia.com/gpu":1}}
}]
}}'
# 期望输出:GPU 0: NVIDIA RTX PRO 6000 Blackwell ...节点 GPU 拓扑确认(训练性能基础):
bash
kubectl debug node/gpu-train-01 -it --image=harbor.example.com/library/ubuntu:24.04 -- chroot /host nvidia-smi topo -m
# 8 卡之间 PIX/PXB 为优;跨 socket 的 SYS 路径尽量避免(训练框架用 CUDA_VISIBLE_DEVICES 排序规避)8.3 训练池(20 台):默认整卡,无需操作
kubectl describe node gpu-train-01 | grep nvidia.com/gpu 应显示 8。
8.4 推理池(8 台):启用 MIG
bash
# 整卡切 4 个 1g.24gb 实例(8 台共 8×8×4=256 个实例)
for n in gpu-infer-0{1..8}; do
kubectl label node $n nvidia.com/mig.config=all-1g.24gb --overwrite
done
kubectl -n gpu-operator logs -l app=nvidia-mig-manager -f # 观察切分
kubectl get node gpu-infer-01 -o json | jq '.status.allocatable' | grep mig
# 期望:nvidia.com/mig-1g.24gb: "32"临时整卡:某台需跑 70B+ 大模型时
kubectl label node gpu-infer-08 nvidia.com/mig.config=all-disabled --overwrite(先 drain 该节点)。
8.5 开发池(2 台):Time-Slicing
yaml
# time-slicing-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: time-slicing-config
namespace: gpu-operator
data:
dev-pool: |-
version: v1
sharing:
timeSlicing:
resources:
- name: nvidia.com/gpu
replicas: 8bash
kubectl apply -f time-slicing-config.yaml
helm upgrade gpu-operator harbor-chartmuseum/platform/gpu-operator \
-n gpu-operator --reuse-values \
--set devicePlugin.config.name=time-slicing-config
# 只对开发池节点生效:
kubectl label node gpu-dev-01 gpu-dev-02 nvidia.com/device-plugin.config=dev-pool
kubectl get node gpu-dev-01 -o json | jq '.status.allocatable."nvidia.com/gpu"'
# 期望:64(8 卡 × 8 份)提醒用户:Time-Slicing 不隔离显存,8 个副本共享 96GB,适合能自控显存的开发场景。
第 9 章 多租户体系
9.1 组织模型
Rancher Project = 团队(team-algo-a / team-algo-b / inference-serving)
└─ Namespace = 业务/环境(team-algo-a-train / team-algo-a-dev)
├─ ResourceQuota(GPU/CPU/内存/RDMA 配额)
├─ LimitRange(容器默认资源,防止裸 Pod 打满节点)
├─ NetworkPolicy(默认拒绝跨命名空间)
└─ LocalQueue(Kueue 队列,见第 11 章)
Rancher 角色:Project Owner(管成员)/ Member(用资源)/ Read-only9.2 命名空间模板
yaml
apiVersion: v1
kind: Namespace
metadata:
name: team-algo-a-train
labels: {gpu-cluster.io/team: algo-a}
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota
namespace: team-algo-a-train
spec:
hard:
requests.nvidia.com/gpu: "32" # 训练池给该团队 32 整卡
rdma/rdma_shared_device_a: "32"
requests.cpu: "512"
requests.memory: 2Ti
---
apiVersion: v1
kind: LimitRange
metadata:
name: defaults
namespace: team-algo-a-train
spec:
limits:
- default: {cpu: "4", memory: 16Gi}
defaultRequest: {cpu: "2", memory: 8Gi}
type: Container
---
# 推理命名空间(MIG 配额示例)
apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota
namespace: inference-serving
spec:
hard:
requests.nvidia.com/mig-1g.24gb: "64"
---
# 默认网络隔离
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: team-algo-a-train
spec:
podSelector: {}
policyTypes: [Ingress, Egress]9.3 强制池隔离
- 业务 YAML 全部由平台模板注入
tolerations + nodeSelector; - 可选增强:装 OPA Gatekeeper,策略"带 GPU request 的 Pod 必须带池 nodeSelector,且与命名空间标签匹配",杜绝跨池调度。
第 10 章 计算网接入(Multus + RDMA)
10.1 安装 Multus
bash
kubectl apply -f multus-daemonset-thick.yml # YAML 中镜像已改 Harbor
kubectl -n kube-system get pods -l app=multus10.2 macvlan 辅网(推理池 vLLM 多机 TP 用)
yaml
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
name: compute-net
namespace: kube-system
spec:
config: |
{
"cniVersion": "0.3.1",
"type": "macvlan",
"master": "ens2f0np0",
"mode": "bridge",
"mtu": 9000,
"ipam": {
"type": "whereabouts",
"range": "192.168.100.100-192.168.100.250/24",
"routes": [{"dst": "192.168.100.0/24"}]
}
}Pod 引用:k8s.v1.cni.cncf.io/networks: kube-system/compute-net,NCCL 用 NCCL_SOCKET_IFNAME=net1。
10.3 RDMA 共享设备插件(训练池 NCCL over RoCEv2)
bash
helm install network-operator harbor-chartmuseum/platform/network-operator \
-n network-operator --create-namespace \
--set rdmaSharedDevicePlugin.deploy=true \
--set rdmaSharedDevicePlugin.image.repository=harbor.example.com/platform/k8s-rdma-shared-dev-plugin \
--set rdmaSharedDevicePlugin.resources[0].name=rdma_shared_device_a \
--set rdmaSharedDevicePlugin.resources[0].ifNames='[ens2f0np0]' \
--set rdmaSharedDevicePlugin.resources[0].rdmaHcaMax=63
kubectl -n network-operator get pods
kubectl describe node gpu-train-01 | grep rdma # allocatable 出现 rdma/rdma_shared_device_a: 63训练 Pod 资源与 NCCL 环境变量(模板,两个章节都会引用):
yaml
resources:
limits:
nvidia.com/gpu: 8
rdma/rdma_shared_device_a: 1
env:
- {name: NCCL_IB_HCA, value: "mlx5_2"} # ibv_devices 输出中计算口对应设备名,按实际改
- {name: NCCL_IB_GID_INDEX, value: "3"} # show_gids 确认 RoCEv2
- {name: NCCL_IB_DISABLE, value: "0"}
- {name: NCCL_SOCKET_IFNAME, value: "eth0"}
- {name: NCCL_DEBUG, value: "INFO"}第 11 章 Kueue 队列调度
11.1 为什么需要
多机训练/批量推理任务需要 gang 调度(要么全部 Pod 一起起,要么排队等待),否则会出现"半个任务的 Pod 占着 GPU 等另一半"死锁。Kueue 是 K8s 官方批调度方案,与 Kubeflow Job 原生集成。
11.2 安装
bash
kubectl apply --server-side -f kueue-v0.12.x-manifests.yaml # 镜像已改 Harbor
kubectl -n kueue-system get pods11.3 资源模型(与节点池对齐)
yaml
# ResourceFlavor:绑定训练池节点
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
name: train-8gpu
spec:
nodeLabels: {gpu-cluster.io/pool: train}
nodeTaints:
- {key: gpu-cluster.io/pool, value: train, effect: NoSchedule}
---
# ClusterQueue:训练池总量
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: train-cq
spec:
resourceGroups:
- coveredResources: ["nvidia.com/gpu", "rdma/rdma_shared_device_a", "cpu", "memory"]
flavors:
- name: train-8gpu
resources:
- {name: nvidia.com/gpu, nominalQuota: 160}
- {name: rdma/rdma_shared_device_a, nominalQuota: 160}
- {name: cpu, nominalQuota: 4000}
- {name: memory, nominalQuota: 40Ti}
preemption:
withinClusterQueue: LowerPriority
---
# 团队队列
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
name: algo-a-queue
namespace: team-algo-a-train
spec:
clusterQueue: train-cq
---
# 推理池(MIG 实例配额,用于批量离线推理任务排队)
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
name: mig-24g
spec:
nodeLabels: {gpu-cluster.io/pool: infer}
nodeTaints:
- {key: gpu-cluster.io/pool, value: infer, effect: NoSchedule}
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: infer-cq
spec:
resourceGroups:
- coveredResources: ["nvidia.com/mig-1g.24gb"]
flavors:
- name: mig-24g
resources:
- {name: nvidia.com/mig-1g.24gb, nominalQuota: 256}业务侧只需给 Job 加标签 kueue.x-k8s.io/queue-name: algo-a-queue 即进入队列;超额任务自动排队(Inadmissible),配额释放后自动调度。
bash
kubectl get clusterqueue train-cq # 看 Flavors/Usage/Admitted
kubectl -n team-algo-a-train get workloads # 排队情况第 12 章 分布式训练(Kubeflow Training Operator)
12.1 安装
bash
# 外网机器 clone 仓库导出 YAML,镜像地址替换为 Harbor 后拷入内网
kubectl apply -k training-operator-manifests/overlays/standalone/
kubectl -n kubeflow get pods12.2 NCCL 验收测试(2 机 16 卡 AllReduce)——先跑通再上业务
yaml
apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
name: nccl-test
namespace: team-algo-a-train
labels:
kueue.x-k8s.io/queue-name: algo-a-queue
spec:
pytorchReplicaSpecs:
Master:
replicas: 1
template: &tpl
spec:
tolerations:
- {key: gpu-cluster.io/pool, value: train, effect: NoSchedule}
nodeSelector: {gpu-cluster.io/pool: train}
containers:
- name: pytorch
image: harbor.example.com/gpu-cluster/pytorch:25.05-py3
command: ["bash", "-c"]
args:
- |
/opt/nccl-tests/build/all_reduce_perf -b 1G -e 8G -f 2 -g 8 \
|| torchrun --nnodes=2 --nproc_per_node=8 \
--rdzv_backend=c10d --rdzv_endpoint=$MASTER_ADDR:29500 \
/workspace/nccl_allreduce.py
resources:
limits:
nvidia.com/gpu: 8
rdma/rdma_shared_device_a: 1
env:
- {name: NCCL_IB_HCA, value: "mlx5_2"}
- {name: NCCL_IB_GID_INDEX, value: "3"}
- {name: NCCL_IB_DISABLE, value: "0"}
- {name: NCCL_SOCKET_IFNAME, value: "eth0"}
- {name: NCCL_DEBUG, value: "INFO"}
Worker:
replicas: 1
template: *tpl验收标准:100G RoCE 单轨 AllReduce busbw ≥ 9 GB/s;单机 8 卡 busbw 视 PCIe 拓扑 ≥ 40 GB/s。不达标按 4.4/2.4.2 排查。
12.3 正式训练最佳实践
| 要点 | 建议 |
|---|---|
| 并行策略 | 8 卡机内 TP/PP(PCIe 互联),跨机 DP/EP;70B 级全参微调建议 ≥8 机 |
| 框架 | Megatron-LM / DeepSpeed(NGC pytorch 镜像自带),PyTorchJob 或 MPIJob |
| 数据 | 训练集放节点 /data(本地 NVMe RAID0),DataLoader num_workers≥8、pin_memory=true |
| Checkpoint | 写本地 NVMe + 异步同步到 NFS/Ceph;按 Kueue 抢占策略保留最近 2 个 |
| 弹性 | torchrun --rdzv-backend=c10d + Kueue 失败自动重排队 |
| NUMA | 镜像内用 nvidia-smi topo -m 确定 CPU affinity,必要时 numactl 绑核 |
第 13 章 vLLM 推理服务与生产力大模型部署推荐
13.1 推理服务总体设计
- 编排:LeaderWorkerSet(LWS)—— 多机多卡推理的标准方案,Leader/Worker 一组原子扩缩容。
- 引擎:vLLM(OpenAI 兼容 API),continuous batching + PagedAttention。
- 暴露:NodePort(30000-32767 固定端口)+ 内网 HAProxy 固定入口(可选增强)。
- 模型权重:节点本地 NVMe
/data/models预置(hostPath 只读挂载,启动最快),由 model-syncer DaemonSet 从 Harbor OCI / 内网对象存储分发。
13.1.1 安装 LWS
bash
kubectl apply --server-side -f lws-v0.6.x-manifests.yaml # 镜像已改 Harbor
kubectl -n lws-system get pods13.1.2 模型分发 DaemonSet(每台推理/开发节点预置)
bash
# 简易版:首次人工 scp/rsync 到每台 /data/models/<模型名>
# 规范版:model-syncer DaemonSet,容器内跑 rsync 从内网文件服务器拉取
mkdir -p /data/models/{Qwen3-32B,DeepSeek-R1-0528,Qwen2.5-Coder-32B-Instruct,bge-m3,bge-reranker-v2-m3}13.2 生产力大模型部署推荐(23TB 显存怎么用)
原则:少数超大模型撑起"智能上限",一批中等模型扛起"日常生产力吞吐"。
| 层级 | 模型 | 部署形态 | 资源 | 用途 |
|---|---|---|---|---|
| 旗舰 | DeepSeek-R1-0528(671B,FP8) | 8 机 64 卡 TP64(或 4 机 32 卡 + FP8) | 训练池闲时/推理池整卡节点,显存约 700GB | 复杂推理、代码架构、深度分析(智能上限) |
| 主力 | Qwen3-235B-A22B(FP8) | 4 机 32 卡 TP32 | ~250GB 显存 | 日常高质量问答/写作 |
| 吞吐主力 | Qwen3-32B / Qwen2.5-32B-Instruct | 单卡整卡 ×N 副本(推理池整卡节点) | 每副本 1 卡 | 日常问答、翻译、摘要,走量 |
| 代码 | Qwen2.5-Coder-32B-Instruct | 单卡 ×N 副本 | 每副本 1 卡 | 接 IDE(Continue/Cline),程序员工效核心 |
| 轻量 | Qwen3-14B / 8B | MIG 1g.24gb 实例 ×N | 每副本 1 实例 | 客服、分类、Embedding 前置处理 |
| RAG 必备 | bge-m3(embedding)+ bge-reranker-v2-m3 | MIG 实例 | 各 2~4 实例 | 企业知识库检索 |
| 多模态(可选) | Qwen2.5-VL-32B/72B | 整卡 TP | — | 图片/文档理解 |
推理池 8 台(64 卡)参考分配:2 台整卡节点跑旗舰(TP16 跨机)+ 4 台 MIG(128 实例)跑 14B/32B/embedding/reranker + 2 台整卡节点跑 32B/Coder 各 8 副本。训练池白天训练、夜间可承接旗舰模型批量推理(离线批处理任务走 Kueue infer-cq)。
13.3 多机整卡推理示例(旗舰模型 TP16,2 机 16 卡)
yaml
apiVersion: leaderworkerset.x-k8s.io/v1
kind: LeaderWorkerSet
metadata:
name: vllm-flagship
namespace: inference-serving
spec:
replicas: 1
leaderWorkerTemplate:
size: 2 # 2 节点 × 8 卡 = TP16
restartPolicy: RecreateGroupOnPodRestart
leaderTemplate:
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: kube-system/compute-net
spec:
tolerations:
- {key: gpu-cluster.io/pool, value: infer, effect: NoSchedule}
nodeSelector: {gpu-cluster.io/pool: infer}
hostPID: true # ray 需要
containers:
- name: vllm
image: harbor.example.com/gpu-cluster/vllm-openai:v0.9.x
command: ["bash", "-c"]
args:
- |
ray start --head --port=6379 --num-gpus=8 && sleep 5 && \
vllm serve /data/models/Qwen3-235B-A22B-FP8 \
--tensor-parallel-size 16 \
--served-model-name qwen3-235b --port 8000 \
--max-model-len 32768 --gpu-memory-utilization 0.92 \
--enable-expert-parallel
env:
- {name: NCCL_SOCKET_IFNAME, value: "net1"}
- {name: HF_HUB_OFFLINE, value: "1"}
ports: [{containerPort: 8000}, {containerPort: 6379}]
resources:
limits: {nvidia.com/gpu: 8}
readinessProbe:
httpGet: {path: /health, port: 8000}
initialDelaySeconds: 300
periodSeconds: 10
volumeMounts: [{name: models, mountPath: /data/models, readOnly: true}]
volumes:
- name: models
hostPath: {path: /data/models, type: Directory}
workerTemplate:
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: kube-system/compute-net
spec:
tolerations:
- {key: gpu-cluster.io/pool, value: infer, effect: NoSchedule}
nodeSelector: {gpu-cluster.io/pool: infer}
hostPID: true
containers:
- name: vllm-worker
image: harbor.example.com/gpu-cluster/vllm-openai:v0.9.x
command: ["bash", "-c"]
args: ["ray start --address=$(LWS_LEADER_ADDRESS):6379 --num-gpus=8 --block"]
env:
- {name: NCCL_SOCKET_IFNAME, value: "net1"}
resources:
limits: {nvidia.com/gpu: 8}
---
apiVersion: v1
kind: Service
metadata:
name: vllm-flagship
namespace: inference-serving
spec:
type: NodePort
selector:
leaderworkerset.sigs.k8s.io/name: vllm-flagship
role: leader
ports:
- {port: 8000, targetPort: 8000, nodePort: 30080}验证:
bash
curl http://10.10.2.31:30080/v1/models
curl http://10.10.2.31:30080/v1/chat/completions -H 'Content-Type: application/json' -d '{
"model": "qwen3-235b",
"messages": [{"role":"user","content":"用一句话解释 RoCEv2"}]
}'13.4 MIG 实例推理示例(32B 模型,单实例一个副本)
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-qwen3-32b
namespace: inference-serving
spec:
replicas: 4 # 4 个 MIG 实例副本
selector:
matchLabels: {app: vllm-qwen3-32b}
template:
metadata:
labels: {app: vllm-qwen3-32b}
spec:
tolerations:
- {key: gpu-cluster.io/pool, value: infer, effect: NoSchedule}
nodeSelector: {gpu-cluster.io/pool: infer}
containers:
- name: vllm
image: harbor.example.com/gpu-cluster/vllm-openai:v0.9.x
args:
- serve
- /data/models/Qwen3-32B
- --port=8000
- --gpu-memory-utilization=0.9
- --max-model-len=16384
- --served-model-name=qwen3-32b
env:
- {name: HF_HUB_OFFLINE, value: "1"}
ports: [{containerPort: 8000}]
resources:
limits:
nvidia.com/mig-1g.24gb: 1
readinessProbe:
httpGet: {path: /health, port: 8000}
initialDelaySeconds: 120
volumeMounts: [{name: models, mountPath: /data/models, readOnly: true}]
volumes:
- name: models
hostPath: {path: /data/models, type: Directory}
---
apiVersion: v1
kind: Service
metadata:
name: vllm-qwen3-32b
namespace: inference-serving
spec:
type: NodePort
selector: {app: vllm-qwen3-32b}
ports:
- {port: 8000, targetPort: 8000, nodePort: 30081}13.5 统一入口与应用接入(把算力变成生产力)
┌─────────────┐ ┌──────────────────────┐
│ HAProxy VM │──▶│ NodePort 30080 旗舰模型 │ ← OpenAI 兼容 API
│ 10.10.0.20 │──▶│ NodePort 30081 32B模型 │
│ (固定入口) │──▶│ NodePort 30082 Coder │
└──────┬──────┘ └──────────────────────┘
│
┌────┴─────┬───────────┬───────────┬────────────┐
│ OpenWebUI│ Continue/ │ Dify/RAG │ 内部系统 API │
│ (对话门户)│ Cline(IDE)│ (知识库) │ 集成 │
└──────────┴───────────┴───────────┴────────────┘HAProxy 配置示例:
# /etc/haproxy/haproxy.cfg 片段
frontend ai_gateway
bind *:80
use_backend flagship if { path_beg /v1 } { hdr(X-Model) qwen3-235b }
default_backend qwen32b
backend flagship
balance roundrobin
server infer1 10.10.2.31:30080 check
server infer2 10.10.2.32:30080 check
backend qwen32b
balance roundrobin
server infer3 10.10.2.33:30081 check
server infer4 10.10.2.34:30081 check生产力落地组合推荐:
- Open WebUI(部署在无 GPU 的管理 VM):统一对话门户,接所有 vLLM 端点,支持多用户/RBAC/知识库。
- Continue.dev / Cline 插件:开发团队 IDE 直连
qwen2.5-coder-32b端点,代码补全/重构/审查。 - Dify + bge-m3 + reranker:企业知识库 RAG,文档问答。
- 批量离线推理:文档翻译/数据清洗类任务用 Kueue infer-cq 排队跑训练池闲时资源。
第 14 章 监控告警体系
bash
helm install monitoring harbor-chartmuseum/platform/kube-prometheus-stack \
-n monitoring --create-namespace \
--set prometheus.prometheusSpec.retention=30d \
--set grafana.adminPassword='xxx'
# GPU Operator 的 dcgm-exporter 自带 ServiceMonitor,自动被 Prometheus 采集
# Grafana 导入 Dashboard:12239(NVIDIA DCGM Exporter)
# NodePort 暴露:
kubectl patch svc monitoring-grafana -n monitoring \
-p '{"spec":{"type":"NodePort","ports":[{"port":80,"targetPort":3000,"nodePort":30300}]}}'告警规则建议(Alertmanager 推送到企业微信/钉钉/邮件):
| 指标 | 阈值 | 含义 |
|---|---|---|
DCGM_FI_DEV_GPU_TEMP | > 85℃ | GPU 过热(查机房散热/风扇) |
DCGM_FI_DEV_XID_ERRORS | > 0 | GPU 硬件错误(立即处理,Xid 79/48/63 等) |
DCGM_FI_DEV_FB_USED / FB_FREE | > 95% 持续 | 显存水位(MIG 多租户重点) |
DCGM_FI_DEV_GPU_UTIL == 0 且 Pod 在跑 | 持续 10min | 任务挂死/数据加载瓶颈 |
节点 node_up / kubelet | down | 节点故障 |
Kueue pending_workloads | > N | 队列积压 |
另外建议装 Loki + Promtail 采集 Pod 日志,NCCL 排障时 NCCL_DEBUG=INFO NCCL_DEBUG_SUBSYS=INIT,NET 的日志非常关键。
第 15 章 整体验收 Checklist
基础设施
- [ ] 交换机:管理网 MLAG 双活正常,拔一根光纤业务无感知;计算网 PFC/ECN 已配
- [ ] 每节点
cat /proc/net/bonding/bond0:双口 up、802.3ad、总速率 200G - [ ] 跨节点
ib_write_bw≥ 95 Gb/s;MTU 端到端 9000 - [ ] IPMI 全部可达,可远程开关机
集群
- [ ] 33 节点 Ready(3 CP + 30 Worker),Rancher UI 已纳管
- [ ]
kubectl get nodes -L gpu-cluster.io/pool:20 train / 8 infer / 2 dev,taint 正确 - [ ] 资源呈现:训练池
nvidia.com/gpu: 8/台;推理池nvidia.com/mig-1g.24gb: 32/台;开发池nvidia.com/gpu: 64/台 - [ ] 任意 1 台 CP VM 关机,API VIP 仍可用;etcd 快照任务在跑
GPU 能力
- [ ] 训练池整卡 Pod
nvidia-smi -L正常 - [ ] MIG 实例 Pod 只见自己 24GB 实例,互不影响
- [ ] 开发池单卡可调度 8 个 Time-Slicing Pod
性能
- [ ] NCCL 双机 AllReduce busbw ≥ 9 GB/s(100G RoCE)
- [ ] vLLM 旗舰模型 TP16 启动成功,首 token 延迟与吞吐符合预期
平台能力
- [ ] Kueue:超额任务 Inadmissible 排队,资源释放后自动调度
- [ ] 多租户:超配额被拒、跨池调度被拒、跨命名空间网络不通
- [ ] 推理 API:NodePort 各端口返回正常,HAProxy 入口统一可用
- [ ] Grafana 12239 面板 240 卡数据齐全;Xid 告警测试触发
- [ ] 全部 Pod 镜像来自 harbor.example.com(无任何外网依赖)
- [ ] 节点重启后:bond 恢复、GPU Operator 自愈、MIG 配置保持、LWS 服务自动拉起
第 16 章 常见问题速查
| 问题 | 排查路径 |
|---|---|
| Pod Pending,GPU allocatable 为 0 | device-plugin 是否运行 → 池 label/taint 与 Pod toleration → ResourceQuota → Kueue 配额 |
| Kueue 任务一直 Inadmissible | kubectl describe workload;ResourceFlavor 的 nodeLabels/nodeTaints 与节点一致性;nominalQuota 余量 |
| NCCL 跨机卡死/极慢 | NCCL_SOCKET_IFNAME → show_gids GID index → 交换机 PFC/ECN → MTU 端到端 → ib_write_bw 单机对测 → 固件 |
ib_write_bw 不达标 | MTU → 线缆/光模块(换 DAC 测试)→ 交换机端口 counters(PFC pause/丢包)→ CX-7 固件 |
| MIG 切分失败/自动回退 | 卡上有残留进程(先 drain)→ 驱动 ≥570 → nvidia-smi -mig 1 → mig-manager 日志 |
| Time-Slicing Pod 被 OOMKill | 时间片不隔离显存:副本显存之和 > 96GB;减少 replicas 或改 MIG |
| vLLM 启动失败 | 模型路径/权限 → HF_HUB_OFFLINE=1 → MIG 24GB 放不下(32B FP16 需 ~70GB,用整卡或 AWQ/FP8)→ 日志看 KV cache 计算 |
| vLLM 多机 ray 连不上 | compute-net IP 是否通(跨节点 ping net1 IP)→ hostPID → 6379 端口 |
| Harbor 拉镜像失败 | registries.yaml auth/endpoint → 机器人 token 权限 → http/https 模式一致 → harbor 容器状态 |
| Rancher 纳管 agent 失败 | systemDefaultRegistry 是否指向 Harbor → agent 镜像是否存在 → cattle-system 日志 |
| RKE2 agent 加入失败 | token 一致性 → 9345 连通(VIP 状态)→ 节点时间同步(NTP) |
| GPU 掉卡(nvidia-smi 少卡) | dmesg 看 PCIe/Xid 错误 → 供电/温度 → 重插/换槽位 → IPMI 看硬件日志 |
| 训练 loss 异常波动 | 先查 Xid 错误和 GPU 温度(坏卡 Silent Error)→ 再看数据/代码 |
附录 A 镜像同步清单(images.txt 核心版)
# 平台
rancher/rancher:v2.12.x
rancher/fleet-agent:v0.13.x
rancher/shell:v0.5.x
nvcr.io/nvidia/gpu-operator:v25.3.x
nvcr.io/nvidia/driver:570.133.20-ubuntu24.04
nvcr.io/nvidia/k8s-device-plugin:v0.17.x
nvcr.io/nvidia/container-toolkit:1.17.x
nvcr.io/nvidia/dcgm-exporter:4.x.x-ubuntu22.04
nvcr.io/nvidia/cloud-native/k8s-mig-manager:v0.10.x
nvcr.io/nvidia/cloud-native/k8s-rdma-shared-dev-plugin:v1.5.x
ghcr.io/k8snetworkplumbingwg/multus-cni:v4.2.x
ghcr.io/k8snetworkplumbingwg/whereabouts:v0.8.x
registry.k8s.io/leaderworkerset/lws:v0.6.x
registry.k8s.io/kueue/kueue:v0.12.x
kubeflow/training-operator:v1-xxx
# 监控(kube-prometheus-stack 全套)
quay.io/prometheus/prometheus:v3.x
quay.io/prometheus-operator/prometheus-operator:v0.8x
docker.io/grafana/grafana:11.x
quay.io/prometheus/node-exporter:v1.9.x
registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.15.x
# 业务
nvcr.io/nvidia/pytorch:25.05-py3
docker.io/vllm/vllm-openai:v0.9.x
nvcr.io/nvidia/cuda:12.8.0-base-ubuntu24.04
docker.io/library/ubuntu:24.04
docker.io/library/busybox:latest
# 应用层(生产力)
ghcr.io/open-webui/open-webui:main
docker.io/ollama/ollama:latest # 可选完整清单以实际 helm chart values 里的 image 字段为准,部署前用
helm template | grep image:逐一核对。
附录 B 调池与运维速记
bash
# 节点从推理池迁回训练池
kubectl drain gpu-infer-08 --ignore-daemonsets --delete-emptydir-data
kubectl label node gpu-infer-08 nvidia.com/mig.config=all-disabled --overwrite
kubectl label node gpu-infer-08 gpu-cluster.io/pool=train --overwrite
kubectl taint node gpu-infer-08 gpu-cluster.io/pool=infer:NoSchedule-
kubectl taint node gpu-infer-08 gpu-cluster.io/pool=train:NoSchedule
kubectl uncordon gpu-infer-08
# 记得同步调整 Kueue train-cq / infer-cq 的 nominalQuota
# 驱动升级(滚动,灰度先行)
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
helm upgrade gpu-operator ... --set driver.version=575.x.x
# 观察一台没问题后逐台进行
# 查看 GPU 分配全景
kubectl get nodes -o custom-columns=NAME:.metadata.name,POOL:.metadata.labels."gpu-cluster\.io/pool",GPU:.status.allocatable."nvidia\.com/gpu",MIG:.status.allocatable."nvidia\.com/mig-1g\.24gb"附录 C 术语速查
| 术语 | 说明 |
|---|---|
| RDMA | 远程直接内存访问,网卡直读写对端内存,绕过 CPU/内核 |
| RoCEv2 | 跑在 UDP/IP 以太网上的 RDMA,CX-7 支持 |
| PFC / ECN | 以太网无损机制:按优先级暂停 + 拥塞标记,RoCE 必备 |
| MIG | NVIDIA 多实例 GPU,单卡硬件级切分为多个隔离实例 |
| Time-Slicing | GPU 时间片共享,无显存隔离 |
| LWS | LeaderWorkerSet,多机推理编排 CRD |
| Kueue | K8s 原生批任务队列/配额调度器 |
| Gang 调度 | 一组 Pod 要么全部调度要么都不调度 |
| NCCL | NVIDIA 多卡/多机集合通信库(AllReduce 等) |
| TP / PP / DP / EP | 张量并行 / 流水线并行 / 数据并行 / 专家并行 |