3、资源评估指标体系:定义核心指标,建立评估模型

说实话,做资源回收这件事,最怕的就是「拍脑袋」。

我刚接手数据平台那会儿,领导问我:「咱们集群资源利用率怎么样?」我支支吾吾答不上来。后来花了一周时间,把监控数据拉出来一看——好家伙,有些队列 CPU 跑到了 90%,有些队列连 10% 都不到。但你要说哪个是浪费,哪个是合理,没有一套指标,根本说不清楚。

所以这一章,咱们就把「怎么衡量资源」这件事彻底讲透。

3.1 三个核心指标:利用率、闲置率、浪费率

我个人习惯,把资源评估拆成三个维度。你想想看,一台服务器、一个队列、一个任务,无非就三种状态:在用、空转、被浪费。

指标 定义 计算公式 说明
资源利用率 实际被有效使用的资源占比 实际使用量 / 总量 × 100% 越高越好,但需留缓冲
资源闲置率 完全未被使用的资源占比 闲置量 / 总量 × 100% 越低越好,但需考虑弹性
资源浪费率 被占用但未产生价值的资源占比 浪费量 / 总量 × 100% 越低越好,这是回收重点

关键区别:闲置 ≠ 浪费。闲置是「没人用」,浪费是「有人占着但不用」。我见过太多团队把闲置当浪费处理,结果把弹性 buffer 全砍了,业务一波动就崩。

3.2 细化指标:从集群到任务

光有上面三个宏观指标还不够。你得能下钻到具体维度。我一般按四个层级来拆:

3.2.1 集群级指标

  • 集群整体利用率:所有节点 CPU/内存/磁盘的加权平均
  • 节点碎片率:单节点利用率低于 20% 的节点占比
  • 集群扩缩容比:实际节点数 / 需求节点数

3.2.2 队列级指标

  • 队列资源饱和度:已分配资源 / 队列总资源
  • 队列等待深度:排队任务数 / 运行任务数
  • 队列资源碎片率:队列内各任务资源需求不匹配导致的浪费

3.2.3 任务级指标

  • 任务资源偏差率:申请资源 / 实际使用资源
  • 任务空转时间比:任务无计算时间 / 总运行时间
  • 任务超配率:申请资源超过实际峰值使用量的比例

3.2.4 用户级指标

  • 用户资源滥用指数:该用户所有任务的超配率加权平均
  • 用户闲置任务占比:该用户超过 7 天未运行的任务数 / 总任务数

我的经验:任务级指标最容易出问题。我曾经发现一个 Spark 任务申请了 200 个 executor,实际只用到了 30 个。这种超配在 YARN 上太常见了,但如果不算「浪费率」,你根本不会注意到。

3.3 建立评估模型:从指标到决策

指标有了,怎么用?我设计了一个三层评估模型,你可以直接套用。

资源评估三层模型 第一层:数据采集层 集群监控(Ganglia/Prometheus) 调度器日志(YARN/K8s API) 任务历史(Spark History / Hive Metastore) 第二层:指标计算层 集群级 → 利用率 / 闲置率 / 碎片率 队列级 → 饱和度 / 等待深度 / 碎片率 任务级 → 偏差率 / 空转比 / 超配率 第三层:评估决策层 阈值判定 → 正常 / 预警 / 回收 回收优先级排序 → 按浪费率从高到低 自动回收 / 人工审批 / 通知用户 数据采集 → 指标计算 → 评估决策,形成闭环

3.4 阈值设定:多少算「浪费」?

这是最头疼的问题。我踩过坑,分享几个经验值:

指标 健康区间 预警阈值 回收阈值
集群 CPU 利用率 60% - 80% < 40% 或 > 90% < 20% 持续 7 天
集群内存利用率 65% - 85% < 45% 或 > 92% < 25% 持续 7 天
任务资源偏差率 1.0 - 1.5 1.5 - 3.0 > 3.0
队列等待深度 < 2 2 - 5 > 5
用户闲置任务占比 < 10% 10% - 30% > 30%

注意:阈值不是死的。我曾经在一个离线数仓集群把 CPU 利用率回收阈值设成 20%,结果月底跑批任务一来,集群直接被打满。后来我改成「持续 7 天低于阈值才触发回收」,加了时间窗口,才稳下来。

3.5 实战:用 Python 实现指标计算

光说不练假把式。我写了个简单的指标计算脚本,你可以直接改改用:

import pandas as pd
import numpy as np

def calc_resource_metrics(df):
    """
    df 字段:task_id, user, queue, cpu_request, cpu_used, mem_request, mem_used, duration, status
    """
    # 任务级指标
    df['cpu_deviation'] = df['cpu_request'] / df['cpu_used']
    df['mem_deviation'] = df['mem_request'] / df['mem_used']
    df['overprovision_rate'] = (df['cpu_request'] - df['cpu_used']) / df['cpu_request']

    # 队列级指标
    queue_metrics = df.groupby('queue').agg(
        total_cpu_request=('cpu_request', 'sum'),
        total_cpu_used=('cpu_used', 'sum'),
        task_count=('task_id', 'count'),
        avg_deviation=('cpu_deviation', 'mean')
    ).reset_index()
    queue_metrics['queue_utilization'] = queue_metrics['total_cpu_used'] / queue_metrics['total_cpu_request']

    # 用户级指标
    user_metrics = df.groupby('user').agg(
        total_tasks=('task_id', 'count'),
        avg_overprovision=('overprovision_rate', 'mean'),
        idle_tasks=('status', lambda x: (x == 'IDLE').sum())
    ).reset_index()
    user_metrics['idle_ratio'] = user_metrics['idle_tasks'] / user_metrics['total_tasks']

    return queue_metrics, user_metrics

# 使用示例
# queue_metrics, user_metrics = calc_resource_metrics(your_dataframe)
# print(queue_metrics[queue_metrics['queue_utilization'] < 0.3])  # 找出利用率低于30%的队列

避坑指南:计算偏差率时,注意分母不能为 0。我遇到过有些任务申请了资源但实际使用量为 0,这种情况直接标记为「异常任务」,单独处理。

3.6 建立评估报告:让数据说话

指标算出来了,怎么呈现给团队和领导?我习惯每周出一份资源评估报告,包含以下内容:

  1. 集群健康总览:一张热力图,展示各队列的利用率、闲置率、浪费率
  2. Top 10 浪费任务:按浪费率排序,列出任务名、用户、申请资源、实际使用
  3. Top 5 浪费用户:按用户资源滥用指数排序,附上该用户的任务明细
  4. 回收建议清单:明确哪些资源可以回收,回收后预计节省多少成本
  5. 趋势对比:与上周数据对比,看回收效果

嗯,这套指标体系我用了三年,迭代了十几个版本。从最初只看 CPU 利用率,到后来能精确到每个任务的浪费率,每一步都是踩坑踩出来的。你照着这个框架搭,至少能少走一半弯路。