Skip to content

第九部分 综合实战与面试(第 32~35 章)

走到这里,你已经学完了前八部分:GPU 硬件与算力基础、驱动与环境、虚拟化与共享(MIG/MPS/HAMi)、K8s GPU 调度、RDMA/IB 网络与 NCCL、DCGM 监控、XID 故障诊断、利用率与成本优化。本部分的任务是把这些"零件"组装成"整车":完成两个端到端综合实战(从零搭建生产级训练集群、推理平台资源治理),梳理一线运维最需要的 SOP 与应急预案,最后给出完整的面试通关指南。学完本部分,你应该能独立交付一个小型 GPU 集群,并从容应对 GPU 运维工程师岗位的面试。


第 32 章 综合实战一:从零搭建生产级 GPU 训练集群

本章目标

  • 能把前面各部分的知识串成一条完整的交付流水线:裸机验收 → OS 基线 → K8s → GPU Operator → IB/RDMA → Volcano → 监控 → 验收
  • 掌握每个阶段的关键命令、检查点和"踩坑点"
  • 学会用 checklist 和验收标准表来管理交付质量

32.1 需求与规划

场景需求与总体架构

某 AI 团队采购了 2 台 8 卡 GPU 服务器(A800 或 H800,NVLink 互联),要求:双机 16 卡 PyTorch 分布式训练可跑满;双机间走 InfiniBand(IB) + RDMA;Kubernetes 统一管理并支持排队(Gang Scheduling);训练数据放共享存储双机可挂载;有 GPU 监控告警,掉卡、XID 能及时通知。

                管理/登录网(1/10GbE)
        ┌───────────────┼────────────────────────────┐
┌───────▼───────┐  IB HDR 200G  ┌───────▼───────┐   ┌───▼──────────┐
│  gpu-node-01   │◄════════════►│  gpu-node-02   │   │ storage-node │
│ 8×A800/H800   │              │ 8×A800/H800   │   │ JuiceFS/NFS  │
│ 2×CX-6/7 IB   │              │ 2×CX-6/7 IB   │   │ 数据+ckpt    │
└───────┬───────┘              └───────┬───────┘   └──────────────┘
        └──────────────┬───────────────┘
              K8s control-plane(3 节点虚机或复用现有集群)
              + GPU Operator + Volcano + Prometheus/Grafana/DCGM

组件选型表

层次组件版本/说明选型理由
OSUbuntu 22.04 LTS内核 5.15 HWE社区资料多,NVIDIA 官方支持好
驱动NVIDIA 数据中心驱动与 GPU Operator 配套版本用 Operator 容器化管理,免手工维护
容器运行时containerd1.7+K8s 1.24+ 标准运行时
K8skubeadm 部署1.28+(或 rke2/kubespray)节点少,kubeadm 最直观
CNICalico(管理网)+ Multus最新稳定版Multus 为 Pod 挂第二张 IB/RDMA 网卡
GPU 管理NVIDIA GPU Operator最新稳定版一键管理驱动/toolkit/device-plugin/DCGM
RDMA 支持network-operator / rdma-shared-dpMellanox OFED向 K8s 暴露 RDMA 设备资源
批调度Volcano与 K8s 版本配套Gang Scheduling,防训练任务死锁
监控dcgm-exporter + Prometheus + Grafana随 GPU Operator 部署第六部分已学,直接复用
存储JuiceFS(对象+元数据)或 NFS按预算JuiceFS 适合大数据集,NFS 简单够用

⚠️ 所有"最新稳定版"在生产落地时都要锁定具体版本号并记录,升级走第 34 章的变更 SOP。

32.2 实施步骤全流程

阶段 1:裸机验收与基线

目标:确认硬件与订单一致、无出厂故障。

bash
# 1) 确认 8 张 GPU 与 IB 网卡全部识别
lspci | grep -i nvidia | wc -l        # 应输出 8
lspci | grep -i mellanox
# 2) BMC/IPMI 带外管理:确认能登录、能看到传感器
ipmitool lan print                    # BMC 网络配置
ipmitool sensor list | grep -i -E "temp|fan|power" | head -20
# 3) 固件版本记录(验收基线,后续变更对比用)
ipmitool mc info                      # BMC 固件版本

检查点:8 卡全识别;IB 卡在位;BMC 可远程开关机、挂载虚拟介质;风扇/温度传感器无异常读数。

阶段 2:OS 安装与基线配置

目标:两台节点 OS 环境一致、干净。

bash
# 1) 主机名与 hosts
hostnamectl set-hostname gpu-node-01
echo "10.0.0.11 gpu-node-01" >> /etc/hosts; echo "10.0.0.12 gpu-node-02" >> /etc/hosts
# 2) 关闭 nouveau(开源驱动,会与 NVIDIA 驱动冲突)
printf 'blacklist nouveau\noptions nouveau modeset=0\n' > /etc/modprobe.d/blacklist-nouveau.conf
update-initramfs -u && reboot
# 3) 时间同步(分布式训练对时钟敏感,日志排查也需要)
apt install -y chrony && systemctl enable --now chrony && chronyc sources -v
# 4) 内核参数
printf 'net.ipv4.ip_forward = 1\nvm.max_map_count = 262144\nfs.file-max = 2097152\n' > /etc/sysctl.d/99-gpu.conf
sysctl --system
# 5) 关闭 swap(K8s 要求)
swapoff -a && sed -i '/swap/s/^/#/' /etc/fstab

检查点lsmod | grep nouveau 无输出;chronyc tracking 显示已同步;两节点互 ping 管理网通。

阶段 3:K8s 集群搭建

节点少时 kubeadm 最直观;批量交付可用 kubespray,有合规要求可用 rke2,流程思想一致。kubeadm 简要流程:

