计量计费与资源账单

想了解平台如何记录各用户/各场景下 Pod 的资源占用并计费、如何自定义计价函数时读这篇

平台使用 / 计量计费
计量计费计费账单billingmetering资源占用podwatch_podPRICE_FUN价格price成本自定义计价kubeflow-watchsupervisord

计量计费与资源账单

简介

计量计费用于完整记录平台所有用户在任何时间、任何场景下使用的 Pod 所占用的资源信息,并据此核算成本。

实现代码

  • 监听采集进程:myapp/tools/watch_pod.py。该进程运行在 infra 命名空间下的 kubeflow-watch Deployment(Pod)中,通过 supervisord 启动。

    • 容器启动命令为 supervisord -c /home/myapp/myapp/tools/supervisord.conf(见 install/kubernetes/cube/base/deploy-watch.yaml:55)。
    • supervisord.conf 中以 [program:watch-pod] command=python myapp/tools/watch_pod.py 拉起该进程(见 myapp/tools/supervisord.conf:35)。
  • 历史 Pod 信息通过 myapp/views/view_pod.py 实现。

  • Pod 特殊字段通过 myapp/models/model_pod.py 设置(原文笔误 myall,正确为 myapp)。

数据库存储

保存在 kubeflow 数据库的 pod 表中(表名见 myapp/models/model_pod.py:23__tablename__ = 'pod')。

自定义价格信息

myapp/models/model_pod.py 中,Pod.price 属性负责计算单个 Pod 的总价格:先从配置文件读取 PRICE_FUN 函数得到每小时单价,再根据起止时间计算运行时长,折算出该任务的总价格。若配置中没有 PRICE_FUN,或计算异常,则价格为 0。

# 获取总价(myapp/models/model_pod.py:54)
@property
def price(self):
    price_fun = conf.get('PRICE_FUN', None)
    if price_fun:
        try:
            price = price_fun(self)  # 获取每个小时的价格
            end_time = datetime.datetime.strptime(self.end_time, '%Y-%m-%d %H:%M:%S') if self.end_time else datetime.datetime.now()
            start_time = datetime.datetime.strptime(self.start_time, '%Y-%m-%d %H:%M:%S') if self.start_time else datetime.datetime.now()
            duration = (end_time - start_time).total_seconds()
            price = round(duration * price / 3600, 2)  # 单价 × 时长(秒)/3600 = 总价
            return price
        except Exception as e:
            print(e)
    return 0

PRICE_FUN 在配置文件 config.py 中定义,用于返回 Pod 资源的每小时单价。需要自定义价格时,可在配置文件中按集群实际资源单价改写该函数。

说明:原文称“默认函数不存在,所以价格为 0”。当前代码中 config.py 已内置了一个非零的默认 PRICE_FUN(见 myapp/config.py:947install/docker/config.py:947),按 CPU / 内存 / GPU 的资源量计价。已据此更正。

# 自定义任务计价函数(myapp/config.py:947,返回每小时价格)
import pysnooper, datetime, math
# @pysnooper.snoop(watch_explode=('pod'))
def PRICE_FUN(pod):
    resource = json.loads(pod.resource)
    # 每核 cpu 0.075 元/h  每 G 内存 0.035 元/h   gpu v100 16 元/h  T4 9 元/h
    price = 16 * float(resource.get('gpu', 0)) + 0.075 * float(resource.get('cpu', 0)) + 0.035 * float(resource.get('memory', 0))
    return price  # 返回每个小时的价格

传入 PRICE_FUNpod 对象包含如下字段(可据此自定义计价逻辑),示例(通过 pysnooper 打印):

pod.end_time      = '2024-03-03 19:27:39'
pod.host          = '192.168.3.7'
pod.id            = 1
pod.name          = 'admin-098b'
pod.namespace     = 'jupyter'
pod.node_selector = '{"cpu": "true", "notebook": "true", "org": "public"}'
pod.org           = 'public'
pod.pod_type      = 'notebook'
pod.project       = public
pod.project_id    = 1
pod.resource      = '{"memory": 0, "cpu": 0.0}'   # 计价主要依据此字段(含 cpu/memory/gpu)
pod.start_time    = '2024-02-29 20:48:44'
pod.status        = 'Failed'
pod.user          = admin
pod.user_id       = 1

提示:计价单价属于运维侧策略配置,落在配置文件中,相关说明见「04-运维管理」的配置文件管理

最后更新 2026-06-30完整文档以官方仓库为准:GitHub Wiki