ARTICLE DETAIL

资讯详情

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

AI平台监控告警体系实战:从指标设计到告警治理

AI平台监控告警体系实战:从指标设计到告警治理 1. 为什么AI平台的监控告警和传统业务系统完全不是一回事先说个我踩过大坑的背景。前几年我接手过一个AI开发平台的运维和稳定性保障工作平台里跑着大量模型训练任务、推理服务、数据预处理作业。最开始团队沿用传统Web系统的监控思路——盯CPU、盯内存、盯接口耗时结果发现完全不够用而且误导性极强。举一个例子某个GPU训练任务显示GPU利用率只有15%按传统思路看这是资源严重闲置该告警了。但实际上这个任务正在跑数据加载和预处理GPU本来就要等数据利用率低是正常的。反过来有时候GPU利用率拉满到98%看着很健康可模型收敛速度反而变慢了原因是DataLoader成了瓶颈GPU在空转等数据。这种场景下指标本身没异常业务结果却出了大问题。传统监控根本无法覆盖这种复杂的判定逻辑。AI开发平台的核心特征决定了监控告警体系必须重新设计。第一任务类型高度异构训练、推理、数据清洗、模型评估各自的生命周期和资源特征差异巨大第二成本敏感GPU、TPU这类算力资源很贵跑一个小时就是真金白银异常没及时发现等于烧钱第三故障模式复杂一个问题往往跨层出现数据问题可能导致训练发散显存泄漏会导致任务被OOM杀掉网络抖动会引发分布式训练断点。所以做这个项目时我给自己定了几条核心原则。首先是分层监控平台层、任务层、业务层各管各的指标不混在一起其次是实时优先AI任务跑起来以后状态变化是以秒级甚至毫秒级发生的5分钟粒度的采集在大多数场景下都太慢了最后是告警必须可执行每条告警发出时接收人应该能立刻判断“发生什么、影响什么、先做什么”而不是一条冰冷的“GPU利用率超过90%”。这套思路跑通之后平台上的故障平均发现时间从小时级压到了分钟级算力浪费率也明显下降。下面我把这套体系拆开讲从指标设计到告警触达再到实战排查都是可以直接落地参考的东西。2. 监控指标设计先想清楚监控什么再谈怎么告警2.1 三类核心指标业务级、资源级、引擎级AI平台的监控指标如果只选一类优先选业务级。业务级指标直接反映任务是否在按预期推进比如训练任务的当前Loss值、准确率变化趋势、推理服务的请求成功率、P95延迟、队列积压量。这些指标出了问题不一定伴随资源异常但一定意味着业务受损。Loss突然变成NaN你从CPU和内存指标上是看不出来的但业务级指标一秒钟就能发现。资源级指标是第二层包括GPU利用率、显存占用、CPU负载、内存水位、磁盘IO、网络吞吐。资源级指标的核心价值在于辅助判断——业务指标异常时用资源指标排查根因业务指标正常但资源指标接近上限时提前扩容或限制新任务调度。资源指标不能单独作为训练的告警依据但可以作为调度和容量规划的参考。引擎级指标是很多团队容易忽略的一层。一个训练任务跑在PyTorch或TensorFlow上框架本身会暴露很多内部状态比如DataLoader的吞吐、梯度同步耗时、通信库的带宽利用率、队列深度。我之前排查过一起分布式训练变慢的问题业务指标和资源指标都非常正常最后看了NCCL的通信指标才发现是某个节点的网络拥塞导致梯度同步被拖慢。引擎级指标在排障时价值极高强烈建议有条件就接。2.2 算力浪费率AI平台最值得盯的一个复合指标传统监控里有一个经典指标叫资源利用率但在AI平台上资源利用率高不等于效率高。我自己设计了一个复合指标叫“算力浪费率”定义是GPU处于空闲或等待状态的时间占比包含任务排队时间、数据加载等待时间、梯度同步阻塞时间、检查点写入阻塞时间等。这个指标怎么算简单版本是这样的在GPU监控数据里把SM活跃度很低但任务又没有结束的时间段统称为“闲置时间”然后除以任务总运行时间。更精细的版本需要结合任务日志来判断当前处于什么阶段比如在等数据还是在等通信。实现上可以在训练脚本里埋点记录每个step中实际计算耗时和数据加载耗时这样能算出粒度更细的浪费比例。我之前见过一个训练任务总运行时长是8小时但实际GPU计算时间只有6小时浪费率高达25%。排查发现是数据预处理环节没做好图片解码全部落在CPU上GPU每跑完一个batch就要等很久。这个场景如果只看GPU利用率你会看到大概75%不算低但用算力浪费率一衡量四分之一的算力白烧了。2.3 自定义指标的埋点规范与通用套路监控系统再好如果业务指标没有埋点一切都是白搭。对于AI训练任务我建议在训练循环的关键节点主动上报指标而不是完全靠采集器去被动拉取。埋点有几个关键位置每个epoch开始的时刻、每个step的耗时、loss值、学习率、batch处理速度、检查点保存耗时、验证集准确率。埋点规范也很重要我踩过命名混乱的坑后来固定了一套命名规则所有指标用点分命名第一段是领域train、inference、resource第二段是任务类型cv、nlp、rec第三段是具体指标名loss、throughput、gpu_util最后用标签区分任务ID、模型名、节点IP。这样告警规则可以按前缀批量匹配不用一条一条写。如果用的是Prometheus那一套体系注意把step耗时这类指标做成直方图而不是单纯的Gauge。直方图能算百分位数比如P99的step耗时这比平均值更能暴露长尾问题。平均值漂亮但P99爆炸的情况在分布式训练里特别常见某个慢节点会拖慢整个训练只有看高百分位数才能发现。3. 监控告警架构搭建从采集到触达的完整链路3.1 整体架构分层采集、存储、评估、触达一套完整的AI平台监控告警体系我会拆成四层。采集层负责从Kubernetes、GPU设备、训练框架、推理服务里拉取指标存储层负责时序数据的写入和查询评估层运行告警规则周期性判断是否触发触达层负责把告警消息推送到钉钉、企业微信、邮件这些渠道。这里每层都有一些选型上的讲究。采集层如果是Kubernetes环境Prometheus的kube-state-metrics加node-exporter是标配但GPU指标的采集需要用DCGM这是NVIDIA官方的GPU监控工具能拿到显存温度、SM占用率、显存带宽利用率这些细粒度数据。训练框架的指标则通过PushGateway或者直接暴露/metrics端点来采集取决于任务形态。存储层要注意保留周期。指标数据量大尤其是秒级采集的GPU指标一天就能产生上亿条数据点。我一般的做法是原始数据保留7天聚合后的5分钟粒度数据保留30天1小时间粒度保留一年。这样既能满足排障需求又不至于把存储成本打到不可接受。评估层的告警规则要独立于监控存储来设计规则引擎需要支持灵活的表达式和周期性评估。告警触达层则要支持多渠道并且能根据告警级别走不同的路由。整体架构里有一个细节容易被忽视就是告警状态的管理——谁处理的、处理到什么程度、是否恢复这些状态流转要在同一套体系里维护否则告警发出去了后面有没有人管完全失控。3.2 采集端实战配置DCGM、Prometheus和自定义指标接入DCGM的接入方式很简单在Kubernetes里以DaemonSet方式部署dcgm-exporter然后通过Prometheus的ServiceMonitor来抓取。DCGM暴露的指标里我常用的几个是DCGM_FI_DEV_GPU_UTILGPU利用率、DCGM_FI_DEV_MEM_COPY_UTIL显存拷贝利用率、DCGM_FI_DEV_GPU_TEMPGPU温度、DCGM_FI_DEV_FB_USED显存使用量、DCGM_FI_DEV_POWER_USAGE功耗。这里有个坑要提醒DCGM_FI_DEV_GPU_UTIL指的是SM利用率不等于显存利用率两者经常不同步。做告警规则时一定要区分清楚比如你关心显存是否要爆了应该看FB_USED而不是GPU_UTIL。训练框架的指标接入以PyTorch为例可以在训练脚本里启动一个Prometheus客户端暴露自定义端口。关键指标包括当前epoch、当前step、loss值、学习率、数据加载耗时占比。如果训练任务是在Kubernetes里跑的建议把这些指标通过Pod的注解自动发现机制接入Prometheus这样新任务启动后不需要手动配置就能被采集到。# 训练脚本中的指标埋点示意 from prometheus_client import start_http_server, Gauge, Histogram loss_gauge Gauge(train_loss, Current training loss, [task_id, model_name]) step_duration Histogram(train_step_duration_seconds, Duration of each training step, [task_id]) start_http_server(8000) for epoch in range(num_epochs): for batch in dataloader: start time.time() loss train_step(batch) step_duration.labels(task_idtask_id).observe(time.time() - start) loss_gauge.labels(task_idtask_id, model_namemodel_name).set(loss.item())这个埋点方式的好处是Push和Pull都支持任务通过Service暴露端口后Prometheus直接拉取不需要额外的PushGateway。如果任务是跑在Kubernetes Job里的要注意Job结束后Pod退出指标就拉不到了。这时候可以把关键结果通过PushGateway推一次或者在Job结束时把最终指标写到日志里由日志采集链路去处理。3.3 告警规则引擎的选型逻辑告警规则引擎是整个体系的大脑选型时我核心看四个能力。第一是否支持多条件组合比如同时满足“GPU利用率低于10%”和“算力浪费率高于20%”才告警第二是否支持时间窗口比如持续5分钟满足条件才触发第三是否支持聚合计算比如按任务维度聚合所有Pod的GPU指标取平均值第四是否支持动态阈值因为不同任务的正常基线差异很大。Prometheus自带的Alertmanager在处理简单规则时完全够用但做聚合、动态阈值这类复杂逻辑就得靠录制规则recording rules配合外部评估。更复杂的场景可以引入专门的告警平台但中小团队直接用Prometheus生态就够了不必过度设计。告警规则的配置我建议全部用代码管理版本化保存。这样每次改动都有记录出问题能回滚。我曾经见过直接在告警平台上手工改规则改动后没人更新文档后来运营同学误改了一条阈值导致整整一周告警风暴排查了三天才找到原因。自动化运维时代手工操作越少越好。4. 告警策略设计让每一条告警都值得打扰人4.1 告警分级路由P0、P1、P2各自走不同的通道告警设计里最容易犯的错误是“所有异常都发同样的通知”。GPU利用率低要提醒训练Loss发散要提醒服务挂了也要提醒结果值班人员的手机半小时响一次最后看到告警都麻木了。要做到每条告警都值得打扰人必须做分级和路由。我采用的方案是三级告警体系。P0级是最高优先级代表核心服务不可用或者正在烧大钱比如推理服务全部实例宕机、大规模训练任务失败、GPU集群整体故障。P0告警要求立即处理通知路径是电话加短信加IM群而且必须支持告警升级——如果5分钟没人确认自动升级到值班组长再没确认就升级到平台负责人。P1级是重要但短时间内不致命的问题比如单个训练任务触发Loss发散但还没完全失败、某个节点的GPU温度过高、推理服务P95延迟开始恶化。P1告警发到IM群和邮件要求30分钟内响应当天处理完即可。P2级是提示性告警比如单次任务失败有重试机制兜底、某个节点的磁盘使用率达到80%、某条流水线任务排队时间超过阈值。P2合并通知每天发一次汇总即可不用实时打扰。4.2 告警路由设计告警按任务归属自动找人告警分级的下一步是路由。AI平台上跑着几十上百个任务分别属于不同的业务团队一个平台运维不可能也没必要处理所有任务的业务类告警。所以路由规则要能“找到对的人”。设计思路是把告警类别和任务归属结合起来。资源类告警GPU故障、节点宕机、磁盘满路由给平台运维组业务类告警Loss异常、推理准确率下降按任务的owner字段路由给对应的算法团队成本类告警算力浪费率过高、GPU闲置超时路由给资源调度管理员。这里的实现技巧是在训练任务的元数据里打上owner标签告警规则里带上这个标签作为路由依据。告警平台根据标签匹配通讯录自动找到对应的人。这样每条告警只发给真正需要处理它的人噪音量直接下降一个数量级。4.3 告警聚合与抑制告别告警风暴告警风暴是所有监控体系的噩梦AI平台也不例外。某次GPU节点宕机上面的20个训练任务全部失败如果每个任务单独发告警一次事件就是几十条通知。到后面做告警聚合和抑制是必须的功能。聚合策略我用的两种组合。时间聚合同一任务在5分钟内触发的同类告警合并成一条并标明重复次数空间聚合同一个故障源的多个关联告警归并为一个告警组找到根因告警其他作为附属信息附带在详情里。比如节点宕机根因告警是“节点不可用”关联告警是上面所有任务的中断通知用户只需要收到一条包含完整上下文的消息。抑制策略稍微复杂一点核心思路是“高级别告警触发时低级别告警自动静默”。节点宕机已经触发P0告警那这个节点上的GPU温度告警、任务排队告警这些P1/P2级别的通知就暂时不发了因为根因已经定位继续发只会造成噪音。这个策略写起来不复杂但效果极好。4.4 通知渠道配置的实操细节通知渠道上国内团队最常用的就是钉钉和企业微信。以钉钉为例告警通知的核心是自定义机器人Webhook。创建机器人的时候注意安全设置我建议用加签方式而不是关键字方式因为加签更安全可靠。把加签生成的密钥配置到告警平台里每发一条消息都会带上时间戳签名能防止Webhook地址泄露后被恶意调用。配置好Webhook后对消息模板也是要有讲究的。一条合格的告警消息必须包含以下内容告警名称、当前值、阈值、触发时间、影响范围、可能原因、处理建议。如果只发一堆数字接收人还得自己去查系统告警的效率就打了折扣。我维护了一套标准的Markdown告警模板字段齐全运维同学看到后不需要打开监控页面就能做初步判断。企业微信的配置方式类似通过群机器人Webhook接入。主用钉钉还是企业微信取决于公司IM生态但推荐两条都接一条作为主通知通道一条作为备份。我遇到过钉钉Webhook被平台限流的情况告警发不出来的滋味可不好受有备份通道等于上了保险。5. 告警治理与复盘告警数量降不下来说明系统还有问题5.1 告警去重与静默的进阶玩法告警治理的目标不是简单地加静默规则把告警按掉而是让每条告警都有价值。我接手平台的前三个月每天告警量大概在300条左右但真正需要人处理的不到30条剩下全是重复告警、自愈告警和无意义告警。经过治理后日告警量降到了50条左右有效告警率显著提升。去重之外静默规则也要精细化。有些告警是已知问题正在修不需要反复提醒可以设置静默窗口有些告警明确发生在维护窗口内直接跳过。我建了一套静默规则模板支持按时间、按集群、按任务类型、按告警名称做精细匹配。比如某个团队的模型每周日凌晨要跑定时评测评测期间某些业务指标的波动是正常的这个时间窗口就该静默掉对应的告警。但静默规则要经常审查。规则设得太宽松会漏掉真实故障太严格又没意义。我这边每季度会复盘一次所有静默规则确认每条规则当前是否还需要、是否过于宽泛。这个动作很容易偷懒不做但每次做完都能发现几条失效或过于宽松的规则。5.2 告警升级机制确保告警有人处理告警发出去没人看等于没告警。我见过不少团队告警一直在IM群里滚动刷屏但处理的人迟迟没有动作因为都以为“别人会处理”。解决这个问题靠的是告警升级机制。升级机制的基本逻辑是告警确认超时后自动升级到上一级。P0告警5分钟未确认通知值班组长再过5分钟仍未确认直接电话联系平台负责人。P1告警30分钟未确认升级到团队负责人。这里的“确认”不是简单点一下按钮而是在告警平台上标记“正在处理”并附上初步处理说明。这样既保证有人响应也留下了处理记录。落地这个机制告警平台需要支持状态流转管理。我的做法是维护一张告警处理表每条告警有状态触发中、已确认、处理中、已恢复、已关闭。所有状态变更都记录操作人和时间方便复盘。这块功能Prometheus Alertmanager原生支持有限我用的是一个自研的轻量告警平台来管理状态和升级效果很好。5.3 运行日报与周报用数据驱动持续改进告警治理不能只靠出问题时才去处理要形成闭环。我建立了一套“告警日报”机制每天早上10点自动统计前一天的告警数据总额、分级占比、平均处理时长、重复告警Top10、告警来源分布。日报用定时任务生成推到管理群和研发群里让所有人看到自己负责的模块告警情况。周报的粒度更粗一些重点看趋势本周告警量和上周对比是上升还是下降、耗时最长的告警是哪些、有没有反复出现的同一类问题。趋势上升说明系统在变差或者有新的变更引入了问题需要主动排查同一类问题反复出现说明根因没解决只是在反复处理表象。这套机制看起来简单但坚持下来效果显著。哪个团队告警多、处理慢数据一摆出来比任何沟通都有效。运营团队看到自己负责的数据管道告警最多自然会去优化算法团队看到自己的训练任务频繁因OOM被杀也会主动修显存管理。数据驱动改进是告警治理从“救火”走向“防火”的关键。6. 一次实战复盘训练任务抖动引发的告警风暴6.1 事情经过不到10分钟平台告警刷了200多条某天下午2点左右告警平台突然开始刷屏大量训练任务同时上报“GPU利用率过低”和“训练速度下降”告警。不到10分钟累积告警超过200条值班群直接被刷爆。按经验判断这种大量任务同时异常的情况大概率不是各任务自身的问题而是某个公共依赖出了问题。初步排查时我先看了资源层指标GPU利用率、CPU负载、内存都正常节点也没有宕机。从告警时间来看所有异常几乎在同一时刻开始符合“基础设施或共享服务故障”的特征。顺着这个思路我检查了平台上的共享组件——数据存储服务、镜像仓库、模型注册中心最终定位到是共享文件系统的元数据服务响应变慢导致所有训练任务在读取训练数据时被阻塞。根因清楚后整个事件的时间线也串了起来共享存储的性能抖动传导到所有训练任务的数据加载环节数据加载变慢导致GPU等待GPU利用率下降触发告警同时训练速度下降step耗时增加又触发了另一类告警。多重告警叠加加上没有做聚合就成了告警风暴。6.2 排查过程与修复动作定位到根因后修复动作分三步走。第一步联系存储团队确认元数据服务的状态发现是文件系统客户端缓存过期导致大量元数据请求回源存储后端压力激增。清理缓存并重启元数据服务后存储性能恢复正常训练任务的数据加载速度逐步回升。第二步处理告警风暴本身。所有任务恢复正常后之前触发的告警状态开始陆续变为“已恢复”但由于告警数量庞大我批量执行了一次“确认并关闭”操作把已经恢复的告警统一归档避免影响后续告警的跟踪。第三步是事后复盘和优化。这次事件暴露了两个问题一是告警规则之间缺乏依赖关系数据加载慢引发的各类告警被当成独立事件对待二是缺少全局维度的告警收敛。后续我做了两个改进在告警规则里增加关联字段当检测到公共依赖异常时自动抑制上游任务的关联告警另外增加了一个“公共依赖健康”监控项如果共享存储或公共服务的指标异常优先发布一条P0根因告警从源头上收敛噪音。6.3 这次复盘带来的规则优化这次事件之后我对告警规则做了一次系统性的重新梳理。核心原则变成了三条第一每条告警规则都必须写明“可能导致该告警的根因有哪些”如果根因已经在其他告警中出现就做抑制关联第二新增告警规则必须经过“噪音评估”预估在异常场景下可能产生的告警数量如果超过预期就要配套聚合策略第三每季度做一次告警规则的“翻新”删除不再适用的规则调整阈值和级别。这套优化策略在后来的工作中持续发挥作用。平台上的告警数量保持了稳定可控没有再出现过一次事件刷屏几百条的情况。更关键的是团队对告警的信任度提升了每条告警发出来都会有人认真看因为大家知道发出来的都是需要人关注的。7. 常见问题与排查技巧实录7.1 告警体系落地中的高频问题速查表问题现象可能原因排查思路与解法告警风暴刷屏缺少聚合和抑制规则故障波及多个任务时各自上报配置时间聚合和空间聚合设置根因告警后自动抑制关联告警告警重复发送告警评估周期过短同一状态在恢复前被反复触发评估周期改为1分钟以上或设置相同告警的最小重复间隔告警发出但没人处理缺少升级机制告警发出后状态无人跟踪配置告警确认超时升级P0告警5分钟未确认自动升级训练任务OOM被杀但无告警显存类指标未接入或阈值设置不合理使用DCGM的FB_USED指标设置警戒阈值如80%和紧急阈值如90%告警触发但不准确阈值设定依赖平均值任务波动大时难以精准判定使用百分位数指标P95/P99或引入动态阈值机制自愈类告警过多系统有自动恢复机制告警发出时问题已解决增加持续时间窗口如持续5分钟才触发减少瞬时抖动告警自定义指标采集不到训练任务在Kubernetes中运行Pod IP变化导致拉取失败使用Prometheus的服务发现机制或改用PushGateway方式上报7.2 我在实操中踩过的一些坑和心得第一个坑与阈值有关。最开始我把GPU利用率低于10%的告警阈值设在5分钟持续窗口结果大量短暂的数据加载间隙频繁触发告警晚上值班的人被骚扰到崩溃。后来我把窗口调到了15分钟同时把“算力浪费率”作为辅助判定条件只有在GPU利用率低且浪费率超过20%时才告警误报率大幅下降。阈值这个东西不能拍脑袋定要看真实数据的分布跑一段时间拿到基线数据后再调整。第二个坑是告警与自动恢复机制打架。平台上的训练任务挂了会自动重启重启之后再跑但重启过程中触发的告警仍然会发出来。有一次某个服务的自动重启机制连续触发告警也连续发了十几次值班同学被折腾够呛。后来我在告警规则里加上“持续状态确认”只有状态持续异常超过一定时间才告警短暂的重启中断不再骚扰人。第三个心得是告警规则的代码化管理。所有告警规则我都用YAML写存到Git仓库里走代码评审流程后合入。这样做的好处是每次变更都有记录出了问题可以快速回滚。有一次运营同学想调整某条规则直接在告警平台界面改动结果语法写错导致规则加载失败监控断了好几个小时。从那以后我直接把告警平台界面改规则的权限关掉了只允许通过Git仓库修改。第四个心得是关注“告警覆盖率”这个概念。所谓覆盖率就是“发生了故障系统能发现多少”。有些故障类型根本没有对应的告警规则出了问题只能靠用户反馈才知道。我每隔一段时间就会问自己最近一次故障是什么原因当时有没有告警如果没有是否缺少某类监控规则不断从实际故障反推监控盲区比从规则出发正向推演有效得多。7.3 平台规模扩大后监控告警如何演进平台规模从几十个任务增长到几百个任务监控告警体系同样需要演进。采集层要注意抓取性能Prometheus拉取频次和任务数量是线性关系任务多了以后需要做分片或者用VictoriaMetrics这类高性能时序数据库替代。告警规则层面规则数量增加后需要做分类管理我按业务域和告警类型给规则打标签方便批量维护。告警治理方面规模大了以后建议引入SLO服务等级目标的概念。不追求所有指标都完美而是定义核心服务的可用性目标比如“推理服务月度可用性99.9%”“训练任务平均失败率低于1%”监控体系围绕SLO来设计告警而不是眉毛胡子一把抓。这样告警的数量天然就会收敛因为很多非关键的异常都被排除在SLO范围之外。我个人在经历了多次告警风暴、多次因为监控盲区导致故障被动发现的教训后最大的体会是监控告警系统的本质不是“技术问题”而是“管理问题”。技术架构选型只是起点更重要的是持续的规则治理、团队协作机制和复盘文化。一个能长期稳定运行的告警体系背后一定有一支重视稳定性、愿意为可观测性投入的团队。这套体系随着平台规模和数据积累会不断迭代没有终点但每迭代一次平台运行的确定性就增加一分。
返回列表