bash
# 所有节点:安装 containerd + kubelet/kubeadm/kubectl(版本锁定)
apt install -y containerd
containerd config default > /etc/containerd/config.toml
# 修改 SystemdCgroup = true 后重启:
systemctl restart containerd
# 控制面节点初始化(管理网网段按实际修改),随后安装 CNI(Calico)
kubeadm init --pod-network-cidr=192.168.0.0/16 --kubernetes-version=v1.28.x
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml
# 两台 GPU 节点 join 后打标签
kubectl label node gpu-node-01 node-role.kubernetes.io/gpu-worker=""
kubectl label node gpu-node-02 node-role.kubernetes.io/gpu-worker=""

检查点kubectl get nodes 全部 Ready;跨节点 Pod 互通。

阶段 4:GPU Operator 部署与验证

bash
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia && helm repo update
helm install gpu-operator nvidia/gpu-operator \
  -n gpu-operator --create-namespace --set driver.enabled=true --set toolkit.enabled=true
kubectl -n gpu-operator get pods -w   # 等待 driver/toolkit/device-plugin/dcgm 全部就绪

验证:跑一个 nvidia-smi Pod:

bash
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata: { name: gpu-test }
spec:
  restartPolicy: Never
  containers:
  - name: cuda
    image: nvcr.io/nvidia/cuda:12.4.0-base-ubuntu22.04
    command: ["nvidia-smi", "-L"]
    resources: { limits: { nvidia.com/gpu: 1 } }
EOF
kubectl logs gpu-test
# 期望输出: GPU 0: NVIDIA A800-SXM4-80GB (UUID: GPU-xxxx)

检查点:单卡 Pod 成功;kubectl describe nodenvidia.com/gpu: 8 已上报。

阶段 5:IB/RDMA 网络与 Multus 配置

bash
# 1) 节点侧:确认 IB 链路(装 OFED 或由 network-operator 管理)
ibstat | grep -E "State|Rate"      # 期望: State: Active, Rate: 200
# 2) 验证双机 RDMA 连通
# node-01: ib_write_bw -d mlx5_0
# node-02: ib_write_bw -d mlx5_0 <node-01的IB IP>

K8s 侧:部署 Multus + RDMA device plugin(rdma/rdma_shared_dp 或 network-operator),创建 NetworkAttachmentDefinition:

yaml
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: ib-network
  namespace: gpu-training
spec:
  config: |
    { "cniVersion": "0.3.1", "type": "ipoib", "master": "ib0",
      "ipam": { "type": "whereabouts", "range": "192.168.100.0/24" } }

检查点:测试 Pod 通过 annotation 挂上第二张 IB 网卡,ib_write_bw 带宽接近线速(200G 链路实测 190G+ 即达标)。

阶段 6:Volcano 部署与 8 卡 PyTorch vcjob 验证

bash
helm install volcano volcano-sh/volcano -n volcano-system --create-namespace
kubectl -n volcano-system get pods

单机 8 卡验证任务(vcjob):

yaml
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
  name: pytorch-8gpu-test
spec:
  minAvailable: 1            # 单 task 也走 Gang 语义
  schedulerName: volcano
  tasks:
  - name: worker
    replicas: 1
    template:
      spec:
        containers:
        - name: pytorch
          image: nvcr.io/nvidia/pytorch:24.05-py3
          command: ["python", "-c", "import torch; print(torch.cuda.device_count())"]
          resources:
            limits: { nvidia.com/gpu: 8 }

检查点:输出 8;Pod 状态 Completed。

阶段 7:nccl-tests 双机验证

双机 16 卡 all_reduce 是集群通信质量的"终审"。

bash
# 在双机 vcjob(2 task × 8 卡)中运行,关键环境变量:
#   NCCL_IB_HCA=mlx5_0,mlx5_1   NCCL_SOCKET_IFNAME=eth0   NCCL_DEBUG=INFO
/opt/nccl-tests/build/all_reduce_perf -b 128M -e 4G -f 2 -g 8

达标判断思路:先看 busbw 而不是 algbw(busbw 已换算算法开销);双机 HDR 200G 双口(理论合计 50GB/s)消息 ≥1GB 时 busbw 达理论值 70% 以上可认为网络健康;明显偏低时排查顺序:NCCL_DEBUG=INFO 确认走 NET/IB 而非 NET/Socket → 查 NCCL_IB_HCA 绑定 → 查 IB 链路 Rate → 查 GPUDirect RDMA 是否生效。

检查点:日志显示 via NET/IB/.../GDRDMA;大数据量 busbw 达标;无 NCCL WARN 报错。

阶段 8:DCGM 监控告警上线

dcgm-exporter 随 GPU Operator 已部署,补上 ServiceMonitor 与告警规则:

yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata: { name: dcgm-exporter, namespace: gpu-operator }
spec:
  selector: { matchLabels: { app: nvidia-dcgm-exporter } }
  endpoints: [ { port: gpu-metrics, interval: 15s } ]
yaml
# 核心告警规则示例(PrometheusRule 片段)
groups:
- name: gpu-health
  rules:
  - alert: GPUXIDError
    expr: increase(DCGM_FI_DEV_XID_ERRORS[5m]) > 0
    labels: {severity: critical}
    annotations: {summary: "{{ $labels.Hostname }} GPU {{ $labels.gpu }} 出现 XID 错误"}
  - alert: GPUTemperatureHigh
    expr: DCGM_FI_DEV_GPU_TEMP > 85
    for: 5m
    labels: {severity: warning}
  - alert: GPUUtilizationLow
    expr: avg by (Hostname) (DCGM_FI_DEV_GPU_UTIL) < 20
    for: 2h
    labels: {severity: info}   # 利用率长期过低 → 交给运营周报处理

检查点:Grafana 面板能看到 16 张卡的利用率/显存/温度/功耗;手动触发一条告警验证通知链路(企业微信/钉钉/邮件)。

阶段 9:交付验收 checklist

#验收项命令/方法标准
116 卡全部上报kubectl get nodes -o json | grep nvidia.com/gpu每节点 8
2单卡/8 卡 Pod 调度第 6 节测试成功
3双机 NCCL + 存储挂载nccl-tests / dd 写测busbw、写带宽达标
4监控告警Grafana + 触发测试面板全、告警可达
5故障演练重启一个节点集群自愈、任务可重排
6文档交付拓扑图、账号、版本清单、SOP移交运维方确认

