集群资源管理:Slurm、Kubernetes等集群资源调度系统的监控与运维
在AI算力集群中,资源调度系统是连接物理硬件与上层业务负载的“操作系统”。无论是面向HPC/科学计算场景的Slurm,还是面向云原生/微服务场景的Kubernetes,调度器都承担着资源抽象、分配、隔离与回收的核心职责。监控与运维调度系统,本质上是在回答三个问题:资源被谁占用?调度决策是否合理?系统本身是否健康?本章围绕这两个主流调度器,梳理监控指标体系、运维方法及常见故障模式。
4.1 调度系统监控的核心原理
调度系统的监控不同于普通应用监控,其核心难点在于“资源视图”与“作业视图”的双重维度。资源视图关注节点、GPU、内存、网络带宽等物理资源的实时水位;作业视图关注作业/容器的排队、运行、终止状态及资源申请量。两者必须关联分析,才能定位“资源充足但作业无法调度”或“作业运行缓慢但节点负载不高”等复杂问题。
以Slurm为例,其监控数据源主要来自三个层面:
- slurmctld:控制守护进程,维护作业队列、节点状态、分区配置,是调度决策的核心,其日志与状态是监控重点。
- slurmd:计算节点上的代理进程,负责执行作业启动、资源隔离与状态上报。
- 外部导出器:如Prometheus的slurm-exporter,通过调用
sacct、sinfo、squeue等命令或直接读取Slurm数据库,将指标转换为时序数据。
Kubernetes的监控架构则更为分层:kubelet负责节点与Pod的资源上报,kube-scheduler负责Pod的调度决策,etcd存储集群状态,而kube-apiserver是所有交互的入口。监控数据通常通过Metrics API、Prometheus适配器或cAdvisor采集。
关键监控指标分类(以Slurm为例)
| 维度 | 指标示例 | 监控意义 |
|---|---|---|
| 集群资源 | 节点总数/空闲/宕机/排空(Drain) | 判断集群可用容量与故障节点比例 |
| 作业状态 | 排队作业数、运行作业数、作业等待时间 | 评估调度效率与队列积压程度 |
| 资源利用率 | GPU利用率、显存占用、CPU负载、内存余量 | 识别资源碎片化或热点节点 |
| 调度器健康 | slurmctld响应延迟、数据库连接数、RPC调用量 | 发现控制平面瓶颈或异常 |
| 作业失败率 | 作业退出码分布、超时作业数、被抢占作业数 | 反映作业本身或资源分配策略问题 |
4.2 监控与运维方法流程
建立调度系统监控体系应遵循“先核心后外围、先指标后日志、先告警后分析”的路径。推荐以下实施流程:
- 梳理调度链路:明确作业从提交到运行的完整路径(如Slurm:
sbatch→ 队列 → 调度决策 → 节点分配 → 作业启动),确定每个环节的监控触点。 - 部署指标采集:使用Prometheus + Grafana作为基础监控栈。Slurm侧部署slurm-exporter,Kubernetes侧部署kube-state-metrics与node-exporter。确保采集频率不低于15秒,避免错过短时资源尖峰。
- 建立关联视图:将调度器指标与硬件指标(如GPU温度、功耗)关联。例如,当GPU利用率低于30%但显存占用超过80%时,可能提示显存瓶颈或数据加载阻塞。
- 配置分层告警:告警规则应区分紧急与警告。紧急级别包括:节点宕机超过阈值、调度器进程异常退出、作业排队时间超过预期;警告级别包括:GPU利用率持续低于10%、节点内存碎片化严重、作业失败率突增。
- 日志集中管理:将slurmctld日志、kube-scheduler日志、kubelet日志统一接入ELK或Loki。日志中应包含作业ID、节点名、用户信息等上下文,便于排障时快速关联。
对于Kubernetes集群,还需额外关注调度器扩展点的监控。如果使用了自定义调度器或调度插件,必须监控其打分、过滤、抢占等环节的耗时与失败次数,否则调度异常可能被默认指标掩盖。
4.3 典型场景:Slurm集群GPU资源碎片化
某AI训练集群共64个节点,每节点8张A100 GPU。运维人员发现集群整体GPU利用率仅为45%,但作业排队时间持续增长。初步排查时,节点负载显示大部分节点GPU利用率在20%-60%之间波动,并未出现明显热点。
进一步分析squeue输出与sacct记录后发现:
# 查看排队作业的资源申请
squeue -u train_user -o "%.10i %.20j %.8T %.10M %.6D %R"
# 输出显示大量作业申请4卡或8卡,但空闲节点多为2卡或6卡碎片
根因是资源碎片化:调度器默认按整节点分配,但部分作业因数据并行规模较小只申请2卡,导致节点上剩余6卡无法被后续8卡作业使用。同时,节点排空(Drain)策略过于保守,部分节点因偶发ECC错误被标记为Drain,但未及时恢复。
解决方案分三步实施:
- 启用GPU细粒度分配:在slurm.conf中配置
GresTypes=gpu并允许SelectTypeParameters=CR_Core_Memory,使调度器支持按卡分配,而非整节点独占。 - 优化排空策略:设置
DrainWaitTime=300,并配置健康检查脚本自动恢复因瞬时错误被Drain的节点。 - 建立碎片率指标:在Grafana中新增“节点GPU碎片率”面板,计算公式为
1 - (可分配最大连续卡数 / 节点总卡数),当碎片率超过50%时触发告警。
实施后两周内,集群整体GPU利用率提升至68%,排队时间下降40%。该案例说明,调度器监控不能只看平均利用率,必须结合作业申请粒度与节点空闲拓扑进行联合分析。
4.4 Kubernetes调度运维的特殊性
Kubernetes调度器(kube-scheduler)的监控重点与Slurm有显著差异。由于Pod生命周期短、副本数动态变化,监控必须关注调度时延与调度失败原因。常见问题包括:
- 资源请求与限制设置不当:大量Pod设置了过高的
requests但实际使用率低,导致节点资源被“预留”而无法调度新Pod。此时应监控kube_pod_container_resource_requests与kube_pod_container_resource_usage的比值,识别超卖或浪费。 - 节点亲和性/反亲和性冲突:复杂的亲和性规则可能导致调度器无法找到满足条件的节点。监控
schedule_attempts_total与schedule_failures_total,并结合调度器日志中的FailedScheduling事件定位具体约束。 - 抢占(Preemption)频繁:当高优先级Pod无法调度时,会抢占低优先级Pod。频繁抢占说明集群资源长期紧张,且优先级策略可能不合理。监控
preemption_attempts_total与受害Pod数量。
对于GPU资源,Kubernetes通常通过Device Plugin框架管理。运维人员需监控nvidia_device_plugin的健康状态、GPU显存分配情况,以及nvidia-smi暴露的GPU利用率。特别注意:Kubernetes不感知GPU利用率,只感知显存分配。因此,即使GPU计算利用率接近0%,只要显存被分配,Pod就不会被重新调度,这可能导致GPU算力闲置。
4.5 常见误区与复盘
误区一:只监控调度器自身,忽略调度策略的影响
调度器进程健康不代表调度决策合理。例如,Slurm的PriorityType配置不当可能导致低优先级作业长期饥饿;Kubernetes的默认调度器可能因未启用NodeResourcesFit插件而忽略资源碎片。监控必须包含策略配置的变更审计与调度结果分析。
误区二:告警阈值设置过于静态
集群规模、作业类型会随时间变化。固定“GPU利用率低于50%告警”可能在训练任务高峰期产生大量误报。建议采用动态基线告警,基于历史7天同时间段的数据计算正常波动范围。
复盘案例:某Kubernetes集群频繁出现Pod调度超时,但调度器指标显示schedule_attempts_total正常。深入排查发现,kube-scheduler的--permit-waiting-pods参数未设置,导致部分Pod在等待Permit阶段超时。该问题在默认指标中无法体现,必须结合调度器日志中的WaitingPod事件才能发现。事后团队增加了对调度器日志关键字的实时监控,并配置了schedule_waiting_pods_duration指标。
另一个常见问题是监控数据采集本身成为瓶颈。当集群规模超过500节点时,slurm-exporter频繁调用sinfo命令会产生较大负载。建议将采集频率从15秒调整为30秒,并启用Slurm的SlurmctldParameters=enable_configless以减少控制节点压力。
调度系统的运维最终要回归到业务可用性。建议每周生成调度质量报告,包含:作业平均等待时间、资源利用率分布、调度失败原因TOP5、节点健康趋势。通过持续迭代监控指标与告警策略,使调度系统从“可用”走向“优用”。