计量计费与资源账单
简介
计量计费用于完整记录平台所有用户在任何时间、任何场景下使用的 Pod 所占用的资源信息,并据此核算成本。
实现代码
监听采集进程:
myapp/tools/watch_pod.py。该进程运行在infra命名空间下的kubeflow-watchDeployment(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:947与install/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_FUN 的 pod 对象包含如下字段(可据此自定义计价逻辑),示例(通过 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-运维管理」的配置文件管理。