32.3 验收标准表

类别项目验收标准
功能GPU 调度1/8/16 卡任务均可通过 Volcano 调度并跑通
功能存储双节点挂载同一共享目录,读写一致
功能监控16 卡指标齐全,3 条核心告警全部可达
性能NCCL busbw大消息量 ≥ 理论值 70%
性能存储带宽顺序读写达到设计值(如 JuiceFS ≥ 1GB/s,按实际选型)
性能IB 单机带宽ib_write_bw ≥ 线速 90%
稳定性burn-in双机 16 卡 all_reduce + 满载训练任务连续跑 48 小时,无 XID、无掉卡、无任务失败
稳定性故障注入拔一根 IB 线缆后告警触发、任务报错可恢复;恢复后复测达标

本章小结

  • 生产交付 = 标准化流水线:验收 → 基线 → K8s → GPU → 网络 → 调度 → 压测 → 监控 → 验收,每步都有检查点。
  • 性能验收看 nccl-tests busbw48h burn-in,不看"能跑起来";交付同时必须交付文档和 SOP。

动手实验

  1. 在实验环境(可用 2 台普通节点模拟)完整走一遍 kubeadm + GPU Operator + Volcano 流程,记录每一步耗时与报错。
  2. 写一份你自己的"裸机验收脚本",自动输出 GPU 数量、IB 状态、BMC 传感器摘要。
  3. 思考题:为什么 burn-in 要用真实训练任务而不只跑 nccl-tests?(提示:nccl-tests 只压通信,压不到显存、功耗墙和存储。)

第 33 章 综合实战二:推理平台资源治理

本章目标

  • 会为一个多团队共享的推理资源池设计"隔离 + 配额 + 可观测"的治理方案
  • 掌握 MIG 节点池与 HAMi 节点池混合架构的落地要点
  • 建立资源运营机制:周报、闲置回收、扩容触发

33.1 场景

公司有 4 台 8 卡 A800 推理服务器(共 32 卡),三个团队共用:

  • A 团队:核心在线推理(客服机器人),要求延迟稳定、互不干扰
  • B 团队:一般在线服务,可以接受一定波动,但要求显存不超用
  • C 团队:算法同学调试/压测,用量不稳定,经常"忘了释放"

要求:显存隔离、资源配额、用量可观测、成本可核算。

33.2 方案设计

总体思路:按 SLA 分区治理

不同团队对隔离的要求不同,不要"一刀切":

分区节点技术服务团队隔离强度
mig-pool2 台(16 卡)MIG(每卡切 1×3g.40gb + 4×1g.10gb 等固定布局)A 团队硬件级,最强
hami-pool2 台(16 卡)HAMi 显存/算力切分B、C 团队显存硬限,灵活

设计逻辑:A 团队要延迟稳定 → 用 MIG 硬件隔离,每个在线服务独占一个实例,邻实例故障/打满都影响不到它;B/C 团队用量零碎且多变 → 用 HAMi 按显存任意切分,利用率优先;MIG 布局变更要 drain 节点,按 A 团队稳定画像一次配好,日常不动。

Namespace 与配额

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-b-quota
  namespace: team-b
spec:
  hard:                          # cpu/memory 常规配额从略
    nvidia.com/vgpu-memory: "655360"     # HAMi:总显存额度 640Gi(Mi 单位)
    nvidia.com/vgpu-cores: "800"         # HAMi:总算力额度 8 卡当量

MIG 池的配额更简单:A 团队 MIG 实例数物理固定,用 requests.nvidia.com/mig-1g.10gb: 28 之类整型资源做硬上限即可。

可观测:用量面板

Grafana 建三个视图:① 池级视图:mig-pool / hami-pool 的已分配 vs 总量(还剩多少);② 团队视图:按 namespace 聚合显存分配量与实际使用量;③ 浪费视图:已分配但 DCGM_FI_DEV_GPU_UTIL < 5% 持续 24h 的 Pod 列表——闲置回收的输入。

33.3 实施关键 YAML 与验证

第 1 步:节点池打标签与污点(防止任务乱跑)

bash
kubectl label node gpu-inf-01 gpu-pool=mig
kubectl label node gpu-inf-03 gpu-pool=hami
kubectl taint node gpu-inf-01 gpu-pool=mig:NoSchedule

第 2 步:MIG 池配置(通过 GPU Operator 的 mig-manager)

yaml
# mig-parted 配置片段:给 mig-pool 节点应用统一布局
apiVersion: v1
kind: ConfigMap
metadata:
  name: mig-parted-config
  namespace: gpu-operator
data:
  config.yaml: |
    version: v1
    mig-configs:
      all-balanced:
        - devices: all
          mig-enabled: true
          mig-devices: { "1g.10gb": 4, "3g.40gb": 1 }
bash
kubectl label node gpu-inf-01 nvidia.com/mig.config=all-balanced --overwrite
# 验证:实例出现
kubectl get node gpu-inf-01 -o json | grep mig | head

第 3 步:HAMi 池部署与验证

bash
helm install hami hami-charts/hami -n kube-system --set scheduler.kubeScheduler.imageTag=v1.28.x

# 验证 Pod:申请 8Gi 显存
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata: { name: hami-verify, namespace: team-b }
spec:
  containers:
  - name: app
    image: nvcr.io/nvidia/cuda:12.4.0-base-ubuntu22.04
    command: ["sleep", "3600"]
    resources:
      limits: { nvidia.com/gpu: 1, nvidia.com/gpumem: 8192 }   # 8Gi 显存上限
EOF

# 进容器验证显存被限制在 8Gi 左右
kubectl exec -n team-b hami-verify -- nvidia-smi --query-gpu=memory.total --format=csv

第 4 步:验证隔离效果

  • 在 team-b 的 Pod 里写"超显存"测试程序,确认 OOM 被限制在自己进程内,不影响同卡其他 Pod;
  • 在 mig-pool 上对一个实例跑满压测,观察 A 团队邻实例的 P99 延迟无变化。

