8台DGX Spark集群搭建实战:从网络规划到Kubernetes调度

发布时间:2026/8/27 20:16:43
8台DGX Spark集群搭建实战:从网络规划到Kubernetes调度 如果把 8 台 DGX Spark 连成一整个集群真正的门槛不在拆箱和通电而在于网络规划、并行策略、调度器配置和故障排查。单台 DGX Spark 是 NVIDIA 面向桌面实验室推出的 AI 超级计算机核心是 Grace Blackwell 平台与 128GB 统一内存适合在本地加载大模型但当你把 8 台放在一个机架上想统一做模型微调、推理服务或者多租户实验时问题就从“能不能跑”变成“怎样让 8 台机器像一个人那样协同”。本文从工程视角拆解这套 8 台 DGX Spark 集群先讲清楚单机能力、集群收益和并行选型再给出 Kubernetes NVIDIA GPU Operator 的搭建步骤最后补上性能验证、常见故障和生产环境建议。无论你是刚拿到两台设备想做张量并行还是已经在跑 8 台集群都可以按顺序复现。这里的“Spark”不是 Apache Spark也不是大数据离线计算框架。NVIDIA DGX Spark 的产品命名偏“桌面级 AI 超算”它不负责跑 Spark SQL它负责的是大模型训练、微调、推理和原型验证。下面所有章节说的都是 GPU 集群不是数据仓库集群。1. 先理解 DGX Spark 单机能力再判断 8 台集群是否值得组1.1 DGX Spark 到底是一台怎样的设备通俗地说DGX Spark 是一台可以放在桌面或小车上的小型 AI 服务器。它不像传统 GPU 服务器那样需要两层机柜和 8 块大板卡而是把 CPU、GPU、统一内存、网络和系统管理能力压缩进一个紧凑机身里。技术定义上DGX Spark 基于 NVIDIA Grace Blackwell 平台采用 GB10 超级芯片。CPU 和 GPU 不再是主机板上分开的部件而是在同一颗超级芯片上完成集成。它提供约 128GB 的统一内存CPU 和 GPU 可以共同访问同一块内存区域。这种设计的核心价值是大模型权重、KV Cache、激活值和框架运行时的临时数据都能放在同一块内存池里减少 CPU 与 GPU 之间的数据搬运。单台 DGX Spark 的官方宣传场景是“在本地运行可达 200B 参数级别的大模型”。这句话要正确理解200B 参数模型通常需要量化、小批次、有限上下文甚至需要牺牲一部分精度才能塞进统一内存。生产环境里的 200B 模型配 64K 上下文、高并发请求、连续推理单台设备会非常吃力。还有一个容易误解的地方统一内存不等于显存。你不能再像看普通 GPU 那样只看“显存 24GB”或“显存 48GB”而要把 CPU 内存和 GPU 内存当成一个大池子统一规划。PyTorch 里torch.cuda.memory_summary()能看到 GPU 侧分配但host侧的内存可能同样成为瓶颈。1.2 用 8 台组集群收益到底在哪里8 台 DGX Spark 从纸面上看统一内存总量接近 1TB。这意味着更大参数规模的模型可能被拆到多台机器上运行多个团队或多个任务也可以并行跑在不同节点上。但要注意8 台设备不自动等价于“单台性能乘以 8”。跨节点通信要走网络而网络带宽和延迟远不能和芯片内部的互连相比。如果把一个需要频繁同步的模型切分到 8 台机器上通信往往会成为新的瓶颈。组集群的真正价值是获得更大的内存池、更高的并发吞吐和更灵活的多任务调度能力。下面这张表可以帮你先判断方向维度单台 DGX Spark8 台 DGX Spark 集群可用统一内存约 128GB约 1TB实际受网络和调度限制典型工作负载单模型推理、原型开发、轻量微调多模型部署、多租户实验、更大模型并行同时并发任务数受单机内存和 GPU 资源限制可按节点拆分支持并行任务跨节点通信不需要必需通信质量直接影响性能运维复杂度低当作一台高性能电脑管理高需处理集群调度、共享存储、监控、故障故障影响范围单台故障任务失败单节点故障可能导致分布式训练中断需要恢复机制如果你的需求只是“一个人跑一个 70B 量化模型”单台 DGX Spark 或两台做简单数据并行很可能就够。如果你要同时跑多个模型、多人共享、定时批量实验才值得组 8 台。1.3 组集群前先想清楚这台集群要跑什么不同业务场景对集群规划的要求差别很大。第一种场景是本地大模型推理服务。目标是让 8 台机器提供稳定的 OpenAI 兼容接口。此类场景需要关注推理引擎的并行策略、请求路由、模型加载时长和 GPU 内存利用率。第二种场景是多节点大模型训练或微调。8 台机器会组成一个分布式训练任务。此时重点是数据并行、流水线并行、检查点保存和失败恢复。网络带宽不足时训练效率会非常明显地下滑。第三种场景是团队 AI 开发平台。需要把 8 台设备当成资源池通过 Kubernetes 给不同成员分配 GPU 配额限制最大并发数并提供统一日志和监控入口。这样即使有人误删 Pod也不会影响整个集群。在动手前先确定你的核心场景。因为场景决定你买什么样的交换机、要不要配共享存储、要不要装训练算子以及要不要搭一套高可用控制平面。没有场景就搭集群最后只会得到一台“能启动但不知道用来干什么”的 8 节点实验环境。2. 8 台 DGX Spark 组集群的前期规划网络、存储和软件栈2.1 网络规划是决定成败的第一项多节点集群必须通信而通信质量和网络强相关。DGX Spark 自带网络接口的速率以及是否支持外接高速网卡要以你手上硬件的具体型号和官方文档为准。这里更重要的是一套通用的网络规划思路。先建一张规划表。8 台机器建议至少规划两类网络管理网络用于 SSH、Kubernetes API、监控采集、系统更新。数据网络用于模型并行、梯度同步、数据集传输、镜像拉取。如果条件允许把两个网络分到不同物理链路或不同 VLAN。数据网络最好使用独立交换机不要和办公室普通流量混在一起。IP 规划示例主机名管理 IP数据 IP角色dgx-spark-m01192.168.10.11192.168.50.11控制面dgx-spark-w01192.168.10.21192.168.50.21Workerdgx-spark-w02192.168.10.22192.168.50.22Workerdgx-spark-w03192.168.10.23192.168.50.23Workerdgx-spark-w04192.168.10.24192.168.50.24Workerdgx-spark-w05192.168.10.25192.168.50.25Workerdgx-spark-w06192.168.10.26192.168.50.26Workerdgx-spark-w07192.168.10.27192.168.50.27Worker在正式部署前至少要把管理 IP 写进/etc/hosts让节点之间能通过主机名互访。实验环境可以不做 DNS生产环境建议用内网 DNS避免大规模集群靠 hosts 文件同步。对于跨节点模型并行10GbE 是第一道底线但不代表 10GbE 一定够用。如果模型用张量并行每一层都需要多次跨节点 all_reduce通信量极大。若使用流水线并行通信量相对小一些。所以网络选型要跟并行策略一起决定而不是先把机器连起来再说。2.2 存储集群不能只有计算节点8 台 DGX Spark 都有自己的本地硬盘但如果每台机器都保存一份完整的模型权重、数据集和日志会出现几个问题模型权重占用大量本地空间且每一份升级都要同步 8 次。微调产生的 checkpoint 散落在各节点节点故障后难以恢复。日志分散排查问题时要登录多台机器。常见的做法是引入共享存储。实验环境可以先用一台节点充当 NFS Server把/data导出到所有节点。也可以部署 MinIO 作为对象存储存放模型权重和数据集训练任务运行时再拉取到本地缓存。NFS 导出示例# 在存储节点执行 sudo mkdir -p /data/models /data/datasets /data/checkpoints sudo chmod 777 /data # 编辑 /etc/exports echo /data 192.168.10.0/24(rw,sync,no_subtree_check,no_root_squash) | sudo tee -a /etc/exports sudo exportfs -ra sudo systemctl restart nfs-server其他节点挂载示例sudo mkdir -p /mnt/dgx-data sudo mount -t nfs 192.168.10.11:/data /mnt/dgx-data # 写入 /etc/fstab echo 192.168.10.11:/data /mnt/dgx-data nfs defaults 0 0 | sudo tee -a /etc/fstab这里要注意NFS 适合存放模型权重、数据集和 checkpoint但不适合把训练日志直接高频写入 NFS。高并发小文件写入会拖慢整个存储。更合理的做法是日志先在本地写再异步同步到对象存储或日志系统。如果实验环境不想引入复杂存储可以先用“本地盘 脚本同步”的方式跑通但要在文档里记录清楚数据在哪台机器。2.3 软件栈版本要对齐否则后面每一步都会踩坑GPU 集群最怕版本错位。驱动版本、CUDA 版本、容器运行时版本、Kubernetes 版本、GPU Operator 版本、模型框架版本任何一个环节不匹配都可能出现“驱动已经装上容器却看不到 GPU”这类问题。一个相对稳定的软件栈规划如下组件作用版本建议DGX OS操作系统和 NVIDIA 原厂驱动基础使用厂商出厂推荐版本不要轻易升级到通用 UbuntuNVIDIA 驱动驱动 GPU 和 CUDA 运行时与 DGX OS 配套containerdKubernetes 容器运行时使用 Kubernetes 官方支持版本Kubernetes集群调度平台使用稳定版避免过新或过旧NVIDIA GPU Operator自动管理驱动、运行时、device plugin 和监控与 Kubernetes 版本兼容CUDA容器内计算框架基础写在基础镜像内跟随模型框架选择PyTorch / vLLM / NeMoAI 负载都放在容器镜像中主机不直接安装需要强调DGX Spark 如果出厂已经安装了 NVIDIA 官方 DGX OS 和驱动就不要为了“更新”而手动重装驱动。很多故障都出在“原本能用升级后反而找不 GPU”的情况。注意DGX Spark 的“统一内存”和普通显卡的“显存”不同不能只看设备显示的内存大小还要考虑系统整体内存分配。部署大模型前先在单机用nvidia-smi、free -g和cat /proc/meminfo确认当前内存占用基线。3. 从零开始搭建 8 节点 Kubernetes 加速集群3.1 初始化前的基础配置这里采用最小可用方案1 个控制面节点 7 个 Worker 节点。生产环境如果在意控制面高可用可以扩展到 3 个控制面节点但会多出 etcd 和负载均衡配置实验阶段先用单控制面跑通。在所有 8 台机器上执行基础配置。设置主机名以控制面节点为例sudo hostnamectl set-hostname dgx-spark-m01安装常用工具并同步时间sudo apt update sudo apt install -y ntpdate sudo ntpdate cn.pool.ntp.org sudo timedatectl set-timezone Asia/Shanghai写入/etc/hosts确保节点之间可以用主机名访问192.168.10.11 dgx-spark-m01 192.168.10.21 dgx-spark-w01 192.168.10.22 dgx-spark-w02 192.168.10.23 dgx-spark-w03 192.168.10.24 dgx-spark-w04 192.168.10.25 dgx-spark-w05 192.168.10.26 dgx-spark-w06 192.168.10.27 dgx-spark-w07加载内核模块并配置转发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这些配置不是随意加的。Kubernetes 的 Service、Pod 跨节点通信依赖 iptables 和 IP 转发br_netfilter是为了让网桥流量也能被 iptables 规则处理。3.2 用 kubeadm 初始化控制平面在控制面节点安装 kubeadm、kubelet、kubectl。由于 Kubernetes 版本更新很快这里不写死具体版本建议先运行apt list -a kubeadm查看可用版本选择一个稳定版本。sudo apt install -y kubeadm kubelet kubectl初始化控制面。这里选择 Calico 作为网络插件所以--pod-network-cidr要与 Calico 默认网段一致。如果你的内网网段已被其他系统占用需要调整为不冲突的地址。sudo kubeadm init \ --pod-network-cidr10.244.0.0/16 \ --apiserver-advertise-address192.168.10.11初始化完成后按提示执行mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config接着安装 Calico CNI。具体版本以官方发布为准这里给出通用命令kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/master/manifests/calico.yaml然后查看节点状态kubectl get nodes此时控制面节点可能没有 Ready因为操作系统的kubelet刚启动需要等待一会儿。网络插件启动完成后状态会变为 Ready。Worker 节点加入集群使用kubeadm join命令。如果初始化时没有保存 join token可以在控制面重新生成kubeadm token create --print-join-command在 Worker 上执行返回的命令。完成后在控制面确认kubectl get nodes -o wide如果所有节点均处于ReadyKubernetes 控制面搭建就完成了。这一步是整个集群的骨架后续 GPU 能力、存储挂载、模型调度都建立在它之上。3.3 安装 NVIDIA GPU Operator而不是手动每台装驱动在很多入门教程里大家习惯手工安装 NVIDIA 驱动然后配置 Docker 的 nvidia-container-runtime。但 8 台机器逐个手工装驱动效率低且容易漏版本。更好的做法是使用 NVIDIA GPU Operator它通过 Kubernetes DaemonSet 在每台节点上自动安装和配置 GPU 运行环境。安装 GPU Operator 前先确认每台节点能否识别 GPUnvidia-smi如果控制面节点本身没有 GPU也可以让 GPU Operator 只作用于 Worker 节点。对于 8 台 DGX Spark建议默认在所有节点启用。使用 Helm 安装helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm repo update helm install gpu-operator nvidia/gpu-operator \ --namespace gpu-operator \ --create-namespace \ --set driver.enabledfalse这里设置了driver.enabledfalse原因是你手上的 DGX Spark 很可能已经预装了官方驱动。如果 GPU Operator 再次自动安装驱动可能与原厂驱动冲突。若你的设备是裸系统、没有 NVIDIA 驱动再把driver.enabled改成true。安装完成后查看是否启动成功kubectl get pods -n gpu-operator kubectl describe nodes | grep -i nvidia如果节点上出现了类似nvidia.com/gpu: 1的资源说明 GPU 资源已经上报给 Kubernetes。随后用一个小 Pod 验证cat EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: nvidia-smi-test spec: restartPolicy: Never containers: - name: nvidia-smi image: nvidia/cuda:12.4.1-base-ubuntu22.04 command: [nvidia-smi] resources: limits: nvidia.com/gpu: 1 EOF kubectl logs nvidia-smi-test看到 NVIDIA 驱动信息后删除测试 Podkubectl delete pod nvidia-smi-test这一步完成8 台机器已经在 Kubernetes 层具备了 GPU 调度能力。但距离“跑大模型”还差一步多节点分布式任务不能简单靠单个 Pod 完成。4. 让大模型真正跑在 8 台 DGX Spark 上并行策略与调度4.1 多机并行不是 Kubernetes 自动帮你完成的Kubernetes 原生 GPU 调度目前只能解决“Pod 请求一块 GPU”和“Pod 请求两块 GPU”的问题。当你给一个 Pod 写limits: nvidia.com/gpu: 2时调度器会尝试在一个节点上找到两块可用 GPU。它不会把一个 Pod 拆到两台机器上。多机大模型任务需要拆成多个 Pod每个 Pod 跑在各自的节点上然后由分布式训练框架负责节点间通信。这类任务通常使用 PyTorchJob、MPIJob 或者 StatefulSet Headless Service 来管理。因此你会遇到两个新问题Kubernetes 如何给多个 Pod 分配稳定的主机名和 IP分布式框架如何知道谁是 master、谁是 worker、如何建立通信解决这两个问题最简单的方式是 StatefulSet。StatefulSet 会为每个 Pod 生成固定名称比如dist-worker-0、dist-worker-1配合 Headless ServicePod 之间可以通过dist-worker-0.dist-test这样的 DNS 名字互相访问。4.2 用 StatefulSet 跑一个多节点通信验证任务下面这段示例用来验证 8 节点之间的 PyTorch 分布式通信是否正常不是完整训练代码。你需要把核心脚本做成镜像或者在启动命令里动态执行。先创建 Headless Service 和 StatefulSetapiVersion: v1 kind: Service metadata: name: dist-test spec: clusterIP: None selector: app: dist-test ports: - port: 23456 targetPort: 23456 --- apiVersion: apps/v1 kind: StatefulSet metadata: name: dist-worker spec: serviceName: dist-test replicas: 8 selector: matchLabels: app: dist-test template: metadata: labels: app: dist-test spec: containers: - name: main image: pytorch/pytorch:2.3.1-cuda12.1-cudnn8-runtime command: [sh, -c] args: - | python /workspace/dist_test.py \ --rank $(echo $HOSTNAME | awk -F- {print $NF}) \ --master dist-test-0.dist-test env: - name: MASTER_ADDR value: dist-test-0.dist-test - name: MASTER_PORT value: 23456 - name: NCCL_DEBUG value: INFO - name: NCCL_SOCKET_IFNAME value: eth0 resources: limits: nvidia.com/gpu: 1对应的 Python 脚本dist_test.py负责初始化 NCCL 并执行一次 all_reduceimport argparse import time import torch import torch.distributed as dist parser argparse.ArgumentParser() parser.add_argument(--rank, typeint, requiredTrue) parser.add_argument(--master, typestr, requiredTrue) args parser.parse_args() dist.init_process_group( backendnccl, init_methodtcp://{}:23456.format(args.master), rankargs.rank, world_size8, ) tensor torch.ones(256, dtypetorch.float32, devicecuda) dist.barrier() start time.time() for _ in range(10): dist.all_reduce(tensor) torch.cuda.synchronize() elapsed time.time() - start if dist.get_rank() 0: print(all_reduce avg time: {:.4f}s.format(elapsed / 10)) dist.destroy_process_group()这个示例能帮你验证 DNS 解析、网络连通性、NCCL 协议是否可用。如果这里卡住后面任何大模型训练和推理都跑不起来。4.3 并行策略怎么选张量并行、流水线并行、数据并行8 台 DGX Spark 的并行策略是性能的关键。选错并行方式可能比单机运行还慢。并行方式基本原理跨节点通信量适用场景数据并行每台节点加载相同模型处理不同数据批次定期同步梯度通信量取决于梯度大小和同步频率模型能塞进单机内存时最常用流水线并行按 transformer 层切分节点 0 负责前若干层节点 1 负责后续层通信量为中间激活值相对稳定模型很大必须跨节点切分时优先考虑张量并行把每一层内的矩阵运算切到多个节点通信量非常大每层前向后向都要 all_reduce单机内多 GPU 更合适跨节点需高速网络专家并行MoE 模型把不同专家放到不同节点需要 all-to-all 通信延迟敏感大规模 MoE 模型网络要求极高对于 8 台 DGX Spark合理的做法通常是把数据并行和流水线并行组合使用。先把一个大模型按层切成几段放到多个节点上每个节点再复制一份模型段处理不同数据。张量并行尽量只用在单节点内如果强行跨 8 台10GbE 网络会很难喂满 GPU。注意跨节点张量并行对网络带宽非常敏感。在正式训练前先做一次小规模 all_reduce 测试如果 128MB 张量的同步耗时明显高于预期就不要在 8 台之间开大张量并行。5. 怎么验证集群和模型性能而不是只看到“能启动”5.1 用通信基准先量出网络水位很多集群搭建完成后跑模型能启动但速度远低于预期。这往往不是 GPU 算力不够而是跨节点通信没有达标。在单机上跑 GPU 算例瓶颈是 GPU 算力。在 8 台机器上跑分布式任务瓶颈通常是网络延迟和带宽。你可以用简单的 PyTorch all_reduce 脚本来记录通信耗时。更细的测试可以逐步增加张量体积张量大小单次 all_reduce 耗时说明1 MB0.x ms检查通信延迟128 MBx ms检查带宽1 GBx ms接近大模型梯度同步场景如果 128MB 的 all_reduce 耗时非常高比如超过百毫秒级就要检查网络配置。先看两端网卡速率ethtool eth0 | grep Speed再看是否有多条链路负载不均最后看交换机端口是否有丢包netstat -i5.2 模型推理压测吞吐、首 token 延迟和并发如果是推理场景建议先固定一组可复现的压测参数然后记录结果而不是只跑一次 curl