从传统运维到 AI Infra: K8s 上调度 100 张 GPU踩坑笔记

文章目录

    • [一、 显卡不是 CPU:整数绑卡的坑](#一、 显卡不是 CPU:整数绑卡的坑)
      • [1.1 痛点:算力利用率只有 15%](#1.1 痛点:算力利用率只有 15%)
      • [1.2 避坑解法:算力切分的三大流派](#1.2 避坑解法:算力切分的三大流派)
    • [二、死锁灾难:为什么默认调度器会让 100 张卡整夜"空转"?](#二、死锁灾难:为什么默认调度器会让 100 张卡整夜“空转”?)
      • [2.1 默认调度器的"贪心灾难"](#2.1 默认调度器的“贪心灾难”)
      • [2.2 避坑解法:必须引入 Gang Scheduling(组调度)](#2.2 避坑解法:必须引入 Gang Scheduling(组调度))
    • [三、 存储与网络风暴:50 个 Pod 并发拉取,底层直接瘫痪](#三、 存储与网络风暴:50 个 Pod 并发拉取,底层直接瘫痪)
      • [3.1 存储风暴(Storage Storm)](#3.1 存储风暴(Storage Storm))
      • [3.2 网络黑洞(NCCL 通信超时)](#3.2 网络黑洞(NCCL 通信超时))
    • [四、 幽灵故障:cAdvisor 看着一切正常,模型其实一直在输出废话](#四、 幽灵故障:cAdvisor 看着一切正常,模型其实一直在输出废话)
      • [4.1 隐蔽的 CUDA Xid 硬件错误](#4.1 隐蔽的 CUDA Xid 硬件错误)
      • [4.2 避坑解法:DCGM + NPD 自动排空自愈](#4.2 避坑解法:DCGM + NPD 自动排空自愈)
    • [五、 流式打字机的 Nginx 惨案:为什么会"卡顿憋大招"和 504 超时?](#五、 流式打字机的 Nginx 惨案:为什么会“卡顿憋大招”和 504 超时?)
      • [5.1 惨案根因:](#5.1 惨案根因:)
      • [5.2 生产级 Nginx 配置标准:](#5.2 生产级 Nginx 配置标准:)
    • [六、 写在最后:传统运维人的二次跃迁](#六、 写在最后:传统运维人的二次跃迁)

一、 显卡不是 CPU:整数绑卡的坑

在传统的微服务架构里,CPU 和内存是弹性且可以任意细分的。你给一个 Web Pod 分配 cpu: 500m、memory: 1Gi,K8s 的 Cgroups 限制得明明白白。

当我们把大模型往上扔时,迎头撞上的第一堵墙,就是 K8s 原生的资源分配机制。

1.1 痛点:算力利用率只有 15%

K8s 原生的 nvidia.com/gpu: 1 只能做整数整卡挂载。当时业务部门要上线一个 14B 的客服微调模型,单卡显存占用大概 18GB。我们用的是 80GB 的 A800/H800,结果一张卡挂给这个 Pod 后,剩下的 62GB 显存完全闲置,其他服务根本用不了!

月底调出 Grafana 大盘一看账单,:"几千万采购的算力,怎么平均利用率才 15%?!"

传统思维 :Pod 需要显卡 -> resources.limits: nvidia.com/gpu: 1(整卡锁定,巨大浪费)

生产实际:单卡多租户混合、显存切分与算力共享才是常态!

1.2 避坑解法:算力切分的三大流派

为了把显存利用率拉到 80% 以上,我们先后踩遍了三种技术路线:

  • NVIDIA MPS(多进程服务):适合小模型推理的高并发算力共享,算力利用率翻倍;但痛点是一个 Pod 崩溃容易导致共享该卡的所有任务一起挂掉
  • NVIDIA MIG(多实例 GPU):A100/H100 上的物理硬隔离,安全级别极高,但切分规格固定(比如 10G/20G),无法随意定制。
  • 开源 vGPU 方案(如 Hami):在 K8s 层劫持 CUDA 调用,成功实现了对 RTX 4090 / 6000 等卡按 1GB 显存颗粒度和 10% 算力核心进行超卖切分,最终将综合利用率提升到了 75% 以上。

二、死锁灾难:为什么默认调度器会让 100 张卡整夜"空转"?

这是我们经历过的最严重的一次生产事故。那天晚上算法团队提交了两个大规模分布式训练任务(DeepSpeed 多机多卡并行),任务 A 和任务 B 各需要 32 张卡(4 台 8 卡机器协同)。

2.1 默认调度器的"贪心灾难"

K8s 默认的 kube-scheduler 是典型的"来一个 Pod 分配一个 Pod":

任务 A 抢到了节点 1、节点 2(共 16 张卡),正在等待剩下的 16 张卡;

任务 B 抢到了节点 3、节点 4(共 16 张卡),也在等待剩下的 16 张卡;

此时集群里只剩下零散卡槽,任务 A 和任务 B 谁也凑不齐 32 张卡!

任务 A:占住 16 卡 ──(等待另外 16 卡)──► 无法启动

任务 B:占住 16 卡 ──(等待另外 16 卡)──► 无法启动

结果:全集群陷入"活锁死锁",几千万的 GPU 白白空转了一整夜!

2.2 避坑解法:必须引入 Gang Scheduling(组调度)

传统 Web 服务可以一个一个起,但分布式 AI 训练必须满足:"All-or-Nothing(要么全部满足同时起,要么一个都不起)"。

我们紧急下线了默认调度,全面切换到云原生批量调度平台 Volcano 与 Kueue:

  • Gang 组调度:设置 minAvailable: 32,只有当 32 个 Pod 所需资源全部锁定时才统一放行绑定,彻底杜绝互相死锁;
  • Queue 队列与优先级抢占:区分"高优先级在线推理"与"低优先级离线微调",白天推理并发高时抢占算力,夜间算力空闲时自动释放给批处理任务跑微调。

三、 存储与网络风暴:50 个 Pod 并发拉取,底层直接瘫痪

大模型动辄几十 GB,这不是常规几百 MB 的 Java/Go 容器镜像,而是一场对机房 I/O 的极限摧残。

3.1 存储风暴(Storage Storm)

当我们尝试做一次水平扩容,50 个推理 Pod 同时启动并从内部共享存储(NFS / Ceph)拉取 80GB 的模型权重时,存储集群的 IOPS 和网络出口瞬间被打爆,节点大面积陷入 NotReady,K8s 出现大面积探针超时。

  • 避坑方案:放弃传统的集中式拉取,采用 JuiceFS + 本地高速 NVMe 缓存,并在每个 GPU 节点上挂载只读缓存盘;同时引入 Dragonfly P2P 镜像加速,百台节点分发大镜像不再依赖中心镜像仓库。

3.2 网络黑洞(NCCL 通信超时)

在做多机多卡训练时,最折磨运维的报错莫过于:

复制代码
NCCL WARN Timeout waiting for operation to complete...

传统的千兆/万兆以太网在处理模型全量同步(AllReduce)时延迟极高,CPU 频繁丢包。搞 AI Infra 必须补课 RoCE v2(RDMA)无损网络,在 K8s 中通过 SR-IOV 插件将物理网卡直通进容器,才能把通信延迟压缩到微秒级。

四、 幽灵故障:cAdvisor 看着一切正常,模型其实一直在输出废话

传统的微服务监控体系,在 GPU 硬件故障面前就像个"睁眼瞎"。很多时候,K8s 显示 Pod 处于 Running 状态,CPU 和内存占用完全正常,但算法同学却跑来投诉:"模型推理怎么卡死了?吐字速度只有 1 Token/s,有时候还全是乱码!

4.1 隐蔽的 CUDA Xid 硬件错误

GPU 硬件非常脆弱。供电瞬断、散热不良、显存 ECC 双位翻转,都会触发 NVIDIA 底层的 Xid 错误(例如经典的 Xid 31: GPU memory page fault 或 Xid 62)。此时显卡可能已经掉频甚至半死,但只要容器进程没彻底 Crash,K8s 就觉得它"很健康"

4.2 避坑解法:DCGM + NPD 自动排空自愈

我们彻底重构了监控链路:

  • 废弃单纯的 Node-Exporter,全量上线 NVIDIA DCGM-Exporter,实时采集 GPU 温度、风扇转速、显存带宽利用率与 ECC 错误率;
  • 联动 Node Problem Detector(NPD):一旦捕获到特定的硬件 Xid 错误,立刻给当前节点打上污点(Taint),自动将上面的业务 Pod 优雅驱逐(Drain),并触发硬件保修脚本,不再等人肉排查。

五、 流式打字机的 Nginx 惨案:为什么会"卡顿憋大招"和 504 超时?

好不容易把集群和模型跑通了,挂上 Nginx 对外提供 API 服务时,前端用户又炸锅了:"说好的丝滑打字机效果呢?怎么屏幕卡住几十秒,然后突然哗啦一下蹦出一大坨字?!"更有甚者,遇到复杂长文本推理,前端动不动就弹窗报错:504 Gateway Timeout。

5.1 惨案根因:

  • 缓冲陷阱:Nginx 默认配置了 proxy_buffering on;,它把大模型吐出的单个 SSE Token 存积在内存缓冲区里(攒满 4KB/8KB),才一次性发给客户端,打字机瞬间变成"憋大招";

  • 超时陷阱:Nginx 默认读取超时是 proxy_read_timeout 60s;,大模型做长文本预填充(Prefill)或深度思考时超过 60 秒,Nginx 直接无情断开连接。

5.2 生产级 Nginx 配置标准:

在转发大模型推理路由时,必须严格配置以下参数:

shell 复制代码
location /v1/chat/completions {
    proxy_pass http://vllm-backend;

    # 彻底关闭缓冲,强制逐 Token 秒级直推客户端
    proxy_buffering off;
    proxy_cache off;
    chunked_transfer_encoding on;

    # 调大超时时间,适配长文本思考与推理
    proxy_read_timeout 600s;
    proxy_send_timeout 600s;

    # 维持 HTTP/1.1 长连接
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}

六、 写在最后:传统运维人的二次跃迁

过去微服务时代,K8s 运维的工作大多被各大公有云平台(ACK、TKE、EKS)封装成了标准服务,纯微服务运维的薪资天花板越来越低。

相关推荐
镜子AI1 小时前
镜子AI工程实践:用熵权法 + TOPSIS 做多方案选型排序(零依赖 Python)
开发语言·人工智能·python
维基框架1 小时前
OpenAI GPT-6.1 Terra发布AI开始真正操作电脑,使用成本也降了
大数据·人工智能·gpt
志尊宝1 小时前
AI原生前端开发(028):AI辅助的调试与错误修复
人工智能·笔记·重构·ai-native
海宇服务1 小时前
零信任架构实战:基于海宇个人大数据报告构建自动化汽车融资租赁资信核验网关
大数据·人工智能·架构·自动化
怎么全是重名1 小时前
CLIP-Learning Transferable Visual Models From Natural Language Supervision
人工智能·深度学习·计算机视觉·异常检测
具身AGI1 小时前
VLA 忘记物理世界,物理AI 物理推理 两个病因
人工智能
ai_coder_ai1 小时前
使用Web IDE边写自动化脚本
运维·前端·自动化
wacsii1 小时前
【Linux基础开发工具(五)】Git版本控制器从入门到实战:核心操作三板斧与新手避坑指南
linux·运维·服务器
广州国启未来1 小时前
企业 AI 落地三件套:RAG、私有化大模型、Agent 智能体
人工智能