33.4 运营机制

技术方案解决"隔离",运营机制解决"浪费"

  1. 周报:每周一自动出报表——各团队显存配额使用率、利用率 Top/Bottom 10 Pod、闲置清单,用 PromQL 取数生成。
  2. 闲置回收:已分配且利用率 < 5% 持续 72h 的 Pod,先提醒 owner,48h 无响应则缩容;C 团队配额周期默认两周,到期不续自动回收。
  3. 扩容触发条件(写进 SOP,避免拍脑袋):池级显存分配率 > 80% 持续一周;或团队 Pending 排队 P95 > 30 分钟;或新模型上线评估需要增量资源。
  4. 成本核算:按"显存·小时"记账,MIG 实例按规格定价,HAMi 按申请量定价,月底分摊到团队。

本章小结

  • 推理资源治理 = 按 SLA 分区(MIG 保稳定、HAMi 提利用率)+ Namespace 配额 + 可观测 + 运营机制。
  • 技术只占一半,周报、闲置回收、扩容触发条件这些"机制"才是资源池长期健康的保障。

动手实验

  1. 在实验集群给一个 namespace 配置 ResourceQuota,验证超配额 Pod 会被拒绝。
  2. 写一条 PromQL,找出"分配显存 > 0 但利用率 24h 均 < 5%"的 Pod。
  3. 思考题:为什么 A 团队不也用 HAMi?如果预算只够买一种方案,你会选哪个,为什么?

第 34 章 运维 SOP 与应急预案

本章目标

  • 建立日/周/月三级巡检机制,每条巡检项都有具体命令
  • 掌握驱动、K8s、固件三类高风险变更的标准流程与回滚预案
  • 对五类典型事故能按预案快速处置,会写 5Why 复盘

34.1 日常巡检 SOP

每日巡检(10 分钟,值班同学执行)

bash
# 1) 集群与节点健康
kubectl get nodes                          # 全部 Ready
kubectl get pods -A | grep -v -E "Running|Completed"
# 2) GPU 健康总览(每台 GPU 节点执行或看 Grafana)
nvidia-smi --query-gpu=index,name,temperature.gpu,utilization.gpu,memory.used,power.draw --format=csv
nvidia-smi -q | grep -i -E "pending|xid"   # ECC pending 与异常
# 3) 告警状态:打开 Alertmanager/告警群,确认无未处理 critical
# 4) 存储水位
df -h | grep -E "data|juicefs|nfs"

每周巡检(30 分钟)

