主题
CPU + GPU:为什么 AI 平台工程本质上是一个异构基础设施问题
“AI 工作负载从来不是‘GPU-only’的端到端流程——它是 CPU、GPU、内存带宽、存储 I/O、网络延迟与调度策略在毫秒级协同下的交响。忽视 CPU 层的瓶颈,等于用 100 张 H100 去跑一个被
kubectl top node显示为 98% CPU wait 的 vLLM Pod。”
—— 来自 CNCF Blog 2026 年深度观察,亦是我们过去 18 个月在 3 家头部大模型平台落地验证后的第一性原理结论。
背景动机:当“GPU is all you need”叙事开始崩塌
2023–2024 年,AI 基础设施圈弥漫着一种乐观的简化主义:“只要堆够 GPU,一切皆可训、皆可推”。Kubernetes 集群被快速打标为 nvidia.com/gpu: 8,Helm Chart 默认启用 resources.limits.nvidia.com/gpu: 4,SRE 团队甚至将 GPU 节点池命名为 ai-gpu-prod——仿佛 CPU、内存、本地 NVMe、RDMA 网络只是 GPU 的静态陪衬。
但现实很快给出了反例:
- 某金融风控大模型推理服务(vLLM + LoRA)在 A100-80G 上 P99 延迟突增至 2.3s,
nvidia-smi显示 GPU 利用率仅 35%,而kubectl top pod显示其 sidecardata-loader容器 CPU 使用率达 12/12 cores; - 某多模态训练 Pipeline 在 PyTorch DDP 启动阶段卡死 47 秒,
strace -p $(pgrep -f "torch.distributed")显示大量futex等待,最终定位为 CPU 核心间 NUMA 不均衡 +/dev/shm容量不足(默认 64MB,实际需 2GB); - 某 RAG 服务在 QPS > 800 后出现
Connection reset by peer,ss -s显示tcp_tw_count爆表,根源却是 Istio sidecar(Envoy)因 CPU 配额不足无法及时 recycle TIME_WAIT socket。
这些都不是 GPU 显存或算力不足的问题——它们是CPU 子系统、内核参数、cgroup v2 限制、NUMA 拓扑感知调度、共享内存配置与网络栈协同失效的综合症候群。AI 平台工程的真正挑战,早已从“如何让 GPU 跑起来”,跃迁至“如何让 CPU/GPU/IO/NIC 在 Kubernetes 的抽象层下不失真地协同”。
核心技术:构建真正异构感知的 K8s AI 工作负载
1. CPU 亲和性 ≠ 简单绑核:NUMA-aware + CFS bandwidth 控制
GPU 计算密集型 Pod 必须绑定到与 GPU 同一 NUMA node 的 CPU cores,否则跨 NUMA 访存将带来 40–60% 带宽衰减(实测 A100+EPYC 9654 场景)。但 spec.affinity.nodeAffinity 仅解决节点级调度,Pod 级 CPU 绑定需组合使用 cpuset.cpus + topology.kubernetes.io/zone。
以下 YAML 展示一个 vLLM 推理 Pod 的生产级 CPU/GPU 协同配置:
yaml
apiVersion: v1
kind: Pod
metadata:
name: vllm-prod-01
annotations:
# 启用 cgroup v2 + memory.low 防止 OOM kill 影响 GPU 进程
container.apparmor.security.beta.kubernetes.io/vllm: runtime/default
spec:
nodeName: gpu-node-07 # 已通过 NodeLabel + DevicePlugin 确保该节点有 A100-80G
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values: ["zone-a"] # 与 GPU 所在 zone 一致
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["vllm-data-loader"]
topologyKey: topology.kubernetes.io/zone
containers:
- name: vllm
image: ghcr.io/vllm-project/vllm:v0.4.3
resources:
limits:
nvidia.com/gpu: 4
cpu: 24
memory: 128Gi
requests:
nvidia.com/gpu: 4
cpu: 24
memory: 128Gi
# 关键:显式指定 cpuset,且与 GPU NUMA node 对齐
volumeMounts:
- name: dev-shm
mountPath: /dev/shm
volumes:
- name: dev-shm
emptyDir:
medium: Memory
sizeLimit: 4Gi # 必须显式设为 ≥2Gi,vLLM 的 PagedAttention 重度依赖
# 启用 RuntimeClass 实现 cgroup v2 + unified hierarchy
runtimeClassName: nvidia-cgroups-v2配套的 RuntimeClass(需提前部署):
yaml
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: nvidia-cgroups-v2
handler: nvidia-container-runtime
overhead:
cpu: 500m
memory: 2Gi
# 启用 cgroup v2 特性开关
scheduling:
nodeSelector:
kubernetes.io/os: linux
feature.node.kubernetes.io/runtime-cgroup-driver-cgroupfs: "false" # 强制 systemd driver✅ 技术判断:
cpuset.cpus不能仅靠 kubelet--cpu-manager-policy=static自动分配——它无法感知 GPU 的 NUMA node。必须通过topology.kubernetes.io/zone+nodeAffinity锁定物理拓扑,再配合 RuntimeClass 强制 cgroup v2,才能实现真正的异构协同。
2. GPU 共享 ≠ 时间片切分:MIG + vGPU 的运维真相
NVIDIA MIG(Multi-Instance GPU)在 K8s 中常被误用为“逻辑 GPU 分片”。但 MIG 是物理硬件切分,每个 MIG instance 独占 L2 cache、显存控制器、计算单元。若在单卡上创建 7 个 MIG instance(如 A100-80G → 7×10G),则每个 instance 的 FP16 算力仅为全卡的 ~1/7,但PCIe 带宽、NVLink、显存带宽仍被 7 个 instance 共享竞争。
生产建议:
- 训练场景禁用 MIG:DDP 多进程需全卡显存 & NVLink 低延迟,MIG 反而引入跨 instance 通信开销;
- 推理场景慎用 MIG:仅当模型显存 ≤10G 且 batch_size 极小(<4)时收益明显;否则优先用
vLLM的 PagedAttention + continuous batching; - 替代方案:
nvidia-device-plugin+k8s-device-plugin支持nvidia.com/gpu.memory: 20Gi(基于 MIG 的 memory-aware scheduling),但需配合nvidia-smi -L动态发现可用 MIG instance。
3. 数据加载:CPU 成为最大隐性瓶颈
vLLM 的 AsyncLLMEngine 默认启动 4 个 DataLoader 线程,但若未挂载高性能本地 NVMe(而非 NFS/CephFS),或未设置 O_DIRECT,则 CPU 将持续处于 io_wait。我们在线上观测到:当 kubectl top node 显示 cpu-wait > 60%,即使 GPU 利用率 <20%,P99 延迟也飙升 300%。
解决方案 YAML 片段:
yaml
# 在 StatefulSet 中显式挂载 NVMe 直通设备
volumeDevices:
- name: nvme-data
devicePath: /dev/nvme0n1p1
volumes:
- name: nvme-data
persistentVolumeClaim:
claimName: pvc-nvme-gpu-07并在容器内初始化脚本中执行:
bash
# 禁用 ext4 journal(推理场景无需事务一致性)
tune2fs -o journal=none /dev/nvme0n1p1
# 设置 I/O scheduler 为 none(NVMe 原生支持 MQ-DEADLINE)
echo none > /sys/block/nvme0n1/queue/scheduler
# mount with direct I/O flags
mount -o noatime,nodiratime,dax /dev/nvme0n1p1 /data运维建议:面向异构基础设施的 SRE 清单
| 维度 | 生产必须项 | 检查命令示例 |
|---|---|---|
| NUMA 拓扑 | 所有 GPU 节点运行 numactl --hardware,确认 GPU PCI bus 与 CPU cores 同 node | lspci -vv -s $(nvidia-smi -q | grep "Bus Id" | head -1 | awk '{print $4}') | grep NUMA |
| 共享内存 | /dev/shm sizeLimit ≥ 2Gi for vLLM; ≥ 4Gi for multi-GPU training | df -h /dev/shm;kubectl exec -it <pod> -- ls -lh /dev/shm |
| cgroup v2 | kubelet 必须启用 --cgroup-driver=systemd + --cgroups-per-qos=true | ps aux | grep kubelet | grep cgroup;cat /proc/1/cgroup | head -1 |
| 网络栈 | net.ipv4.tcp_tw_reuse=1, net.core.somaxconn=65535, net.ipv4.ip_local_port_range="1024 65535" | `sysctl -a | grep -E "(tw_reuse |
| GPU 监控 | 部署 dcgm-exporter + Prometheus,必须采集 DCGM_FI_DEV_GPU_UTIL, DCGM_FI_DEV_MEM_COPY_UTIL, DCGM_FI_DEV_PCIE_TX_BYTES | `curl http://dcgm-exporter:9400/metrics | grep -E "(gpu_util |
⚠️ 关键提醒:不要信任
nvidia-smi dmon的默认采样间隔(2s)。生产环境请将dcgm-exporter的--collectors显式设为--collectors=dcgm_gpu_util,dcgm_gpu_mem_copy_util,dcgm_gpu_pcie_tx_bytes,并调高 Prometheus 抓取频率至1s——PCIe 带宽毛刺往往在 500ms 级别发生。
延伸阅读
- 📘 CNCF TAG-AI 白皮书 v2.1:首次明确定义 “Heterogeneous Orchestration Layer” 架构层级,提出
TopologyAwareScheduler+DeviceProfile CRD标准。 - 📚 Kubernetes Enhancement Proposal KEP-3982:Topology Manager v2 正式进入 Beta,支持 CPU/GPU/NVMe/SmartNIC 多设备拓扑联合约束。
- 🛠️ 开源工具推荐:
gpu-operatorv24.9+:原生支持 MIG profile hot-reload 与nvidia-dcgm-exporter一键部署;kube-hunter插件--ai-mode:自动扫描 NUMA 错配、/dev/shm不足、cgroup v1 遗留等 AI 特征风险;vLLM Bench:提供--enable-chunked-prefill --gpu-memory-utilization 0.9等真实负载压测模板,比nvidia-smi更早暴露 CPU 瓶颈。
AI 平台工程没有银弹。它是一场在 Linux 内核、GPU 固件、Kubernetes 调度器与大模型框架之间持续校准的精密平衡术。当你下次再看到 nvidia-smi 显示 GPU 利用率低迷时,请先敲入 kubectl top node --sort-by=cpu-wait——因为真正的敌人,往往藏在 GPU 的阴影之外。
—— KnoAI 技术站|深耕 K8s 异构调度一线 · 2026.09