ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

国产算力集群7×24小时压测实战:稳定性排查与工具链全解析

国产算力集群7×24小时压测实战:稳定性排查与工具链全解析 7×24小时压测跑到第21个小时的时候凌晨两点半值班群里炸了锅一张国产加速卡的HBM显存占用率异常升高业务侧开始报OOMKubernetes反复重启那个Pod整个分布式训练任务卡在同步阶段训练效率肉眼可见地往下掉。这是我近期做过的最累、也是收获最大的一次国产算力集群稳定性测试。国产算力集群和常规x86服务器集群最大的区别在于硬件架构新、驱动和固件迭代快、算子生态还在快速补齐很多问题不属于能不能跑而属于跑久了会不会出事。这类问题只有长时间压测才能钓出来。这篇文章我会完整复盘这次7×24小时压测的全过程覆盖测试方案设计、工具选型、并发数确认、监控指标建立以及在压测过程中真实遇到的几起故障排查链路。内容偏工程实践适合正在做算力集群交付、AI训练平台稳定性保障或者刚接手国产算力集群运维的同学参考。1. 为什么国产算力集群的7×24小时压测这么难避开1.1 短压测发现不了的四类问题很多团队在集群上线前只跑2到4小时的压测看性能数据达标了就交付。这个节奏对于成熟的国外GPU集群也许勉强够用但对国产加速卡集群风险相当大。我把这段时间遇到的高频问题归成了四类显存/内存泄漏型进程每跑一个迭代就泄漏几十MB显存或者主存单独看单次迭代完全正常但累积到第8小时、第20小时OOM就来了。驱动和固件的边缘条件bug某些驱动版本在特定频率的中断请求、特定尺寸的通信消息组合下文件句柄、事件计数器会持续累积短时间压测根本走不到那个累积量。散热和供电的温水煮青蛙满载压测早期温度稳定但随着机房精密空调联动策略变化、相邻机柜负载波动机柜进风温度慢慢上升芯片触发降频保护性能一天比一天差。互联通信的静默降级RDMA网卡或者交换机的错误计数累积到一定阈值后链路触发降速或者ECMP哈希偏移分布式训练里的AllReduce带宽下降算力利用率从92%跌到65%但业务不报错非常隐蔽。这些问题的共同点是都需要时间作为催化剂。4小时以内大概率都触发不了7×24小时压测的价值恰恰就在这里。1.2 稳定性压测的四个层次硬件、驱动、调度、业务链路在设计压测方案前我先理清了这次测试需要覆盖的四个层次这也是国产算力集群稳定性压测的基本分层逻辑。硬件层加速卡的算力、显存带宽、PCIe/RDMA链路、供电和散热。这一层我们用厂商提供的smi工具类似nvidia-smi配合自研的算子压力程序来测。驱动/固件层驱动驻留进程、设备健康检查、错误恢复机制。这一层很多问题要等上十几个小时才显现也是7×24压测的主要目标。调度层Kubernetes对加速卡资源的分配回收、容器退出后显存是否释放、节点异常后任务能否自动迁移。这一层最容易出现资源泄漏累积类问题。业务链路层训练任务吞吐、推理服务P99延迟、数据加载和checkpoint落盘是否稳定。这一层决定了压测结果对实际业务有没有参考价值。聪明的读者应该发现了这四个层次并不是独立的显存泄漏可能同时触发驱动层和调度层的问题网络降级又会直接反映到业务层的吞吐指标上。所以整个压测过程中我们并不是只盯一个指标而是四条线的数据同时采集、交叉验证。2. 压测之前先摸底并发数、基线指标与监控体系怎么定2.1 并发数不是拍脑袋定的梯度加压法确定系统承载上限很多刚接触压测的同学上来就问并发数设多少合适答案通常是看系统承载上限而上限必须用梯度加压法测出来。这一步在JMeter里操作非常标准也建议其他工具都遵循同样的思路。我用JMeter简单描述一下完整步骤第一步录制或定义被测系统的核心接口比如大模型推理服务的/completions接口、训练集群的日志上报接口。第二步从10并发起步持续压10分钟记录TPS、平均响应时间、P99、错误率。第三步并发翻倍到20、50、100、200每档同样跑10分钟继续记录。注意每档之间停顿2分钟让系统把连接池和队列排空避免上一档的积压影响下一档数据。第四步画TPS和响应时间随并发变化的曲线找出拐点。拐点的判定逻辑是这样的当并发从50加到100时TPS还在明显增长、响应时间小幅上升说明系统还没到上限继续加到200时TPS几乎不再增长甚至下降P99响应时间突然恶化错误率开始冒头那200就是压力拐点。结合我们这次的实际数据推理服务在并发50档时TPS为3200并发100档时TPS只涨到3350P99却从80ms涨到240ms。显然100并发已经不是合理承载区间。我们把推荐承载并发定在拐点的70%-80%也就是70左右压测的峰值水位则定在100压测过程中允许P99抖一抖但不允许错误率超过0.1%。这里还有个小教训梯度加压做了两轮第一轮是早上做的第二轮是下午做的两轮得出的拐点差了将近15%。查了半天发现是下午机房温度升高后芯片轻微降频性能天花板低了。所以做基线摸底时最好固定在同一时间段并且记录当时的机房温湿度否则你测的可能是天气数据。2.2 用硬件基准测试校准理论天花板业务接口的压测数据只能代表系统整体表现如果想区分瓶颈是软件还是硬件必须在压测前先跑一遍硬件基准测试。我这次做了三类基准测试算力基准用厂商的矩阵乘法算子做持续大尺寸GEMM计算跑30分钟看实际算力达成理论峰值的百分比。国产加速卡一般能达到理论峰值的75%-85%就算正常如果连70%都到不了多半是驱动或算子库版本有问题。通信基准用集合通信库做节点间AllReduce带宽测试持续20分钟。记录带宽均值、抖动幅度。存储基准模拟checkpoint写入场景连续写大文件看存储带宽是否稳定。这三类基准数据会在后续压测中反复用到。比如第4章的训练效率腰斩案例正是因为我在压测前后各保留了一份通信带宽基线才能迅速定位问题是出在网络而不是算力。2.3 压测期间要看哪些指标7×24小时压测最忌讳只看业务层TPS。我们这次建立了一套按角色划分的指标清单全部接入Prometheus统一采集Grafana出图。指标采集方式正常参考阈值加速卡利用率厂商smi工具exporter压测期间稳定在85%以上显存/HBM占用厂商smi工具exporter应围绕某一水平波动不允许单调递增芯片温度厂商smi工具exporter不超过厂商规定的降频阈值互联带宽与错误计数交换机SNMP 集合通信库自测错误计数增量约为0主机CPU/内存/句柄数node_exporterCPU不长期100%句柄数不持续增长任务调度队列Kubernetes API队列长度不超过10业务侧TPS/P99/错误率k6/JMeter聚合报告P99在目标水位内错误率低于0.1%这里我想特别强调显存占用这个指标。平时大家看显存都看当前值但压测场景更该看变化值。如果显存曲线每小时的斜率是正的哪怕斜率很小都必须高度重视这就是慢性泄漏的典型信号。后面4.1节的案例就是靠这个判断先发现了线索。2.4 压力参数的设定四个水位法压力参数不能设一个固定值就跑一整天因为目标水位和危险水位应该是两回事。我习惯把压力参数分成四个水位峰值水位压测要达到的最大压力对应前述梯度加压的拐点并发本场景是100并发目的是验证系统在极限边缘不崩。期望水位日常业务运行的典型压力本场景是50并发对应接近线性区间的中段。告警水位当系统资源占用或响应时间越过告警阈值触发值班通知但不中断压测。危险水位当错误率超过0.5%或出现单点故障需要人工介入必要时降级压测。7×24压测并不是一直跑峰值水位那没有意义。我们的做法是白天高峰时段以期望水位为主每两小时插一段15分钟的峰值水位夜间降载到期望水位的60%左右同时保留一个常驻的长稳任务在后台持续跑模拟真实环境的潮汐特征。3. 执行方案工具选型、测试场景与7×24值守安排3.1 压测工具怎么选k6、JMeter、自研压测进程的配合提到压测很多人的第一反应是JMeter。它确实生态成熟但我个人不建议用JMeter一个工具扛完7×24的场景原因后面4.4节会具体讲。我这次用的是三个工具配合k6负责接口层和微服务链路的持续压力。k6脚本用JavaScript写非常轻量单机就能打出较高的并发适合长时间稳定施压。下面是这次用的一个最简脚本骨架import http from k6/http; import { check, sleep } from k6; export const options { // 100并发持续跑压测7×24由外部守护进程控制 vus: 100, duration: 12h, thresholds: { http_req_failed: [rate0.001], http_req_duration: [p(99)250], }, }; export default function () { const res http.post( http://推理服务地址/completions, JSON.stringify({ prompt: stable test prompt, max_tokens: 64 }), { headers: { Content-Type: application/json } } ); check(res, { status is 200: (r) r.status 200 }); sleep(0.1); }JMeter负责复杂的混合业务流压测。我们用JMeter模拟了数据上传、模型加载、批量推理、结果回传等多个环节串联的复杂场景方便做线程组之间的依赖控制。JMeter压测机部署在独立的虚拟机集群上直接连接到被测集群的负载均衡入口。自研压测进程负责给加速卡本身施压。用Python或C写一个循环反复执行大尺寸矩阵乘法、卷积算子占满算力、打满显存带宽。这样能确保除了业务请求底层算力也处于持续满载状态。这三个工具各管一段自研进程管卡k6管服务JMeter管业务流。三者同时跑才能在业务层出问题时反查底层原因。3.2 场景设计混合负载比纯压力更能显露问题很多压测方案设计成一马平川的恒定压力这其实不利于暴露稳定性问题。真实业务是波动的系统在压力突变时最容易出状态错乱。我在这次测试里加入了三类混合场景昼夜潮汐场景白天模拟业务高峰k6和JMeter的并发数按计划周期性调整夜间降低到60%但保持长稳任务持续运行。周期性checkpoint场景每隔2小时模拟一次训练任务checkpoint落盘同时保留推理流量在跑。这样能验证存储子系统在压力叠加下的表现很多分布式存储的故障都是在这种叠加场景下暴露的。混部场景在部分节点上同时调度训练任务和推理服务故意制造资源争抢观察调度器在国产加速卡资源碎片化时的处理能力。混合场景带来的最大问题是结果分析复杂指标会有正常波动。所以我在设计场景时配套了一个场景时刻表每个时间点对应哪几个场景在跑全部落到表格里。后续复盘任何一个异常指标都能追溯到当时在跑什么场景。3.3 7×24小时值守与告警怎么熬过一整天长时间压测对团队最大的消耗不是技术是人。我的经验是一定要把告警分级和值守轮班提前制定好否则7×24跑完技术问题没解决团队先垮了。告警我们分了三级P0业务错误率超过0.5%、加速卡掉线、存储不可用。这类告警要求值班人员15分钟内响应直接联系二线专家。P1温度接近降频阈值、显存曲线持续增长、任务队列堆积。要求1小时内处理先确认现象再决定是否介入。P2指标轻微波动、告警恢复自愈。记录到当天的日报里不打断值班休息。值班排班采用三班倒白班9点到18点由测试开发驻场负责观察、记录、跑排查命令小夜18点到24点和深夜班0点到9点以远程值班为主盯告警群和Grafana。每班交接时填写一份简化的值班交接表上面只保留三个要素当前压测阶段、异常事件列表、遗留问题。我还会在压测机上挂一个定时脚本每30分钟自动截一次Grafana关键面板的图同时抓一遍系统日志的关键错误行存到独立目录。这个习惯帮了大忙——很多偶发异常是在事后复盘时从这些自动留存的过程快照里找到线索的。4. 走访踩坑全程四起压测中翻车案例的真实排查链路4.1 案例一显存泄漏导致任务被K8s反复驱逐现象出现在压测第21小时。值班群告警某推理Pod的OOMKilled计数持续增加节点状态从Ready变成NotReady几分钟后又恢复过一会儿再次NotReady分布式训练任务卡在参数同步阶段。排查链路是这样的第一步看监控曲线。我打开显存占用面板发现某张卡的显存占用并不是突然飙高而是从压测第8小时开始每一小时稳定上升大概450MB。这说明不是某个大请求导致的瞬时OOM而是典型的慢性泄漏。第二步看dmesg和厂商smi工具的日志。dmesg里有大量RAS: ECC correctable error记录但没有不可恢复的硬件错误。厂商smi工具显示卡的health状态正常。第三步手动复现。我们在维护窗口申请同一型号的卡写了一个小程序循环申请、释放显存结果发现每次释放后显存基线都会比前一次高一点点。到这里基本锁定是驱动层的显存回收逻辑存在泄漏。第四步升级固件和驱动版本后重新起了一个12小时的前置验证显存曲线走平泄漏消失。这个案例的核心经验是显存监控一定要看趋势而不是看当前值。如果值班人员只在显存到达90%时才看一眼会误以为是正常的压力波动根本没法提前预警。4.2 案例二互联网络丢包率悄悄升高训练效率腰斩这个故障是四个案例里最隐蔽的。压测第46小时业务报训练吞吐下降明显但推理服务的TPS没有明显波动。我们起初以为只是训练任务自身的问题。排查链路第一步看训练任务侧指标。算力利用率从92%降到了65%但加速卡的利用率仍然是100%说明卡一直在算但大量时间花在等待网络数据上。第二步看集合通信日志。日志里出现了NCCL timeout和no progress的警告频率不高但一直在增多。第三步看交换机的RoCEv2统计。发现其中一个端口的PFC pause帧数量比基线时期增加了约两个数量级。pause帧说明接收端拥塞数据被流控住了。第四步用无损网络自测工具做端到端带宽测试定位到某根光缆连接的端口异常。换线缆、清洁光模块后带宽恢复训练吞吐在半小时内回到88%以上。这个案例提醒我分布式训练对网络的敏感性远高于普通业务网络层面即使只是0.1%的丢包率都会因为重传指数放大造成算力利用率断崖式下跌。所以后来的压测方案里我把互联错误计数增量设成了一个独立的P1监控项。4.3 案例三机房制冷不足触发降频温度墙记录曲线找出的元凶压测第30小时我们发现某机柜里所有加速卡的算力利用率都从95%掉到80%左右但Kubernetes没有任务失败业务也没有报错比4.2更安静。这种安静的性能下降是最难查的。排查链路第一步查性能计数器。厂商smi工具显示芯片时钟频率从1755MHz降到了1305MHz左右这个频率变化直接对应算力下降。第二步查温度。所有卡的芯片温度都维持在85度附近超过厂商建议的80度舒适区进入降频范围。第三步查机房环境。进风温度接近26度高于机房设定的23度。再查精密空调运行日志发现空调压缩机在压测中段有一次切换操作制冷联动没有及时跟上机柜负载的增加。第四步调整气流组织并临时把空调设定温度调低1度芯片温度降到79度以内时钟频率恢复算力利用率回到94%。这个案例说明压测不仅是软件层面的事。给国产算力集群做长时间满载压测一定要提前跟基础设施团队确认制冷余量和供电余量否则你压测出来的性能数据会是一份不断被环境因素干扰的数据。4.4 案例四压测工具自身先崩了——压测架构的容量规划这个案例发生在压测第52小时。JMeter集群报了大量的connection reset错误率飙升达到P0标准。我们紧急介入准备切流量重启压测结果发现被测推理服务的日志一切正常。排查后续才发现问题出在JMeter施压机自身这台用于JMeter的虚拟机上文件句柄数达到上限导致连接池里的socket无法正常建立。也就是说是压测工具自己先崩了被测系统反而是健康的。这个案例给我的教训非常深压测前必须先用小流量验证施压端能力确保JMeter集群能打出比目标并发高30%的压力有余量。施压机要和被测集群严格分离开不能用同一台交换机下的虚拟机同时扛两边的压力否则网络抖动时两边一起挂。施压机的资源监控也要纳入告警重点关注文件句柄数、线程数、JVM堆内存。后来我们把JMeter压测机的句柄数上限调大同时额外加了一台备用的施压机一旦主施压机自身指标异常立刻切换。这个改动直接把后续压测的假故障清零了。5. 稳定性压测结果怎么评估指标计算与报告输出5.1 用变异系数替代平均可用率作为核心指标我见过很多稳定性测试报告写着系统可用率99.5%看起来很漂亮但根本经不起推敲。可用率是个平均值掩盖了抖动。真正应该看的是指标在时间轴上的离散程度。我这次引入了变异系数CV这个概念公式很简单CV 标准差 / 平均值对TPS和P99分别计算。CV越低说明系统输出越稳定。我的评价参考标准是CV范围稳定性评价建议小于5%优秀可以进入验收交付5%-10%可接受继续观察关键抖动点10%-15%需要治理找出抖动源并优化大于15%不稳定不建议上线排查根因举个例子压测后期优化完成后推理服务的TPS平均值为3100标准差为140CV约4.5%评价为优秀而压测早期同样的场景TPS平均值为2850标准差达到620CV超过21%明显不稳定。同一组数据用可用率都是99%以上但用CV一下就分出了高下。5.2 故障闭环率与恢复SLA除了性能稳定性还要统计可用性指标。我在报告里列了这几项故障次数整个7×24中触发P0告警4次P1告警7次。MTBF平均故障间隔用总时长除以故障次数约4.8小时一次P0级别的严重故障这个数字在优化前确实不好看。MTTR平均恢复时长P0故障从发现到恢复的平均时间是35分钟距离目标的15分钟还有距离。闭环率所有发现的故障最终是否都定位到了根因并验证修复闭环率越高说明压测不只是吓唬人而是真能推动系统变好。这些指标合在一起才是一份有说服力的稳定性报告。单看跑满了7×24没死人其实意义不大——没人能保证跑完24小时不出问题关键是出了问题能不能系统性解决。5.3 从monkey测试到混沌工程随机破坏力是稳定性的试金石聊到稳定性就绕不开monkey测试。大家比较熟悉的是Android生态里的monkey命令通过向系统发送大量伪随机事件流来验证长时间运行的稳定性。这个思想完全可以迁移到算力集群压测中。我们在7×24压测中后期借鉴了monkey的思路设计了一组随机干扰实验随机kill掉一个正在运行的训练Pod观察调度器能否在预期时间内拉起新Pod到其他节点。随机登入一台计算节点手动触发一次驱动重新加载观察已运行的容器是否异常退出。随机向存储模块发起大量的孤儿写请求制造I/O扰动观察checkpoint是否能照常完成。随机改变k6脚本的请求间隔模拟突发流量毛刺观察限流和排队机制。这些随机操作并不是要去破坏系统而是提前制造可控的乱验证系统在乱局里能不能自愈。混沌工程的核心原则是先小范围试确保任何一次注入都不会导致不可恢复的灾难然后逐步加码。5.4 报告怎么写给管理层的摘要和给工程的附录压测报告如果只给一个技术结论管理层看不懂如果全是商业汇报工程师拿不到可执行的细节。我的做法是拆成两部分。前面两页给管理层一句话结论系统经过7×24压测当前达到/未达到稳定性目标。关键数字故障次数、CV、P99达标情况、吞吐变化趋势。剩余风险列三到五项当前仍未解决、但不阻断裂收的风险点每个点附带一句如果发生会怎么样。后面全部为技术附录给工程师每个P0/P1故障的完整排查链路从现象到根因到修复方案再到验证结果。所有监控面板的链接、日志文件的存放路径。故障复现脚本和复现步骤。优化前后核心指标的对比表。报告模板化之后每次压测的产出质量稳定后续查阅也方便得多。6. 配套工具链与后续扩展大模型链路全量压测的方向6.1 面向大模型训练/推理场景的全链路压测这次7×24压测主要跑的是推理服务和混部训练场景。但如果集群核心业务是大模型训练还需要升级到大模型链路全量压测。全链路压测和普通接口压测的区别在于它不只看一个服务端点而是覆盖从数据进来到结果出去的所有环节。一条典型的大模型训练链路至少包括数据加载与预处理DataLoader从分布式存储读取原始数据做清洗、tokenize喂给GPU。这里的瓶颈是存储带宽和CPU预处理能力。前向与反向计算GPU/NPU算力是否吃满算子是否有低效实现。梯度同步与通信AllReduce是否在通信图上打折扣网络是否成为瓶颈。Checkpoint落盘周期性保存模型权重时存储能否扛住瞬时写入洪峰。推理服务如果集群混部推理请求的排队策略、显存分配策略是否被训练任务挤占到不可接受。全链路压测里通常用真实数据集、真实模型、真实的超参配置跑若干个完整的训练批次把每个阶段的耗时和资源利用率单独打点最后串成一张链路耗时瀑布图。哪个环节的等待时间长瓶颈一目了然。6.2 压测持续化流水线里的混沌巡检7×24压测毕竟成本高不能每个版本都来一轮。我的建议是建立三级压测节奏每次代码变更后跑4小时的快速稳定性验证覆盖主要接口和单机算力目标是拦截明显回归。每两周跑一次8小时稳定性测试加入混部和混沌注入场景。每个季度或重大交付前跑一次7×24全量稳定性测试完整复现这次做的事。这样既能控制成本又能让稳定性测试成为持续集成的一部分。长期看比一次性突击压测有效得多。6.3 成本与收益不建议一上来就做7×24最后说点反共识的体会我不建议任何团队在第一次接触国产算力集群时上来就安排7×24压测。原因很简单基础设施的坑都还没填平。第一次跑的时候很可能是前8小时在解决网络配置问题中间8小时在跟驱动bug斗智斗勇最后8小时在等数据跑完。表面上看跑满了24小时实际上有效测试时间非常有限。更合理的路径是先用4小时压测跑通整个监控、告警、汇报链路再扩展到24小时确认没有问题盲区后再启动7×24。本次案例里那个压测工具自身先崩了的问题就是因为前期没做施压端能力验证完全可以通过短压测提前暴露。这次7×24压测给我个人的最大体会是国产算力集群的稳定性问题很少是单一硬件故障更多是驱动、调度、网络、制冷多个环节在长时间维度上的低水平叠加。压测方案设计得再好也不如把每一次故障都追到根因并修复来的实在。最后再分享一个小技巧压测结束后别急着把环境拆掉保留完整的监控数据和现场快照至少一周。很多偶发问题不会当场现形往往是过几天复盘曲线时才从某个不起眼的毛刺里抓到真正有价值的线索。
返回列表