bash
# 1) XID 统计(本周趋势,看是否有劣化中的节点)
grep -i "xid" /var/log/syslog* 2>/dev/null | awk '{print $1}' | sort | uniq -c
# 2) ECC 累计错误(对比上周基线,突增的卡列入观察名单)
nvidia-smi --query-gpu=index,ecc.errors.uncorrected.aggregate.total --format=csv
# 3) IB 端口错误计数(误码趋势)
for f in /sys/class/infiniband/*/ports/*/counters/*_errors; do echo "$f: $(cat $f)"; done | grep -v ": 0"
# 4) 资源利用率周报生成(第 33 章的周报脚本)
# 5) 证书有效期(kubeadm 集群证书一年到期,最容易被遗忘)
kubeadm certs check-expiration

每月巡检(2 小时)

  1. 固件/驱动版本盘点:输出全集群版本矩阵,确认与基线一致,无"漂移"节点;
  2. 备份有效性演练:etcd 快照恢复演练一次(在测试环境恢复验证);
  3. 容量复盘:按第 33 章扩容触发条件评估下月是否需要扩容;
  4. 预案演练:从 34.3 抽一个场景做桌面/真实演练(如主动 cordon 一台节点观察任务迁移);
  5. 文档更新:SOP、拓扑图、联系人表是否与现状一致。

34.2 变更 SOP

所有变更遵循统一框架:评估 → 备份/快照 → 灰度 → 观察 → 全量 → 记录。GPU 集群的三类高风险变更:

驱动升级

bash
# 前置:确认新驱动与 CUDA 版本、PyTorch 镜像的兼容性矩阵(docs.nvidia.com)
# 1) 灰度节点选择:选负载最低的一台
kubectl cordon gpu-node-01
kubectl drain gpu-node-01 --ignore-daemonsets --delete-emptydir-data
# 2) 升级(GPU Operator 场景:改 ClusterPolicy 的 driver.version,Operator 逐节点滚动)
#    手工场景:停 driver 容器/模块 → 安装新驱动 → nvidia-smi 验证
# 3) 验证通过后灰度跑业务 24~48h,再全量滚动;最后 uncordon
kubectl uncordon gpu-node-01

回滚预案:保留旧驱动安装包与 Operator 版本 pin;异常时将 driver.version 改回旧值重放,或在该节点重装旧驱动。回滚验证标准nvidia-smi 正常 + 跑通一个训练任务 + 无新 XID。

K8s 升级

  • 版本规则:逐个小版本升(1.28→1.29,不跨版本);先升控制面再升 worker;worker 流程同驱动升级(drain → 升级 → 验证 → uncordon),每次一台;
  • 特别注意:升级前确认 GPU Operator、Volcano、HAMi、Multus 与新版本的兼容性,这是 GPU 集群比通用集群多的一步。

固件升级(GPU VBIOS / BMC / IB 网卡)

风险最高、收益最低频,非必要不升级,只在修复已知 bug 或安全通告时做;必须有 BMC 带外管理兜底(变砖可远程救),安排停机窗口,一次一台,升级后跑 2h 满载压测再放回。

通用回滚检查表

检查项通过标准
业务任务灰度节点跑代表性任务 24h 无失败
硬件健康无新增 XID、ECC 计数不增长
性能nccl-tests busbw 与升级前基线偏差 < 5%
监控指标无断点、告警规则仍生效

34.3 应急预案

总则:先保业务(隔离故障、迁移任务),再修硬件;每个动作留痕(时间、命令、现象)。

预案一:单卡故障(XID 掉卡)

发现(XID 告警 / nvidia-smi 显示卡丢失)
  → 1. 定位:确认节点与卡号,查 XID 码对照表判断类型
  → 2. 止血:kubectl cordon 该节点;该卡上的任务 eviction/重排到健康节点
  → 3. 尝试恢复:nvidia-smi --gpu-reset(需卡空闲)或重启节点
  → 4. 验证:dcgmi diag -r 2 通过 → uncordon;反复掉卡(一周 ≥2 次)→ 走 RMA 换卡,节点保持 cordon 直到更换

预案二:整机宕机

发现(节点 NotReady / BMC 失联告警)
  → 1. BMC 带外确认:电源状态、SEL 日志(ipmitool sel list)
  → 2. 业务侧:确认任务已被 K8s 重排(训练任务靠 checkpoint 恢复,检查最近 ckpt 时间)
  → 3. 硬件侧:能远程重启则重启观察;反复宕机 → 联系 IDC/厂商,重点怀疑电源/主板;恢复后全量诊断(dcgmi diag -r 3)+ 2h 压测 → 重新上线

预案三:IB 网络分区

发现(训练任务 NCCL timeout 告警 / ibstat State 非 Active)
  → 1. 范围判定:单机还是全网?单机 → 查本机线缆/网卡;全网 → 查交换机/子网管理器(opensm)
  → 2. 止血:cord off 受影响节点,任务迁移到网络健康分区
  → 3. 修复:更换线缆/模块、重启 opensm、检查端口误码计数
  → 4. 验证:ib_write_bw + 双机 nccl-tests 达标后恢复

预案四:存储故障

发现(训练任务 IO 报错 / df 不可达 / JuiceFS 元数据告警)
  → 1. 影响面:哪些节点/任务挂载受影响;checkpoint 是否可写(最关键!)
  → 2. 止血:暂停新任务调度(临时 cordon 或调低队列配额),防止故障放大
  → 3. 处置:NFS → 服务端排查;JuiceFS → 查元数据引擎与对象存储连通性
  → 4. 恢复验证:读写压测 + 确认任务可从最近 checkpoint 续跑;若丢数据 → 启用备份恢复,评估丢失的 ckpt 时间窗并通知业务方

预案五:机房高温告警

发现(BMC 温度告警 / DCGM GPU_TEMP > 阈值)
  → 1. 确认范围:单机(风扇故障)还是整排(空调故障)
  → 2. 整排高温 → 按优先级 graceful 停掉低优先级任务保核心在线;逼近阈值 → 有序关机(先 drain 再 shutdown)
  → 3. 单机高温 → 检查风扇转速(ipmitool sensor | grep -i fan),备件更换
  → 4. 恢复后逐批上电,观察温度回落再放量

34.4 值班与复盘

值班/oncall 制度建议

  • 分级响应:critical(掉卡、宕机、存储故障)15 分钟内响应;warning(高温趋势、误码增长)工作时间处理;
  • 值班轮换:至少 2 人互备,值班期间不出差、不醉酒,交接必须过一遍未闭环告警;
  • 升级路径:值班 → 二线(资深)→ 厂商/IDC,每级超时 30 分钟自动升级;
  • 告警纪律:所有 critical 告警必须有 owner 和处置记录,禁止"静默处理"。

故障复盘模板(5Why)

markdown
# 故障复盘报告

- 故障时间:2026-07-20 14:03 ~ 15:27(84 分钟)
- 影响范围:team-a 训练任务 xxx 中断,损失约 3 小时训练进度(有 checkpoint)
- 直接原因:gpu-node-02 第 5 卡 XID 79(GPU 掉出总线)
- 时间线:14:03 告警 → 14:10 响应 → 14:25 cordon 迁移 → 15:00 重启恢复 → 15:27 诊断上线

## 5Why 分析
1. 为什么任务中断?→ 第 5 卡掉卡,NCCL 通信失败
2. 为什么掉卡?→ XID 79,硬件层面 GPU 与总线断开
3. 为什么硬件断开?→ 该卡近两周 ECC 计数持续增长,属于劣化中的卡
4. 为什么劣化卡还在服役?→ 周巡检发现了 ECC 增长但未触发处置动作
5. 为什么巡检项没有动作?→ SOP 只写了"记录",没写"达到什么阈值要做什么"

## 改进措施(每条有 owner 和 deadline)
1. SOP 补充:ECC 周增长 > 10 的卡列入观察名单,> 50 主动下线换卡(owner: 张三,7/31)
2. 告警增加:ECC 增长速率告警(owner: 李四,8/7)
3. 该卡走 RMA 流程(owner: 王五,8/15)

复盘的核心原则:对事不对人,每个"为什么"最终都要落到流程/系统/机制的改进上,而不是"某某操作失误"。

本章小结

  • 巡检的价值在于趋势:单次指标正常不代表健康,ECC/误码/温度的趋势才预警故障。
  • 变更的铁律:兼容性先行、灰度先行、回滚预案先行;预案要演练过才算数,复盘要落到改进项才算闭环。

动手实验

  1. 用 bash 写一个每日巡检脚本,输出"节点状态 + GPU 温度/显存 + 告警数"三段式报告。
  2. 在测试集群演练一次节点 drain → 升级 → uncordon 的完整流程并记录耗时。
  3. 用 5Why 模板复盘一个你真实遇到过的故障(不限 GPU)。

第 35 章 面试通关指南

本章目标

  • 了解 GPU 运维工程师面试的考察维度,有针对性地准备
  • 掌握 25 道高频题的答题要点和 5 道场景设计题的答题框架
  • 会把本教材的实战经历包装成简历亮点,规划职业发展

35.1 岗位能力模型

面试官对 GPU 运维工程师的考察,通常围绕 5 个维度展开:

维度考察内容对应教材部分
硬件与驱动GPU 架构、显存、NVLink、驱动/CUDA 兼容性、XID第一、二、七部分
K8s 调度Device Plugin、GPU Operator、Volcano、MIG/HAMi第三、四部分
网络RDMA/IB/RoCE、NCCL、GPUDirect、通信排障第五部分
监控DCGM 指标、Prometheus/Grafana、告警设计第六部分
故障处理掉卡、ECC、过热、训练变慢的排查思路第七、八部分 + 本部分

面试心法:面试官真正想听的不是命令背诵,而是"分层定位的思维"——任何问题都能从硬件 → 驱动 → 容器 → 调度 → 网络 → 应用逐层排除。

35.2 高频面试题 25 道

以下按 5 个维度分组,每题先给结论、再给原理、最后给操作细节。

硬件与架构(Q1~Q5)

  • Q1:GPU 和 CPU 的核心区别是什么?为什么深度学习用 GPU? CPU 是少量强大核心,擅长复杂控制和串行逻辑;GPU 是数千个简单核心,擅长大规模并行计算。深度学习的矩阵乘法天然可并行,GPU 的并行吞吐 + 高显存带宽(HBM 可达 TB/s 级)恰好匹配,训练速度可快数十倍。
  • Q2:SXM 和 PCIe 形态的 GPU 有什么区别? SXM 是英伟达专用插座形态:功耗上限更高(如 H100 SXM 700W vs PCIe 350W)、支持完整 NVLink 互联、走 HGX 整机设计;PCIe 形态兼容通用服务器但卡间互联弱。8 卡训练服务器几乎都是 SXM。
  • Q3:NVLink 和 PCIe 带宽差多少?对训练有什么影响? NVLink(如 H100 第四代)单向约 900GB/s 量级,PCIe Gen5 x16 约 128GB/s,差近一个数量级。单机多卡 AllReduce 走 NVLink 时通信几乎不构成瓶颈;若卡间只能走 PCIe,大模型数据并行的梯度同步会明显拖慢。
  • Q4:什么是 ECC 错误?单比特和双比特错误有什么区别? ECC 是显存的纠错机制。单比特错误(SBE)可自动纠正,偶发无害;双比特错误(DBE)不可纠正,会导致 XID 错误、任务失败。运维看两个指标:当前值是否突增、aggregate 累计是否持续增长(持续增长 = 显存颗粒劣化,列入换卡名单)。
  • Q5:A800/H800 和 A100/H100 有什么区别? A800/H800 是面向特定市场的版本,核心算力与 A100/H100 基本一致,主要差异是 NVLink 互联带宽被限制(影响多卡扩展效率)。做方案设计时要据此调整:更重视拓扑感知调度、控制单机内通信占比。

驱动与 CUDA(Q6~Q9)

  • Q6:驱动版本、CUDA Toolkit、PyTorch 三者的兼容性关系? 驱动决定支持的 CUDA 运行时上限(向后兼容:新驱动可跑旧 CUDA);CUDA Toolkit 是编译/运行时库;PyTorch 各版本编译时绑定特定 CUDA 版本。原则:驱动 ≥ 应用所需 CUDA 对应的最小驱动版本,容器内自带 CUDA 运行时,宿主机只需装驱动。
  • Q7:容器里跑 GPU 需要什么?nvidia-container-toolkit 做了什么? 宿主机装驱动 + nvidia-container-toolkit。容器启动时 toolkit 通过 hook 把驱动库文件、设备节点(/dev/nvidia*)挂载进容器,并根据 NVIDIA_VISIBLE_DEVICES 控制可见的 GPU。容器内的 CUDA Toolkit 由镜像自带,与宿主机解耦。
  • Q8:nvidia-smi 显示的进程显存和 PyTorch 报的显存对不上,为什么? PyTorch 有显存缓存分配器:释放的张量不立即还给驱动,留在缓存里复用。nvidia-smi 看到的是驱动视角的占用。可用 torch.cuda.empty_cache() 或设置 PYTORCH_CUDA_ALLOC_CONF 调整行为。这不是泄漏,判断泄漏要看显存是否持续增长不回落
  • Q9:升级驱动有哪些注意事项? 确认与业务 CUDA/框架版本的兼容性矩阵;灰度一台节点(cordon+drain)先升级观察 24~48h;GPU Operator 场景改 driver.version 由 Operator 滚动;保留旧版本回滚路径;升级后跑 dcgmi diag 和代表性任务验证。

虚拟化与共享(Q10~Q13)

  • Q10:MIG 和 MPS 的区别?各自适用什么场景? MIG 是硬件级切分:显存、SM、L2 缓存物理隔离,故障域独立,规格固定(如 1g.10gb),变更需 drain,适合多租户在线推理;MPS 是 CUDA 运行时层让多进程共享 GPU 上下文,隔离弱但灵活、零规格限制,适合同节点多个小任务提吞吐。一句话:要隔离用 MIG,要利用率用 MPS
  • Q11:HAMi 的原理是什么?有什么局限? HAMi 通过 CUDA API 拦截(劫持显存分配等调用)实现显存硬限制和算力软限制,让 K8s 能按 MB 级粒度分配 GPU。局限:依赖 API 拦截(非官方机制,极端 CUDA 特性可能绕过);算力限制是软的;隔离强度不如 MIG。适合推理资源池,不适合强隔离合规场景。
  • Q12:Device Plugin 的原理是什么? K8s 扩展机制:device plugin 以 DaemonSet 跑在节点上,通过 gRPC 向 kubelet 注册自定义资源(如 nvidia.com/gpu),上报可分配设备列表;调度器按整型资源计数调度,kubelet 在分配阶段调用 plugin 的 Allocate,plugin 返回设备节点/环境变量/挂载信息,由容器运行时注入容器。这也解释了为什么原生 GPU 只能按整卡分配。
  • Q13:一卡多 Pod 有哪些实现方式? 时间片共享(device plugin 虚报副本数,无隔离)、MPS(共享上下文)、MIG(硬件切分)、HAMi 类软件切分(显存硬限)。选型看隔离需求与卡型,见 Q10/Q11。

调度与网络(Q14~Q19)

  • Q14:什么是 Gang Scheduling?为什么训练任务必须要它? Gang Scheduling(成组调度):一个分布式任务的 N 个 Pod 要么全部调度成功、要么全部不调度。没有它,K8s 默认逐个调度,16 卡任务可能先起 10 个 Pod 占着卡等另外 6 个,资源不够就死锁——占着的等不到,等着的起不来。Volcano/Scheduler-plugins 都实现了该语义。
  • Q15:RDMA 是什么?相比 TCP 有什么优势? RDMA(远程直接内存访问):网卡直接读写远端内存,绕过内核协议栈和 CPU。优势:低延迟(微秒级)、高带宽、零拷贝、CPU 占用几乎为零。AI 训练梯度同步是带宽敏感型通信,RDMA(IB 或 RoCE)是多机训练的标配。
  • Q16:NCCL 的 Ring 和 Tree 算法有什么区别? Ring-AllReduce:所有卡连成环,通信量与卡数无关,带宽利用率最优,适合大消息;Tree:延迟随卡数对数增长,适合小消息。NCCL 按消息大小和拓扑自动选择。运维要知道:Ring 依赖拓扑探测正确(NCCL_TOPO_FILE),跨机性能取决于机间链路。
  • Q17:NCCL 通信慢/超时,你的排查顺序是什么? 1) NCCL_DEBUG=INFO 看走的什么通道(NET/IB?NET/Socket?SHM?);2) 若走了 Socket 说明 IB 没识别,查 NCCL_IB_HCANCCL_SOCKET_IFNAME、容器内能否看到 IB 设备;3) ib_write_bw 测裸带宽排除物理层;4) nccl-tests 对比基线定位单链路问题;5) 查 GPUDirect RDMA 是否生效(GDRDMA 字样)。口诀:先看通道,再测带宽,后查拓扑
  • Q18:RoCE 和 InfiniBand 怎么选? IB:原生 RDMA、无损、有子网管理器,性能最稳,成本高、生态封闭(Mellanox 系);RoCEv2:跑在以太网上,成本低、可与现有 IP 网络融合,但需要 PFC/ECN 等无损配置,调不好会丢包性能骤降。预算充足、追求省心选 IB;大规模且网络团队强可选 RoCE。
  • Q19:GPUDirect RDMA 是什么?怎么确认它生效了? GDR 允许 IB 网卡直接读写 GPU 显存,跳过 CPU 和主机内存拷贝,大幅降低跨机 GPU 通信延迟。确认方法:NCCL 日志出现 GDRDMA;节点上 lsmod | grep nvidia_peermem(或新版 nvidia-peermem 模块)已加载;nccl-tests 大消息 busbw 达标。

监控与故障处理(Q20~Q25)

  • Q20:GPU 监控你关注哪些核心指标? 利用率(SM util)、显存占用、温度、功耗、ECC 计数、XID 错误、PCIe/NVLink 吞吐、显存带宽利用率。告警上:XID 和掉卡是 critical,温度是 warning,长期低利用率是运营信息(info)。
  • Q21:常见的 XID 错误码有哪些?怎么处理? XID 13/31(应用非法内存访问,多为代码问题)、XID 48(双比特 ECC)、XID 63/64(ECC 页退役)、XID 79(GPU 掉出总线,最严重,硬件级)、XID 74(NVLink 错误)、XID 119/120(GSP 相关)。处理思路:查码定性 → cordon 隔离 → reset/重启尝试恢复 → 诊断(dcgmi diag)→ 反复出现走 RMA。
  • Q22:任务跑得好好的突然 hang 住,怎么排查? 1) 看日志停在哪个 step;2) 如果是多机,大概率某节点通信 hang:逐节点 nvidia-smi 看是否有卡利用率 0%、查 XID;3) py-spy dump 或 gdb 看 Python 栈停在哪个 collective;4) NCCL 日志找 timeout 的 rank;5) 检查 IB 链路状态。多数 hang 的根因是掉卡或网络分区。
  • Q23:GPU 利用率低(如 30%),可能的原因和优化手段? 数据侧:DataLoader 瓶颈(加 workers、开 pin_memory、数据预处理下沉);训练侧:batch size 太小、频繁同步、未开混合精度/梯度累积;框架侧:未用编译优化(torch.compile)、算子低效;存储侧:远程存储读带宽不足。排查工具:nsys/DCGM 的 SM 与显存带宽指标区分"算不动"还是"等数据"。
  • Q24:怎么做 GPU 集群的成本优化? 利用率优化(混部:在线推理 + 离线批任务错峰;超卖:HAMi 显存切分);调度优化(Gang + 队列优先级 + 抢占,减少碎片和死等);运营优化(闲置回收、配额、按显存·小时计费分摊);采购优化(按负载画像选卡型,避免"大马拉小车")。
  • Q25:你设计 GPU 集群告警体系的原则是什么? 分层:硬件层(XID、温度、ECC、掉卡)→ 平台层(节点 NotReady、调度 Pending 积压)→ 业务层(任务失败率、训练 loss 异常由业务方报)。分级:critical 立即电话/IM,warning 工单。纪律:每条告警必须有处置 SOP 和 owner,告警降噪(聚合、抑制、静默窗口),避免告警风暴淹没真故障。

35.3 场景设计题 5 道

场景 1:设计一个 1000 卡的大模型训练集群

  1. 规模换算:1000 卡 = 125 台 8 卡机;先问清模型规模与并行策略(DP/TP/PP 配比决定通信模式)。
  2. 网络设计:IB NDR 400G,导轨优化(rail-optimized)拓扑,每机 8 口对应 8 卡;无阻塞 Fat-Tree;GPUDirect RDMA 必须开。
  3. 存储设计:分层——高性能并行文件系统(Lustre/CPFS)承载训练数据,对象存储做冷数据与 checkpoint 归档;ckpt 写带宽按"模型大小 × 频率"反推。
  4. 调度平台:K8s + Volcano,拓扑感知调度(同任务落在同 leaf 交换机下),队列配额 + 优先级抢占。
  5. 可观测与容错:DCGM 全覆盖;checkpoint 间隔与故障恢复演练;千卡集群每天都有硬件事件,快速检测-隔离-恢复-续训的自动化闭环是核心卖点。
  6. 收尾:供电与散热(液冷趋势)、分期交付与 burn-in 验收。

场景 2:用户报障"训练变慢了",你怎么排查?

  1. 量化:慢了多少?step time 从基线 X ms 涨到多少?何时开始(关联变更记录)?所有任务还是单个任务?
  2. 全局还是局部:全集群变慢 → 查共享依赖(存储、网络交换机、镜像仓库);单任务/单节点 → 下钻。
  3. 硬件层:温度/功耗墙(降频!nvidia-smi -q -d PERFORMANCE 看 throttle 原因)、XID、ECC、降速的链路(IB Rate 掉了)。
  4. 通信层:nccl-tests 对比基线;NCCL 日志是否退化到 Socket。
  5. 数据/存储层:IO 等待(iostat、DataLoader worker 利用率)、存储带宽是否被打满。
  6. 软件变更层:镜像/驱动/框架版本是否在时间点上发生过升级。
  7. 方法论收口:"对比基线 + 逐层排除 + 一次只改一个变量"。

场景 3:推理服务高峰期 GPU 打满、延迟飙升,但卡不够用,怎么办?

短期(无损扩容:HAMi/MPS 提单卡吞吐、动态批处理、量化降显存、跨池借调)→ 中期(容量画像:按峰谷规律定时伸缩和混部填谷;热点模型多副本)→ 长期(用 QPS/延迟/成本数据反推采购,建容量预警线)。强调:先榨干利用率,再谈加卡

场景 4:如何设计 GPU 集群的故障自愈体系?

检测(DCGM XID 告警 + node-problem-detector)→ 决策(故障分级:可 reset / 需重启 / 需换卡)→ 执行(自动 cordon + drain → 处置动作 → dcgmi diag 验证 → 自动 uncordon)→ 业务衔接(通知任务 controller 从 checkpoint 重启)→ 防误伤(同一时刻自愈节点数限流;策略先在测试池灰度)。人机边界:可自动化的做闭环,换卡类物理动作留人工工单。

场景 5:领导让你把 GPU 利用率从 35% 提升到 60%,你的方案?

  1. 先度量:分团队/分任务类型出利用率画像,找到洼地(通常是不释放的调试任务和小 batch 训练);2) 技术手段:混部(离线填在线的谷)、HAMi 超卖、Volcano 队列抢占、推广 AMP/大 batch/编译优化;3) 运营手段:闲置回收、配额与计费倒逼、利用率纳入团队考核;4) 风险控制:在线 SLA 保护(分区隔离)、超卖上限灰度放量;5) 目标拆解:35% → 60% 按"回收闲置贡献 X%、混部贡献 Y%、训练优化贡献 Z%"做计划,月度复盘。

35.4 简历与项目包装建议

把本教材的实战写成简历项目,关键是量化 + 技术栈 + 你的角色

GPU 算力平台建设项目(个人实战/实验室项目)

  • 从裸机交付 2×8 卡 A800 训练集群:完成硬件验收、OS 基线、kubeadm + GPU Operator + Volcano + IB/RDMA 全链路部署,nccl-tests busbw 达理论值 7x%
  • 基于 MIG + HAMi 混合池设计多团队推理资源治理方案,显存级隔离与配额管理,配套 Grafana 用量面板与闲置回收机制
  • 搭建 DCGM + Prometheus 监控告警体系,编写 XID 处置、节点宕机等 5 个应急预案与巡检 SOP

包装建议:

  1. 写真实做过的事:实验环境 2 台机器也比"只看过文档"强,面试官追问细节时你能接住;没做过的(如千卡集群)说"设计过方案 + 小规模验证过",不要说"运维过";
  2. 量化一切:卡数、带宽、利用率提升、MTTR,没有数字的成就没有说服力;
  3. 突出排障案例:准备 2~3 个亲手解决过的故障,用"现象 → 定位 → 根因 → 改进"讲故事。

35.5 职业发展路径

算力平台工程师(1~3 年)
  ├─ 纵深:GPU 运维专家 → 平台架构师
  │    负责大规模集群的架构设计、技术选型、容量规划
  ├─ 横向:SRE / 基础架构工程师
  │    把 GPU 集群经验泛化到整个基础设施的稳定性工程
  └─ 跨界:AI Infra / ML Platform 工程师
       深入训练/推理框架层,做平台与算法的桥梁(薪资天花板更高)

成长建议:

  • 第 1 年:把"执行"做扎实——交付、巡检、排障,建立自己的故障案例库;
  • 第 2~3 年:从"会用"到"懂原理"——读 NCCL、device plugin 源码,能把性能问题定位到代码层;
  • 第 3 年+:培养架构视野——成本核算、容量规划、选型权衡,关注行业演进(NVL72、液冷、国产算力卡);保持输出(博客、内训、开源社区),是职业跃迁的放大器。

本章小结

  • 面试考察 5 个维度,核心心法是分层定位思维,而不是背命令;25 道高频题覆盖全书主干,答题先结论、再原理、后操作。
  • 场景题用框架答题:先量化问题、再分层展开、最后方法论收口;简历靠真实实战 + 量化数字;职业发展三条路:架构、SRE、AI Infra。

动手实验(最终任务)

  1. 对着镜子(或找朋友)把 Q17、Q22、场景 2 各讲一遍,录音回放,检查是否"结论先行、层次分明"。
  2. 把第 32、33 章的实战整理成一页项目总结(架构图 + 关键数字 + 遇到的坑),这就是你的面试作品集。
  3. 用 35.4 的模板更新你的简历,投递至少 5 个岗位,用真实面试反馈迭代。

🎓 结语:从第一部分认识 GPU 是什么,到现在能独立交付集群、治理资源、处置故障、从容面试——你已经完成了从零基础到合格 GPU 集群运维工程师的蜕变。技术会持续演进(新的卡、新的框架、新的拓扑),但"分层定位的思维、标准化的流程、对稳定性的敬畏"会让你走得更远。祝前程似锦,算力无忧!