如何定义 vGPU(Hami) 成本模型

前提条件

在 GPU 集群中:

  • 已安装 Alauda Build of Hami
  • 已安装成本管理智能体

关于 Alauda Build of Hami

Heterogeneous AI Computing Virtualization Middleware (HAMi),前身为 k8s-vGPU-scheduler,是一个用于在 k8s 集群中管理 Heterogeneous AI Computing Devices 的 "all-in-one" chart。它可以提供在任务之间共享 Heterogeneous AI 设备的能力。

Note
因为 Alauda Build of Hami 的发版周期与灵雀云容器平台不同,所以 Alauda Build of Hami 的文档现在作为独立的文档站点托管在 Alauda Build of Hami

操作步骤

创建 PrometheusRule 以生成所需指标

在 Hami 集群中创建一个 PrometheusRule。

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    prometheus: kube-prometheus
  name: hami-gpu-labels
  namespace: kube-system
spec:
  groups:
    - name: hami-gpu-labels.rules
      rules:
        - expr: |
            min by (podnamespace, deviceuuid, label_modelName, label_device) (
              vGPUCorePercentage
              * on (deviceuuid) group_left(label_modelName, label_device) (
                label_replace(
                  label_replace(
                    label_replace(
                      DCGM_FI_DEV_SM_CLOCK,
                      "deviceuuid", "$1", "UUID", "(.*)"
                    ),
                    "label_modelName", "$1", "modelName", "(.*)"
                  ),
                  "label_device", "$1", "device", "([a-zA-Z]+)[0-9]+$"
                )
              )
            )
          record: vgpu_core_labels

添加采集配置(成本管理智能体)

在运行成本管理智能体的 Hami 集群中创建一些 ConfigMap,以声明需要采集的内容。

注意:项目配额的 configmap 仅在 hami 2.7+ 中受支持

apiVersion: v1
data:
  config: >
    - kind: vGPU
      category: vGPUCore
      item: vGPUCoreQuota
      period: Hourly
      labels:
        query: "vgpu_core_labels{}"
        mappers:
          name: deviceuuid
          namespace: podnamespace
          cluster: ""
          project: ""
      usage:
        query: sum by (deviceuuid,podnamespace) (avg_over_time(vGPUCorePercentage{}[5m]))
        step: 5m
        mappers:
          name: deviceuuid
          namespace: podnamespace
          cluster: ""
          project: ""
    - kind: vGPU
      category: vGPUMemory
      item: vGPURamBytesQuota
      period: Hourly
      labels:
        query: "vgpu_core_labels{}"
        mappers:
          name: deviceuuid
          namespace: podnamespace
          cluster: ""
          project: ""
      usage:
        query: sum by (deviceuuid,podnamespace) (avg_over_time(vGPU_device_memory_limit_in_bytes{}[5m]))
        step: 5m
        mappers:
          name: deviceuuid
          namespace: podnamespace
          cluster: ""
          project: ""
    - kind: vGPU
      category: vGPUCore
      item: vGPUCoreUsed
      period: Hourly
      labels:
        query: "vgpu_core_labels{}"
        mappers:
          name: deviceuuid
          namespace: podnamespace
          cluster: ""
          project: ""
      usage:
        query: sum by (deviceuuid,podnamespace) (avg_over_time(Device_utilization_desc_of_container{}[5m]))
        step: 5m
        mappers:
          name: deviceuuid
          namespace: podnamespace
          cluster: ""
          project: ""
    - kind: vGPU
      category: vGPUMemory
      item: vGPURamBytesUsed
      period: Hourly
      labels:
        query: "vgpu_core_labels{}"
        mappers:
          name: deviceuuid
          namespace: podnamespace
          cluster: ""
          project: ""
      usage:
        query: sum by (deviceuuid,podnamespace) (avg_over_time(vGPU_device_memory_usage_in_bytes{}[5m]))
        step: 5m
        mappers:
          name: deviceuuid
          namespace: podnamespace
          cluster: ""
          project: ""
kind: ConfigMap
metadata:
  labels:
    cpaas.io/slark.collection.config: "true"
  name: slark-agent-vgpu-namespace-config
  namespace: cpaas-system
---
# Note: The following configmap is only supported in hami 2.7+
apiVersion: v1
data:
  config: >
    - kind: Project
      category: vGPUCore
      item: vGPUCoresProjectQuota
      period: Hourly
      usage:
        query: avg by (project, cluster) (avg_over_time(cpaas_project_resourcequota{resource="limits.nvidia.com/gpucores", type="project-hard"}[5m]))
        step: 5m
        mappers:
          name: project
          namespace: ""
          cluster: cluster
          project: project
    - kind: Project
      category: vGPUMemory
      item: vGPURamBytesProjectQuota
      period: Hourly
      usage:
        query: avg by (project, cluster) (avg_over_time(cpaas_project_resourcequota{resource="limits.nvidia.com/gpumem", type="project-hard"}[5m]))
        step: 5m
        mappers:
          name: project
          namespace: ""
          cluster: cluster
          project: project
kind: ConfigMap
metadata:
  labels:
    cpaas.io/slark.collection.config: "true"
  name: slark-agent-project-config-vgpu
  namespace: cpaas-system

添加 yaml 后,需要重启智能体 Pod 以重新加载配置。

kubectl delete pods -n cpaas-system -l service_name=slark-agent

添加显示/存储配置(成本管理服务端)

在运行成本管理服务端的集群中创建一个 ConfigMap,用于声明计费项、计费方式、单位和显示名称。这会告诉服务端需要计费的内容以及计费方式。

注意: 如果没有启用 GPU Overcommitment Ratio,使用 Request Usage 没有意义。如果你使用 Request Usage,请先启用 GPU Overcommitment Ratio。

apiVersion: v1
data:
  config: |
    - name: vGPUCore
      displayname:
        zh: "HAMi NVIDIA vGPU Cores"
        en: "HAMi NVIDIA vGPU Cores"
      methods:
        - name: Request
          displayname:
            zh: "请求量"
            en: "Request Usage"
          item: vGPUCoreQuota
          divisor: 1
          unit:
            zh: "core-hours"
            en: "core-hours"
        - name: Usage
          displayname:
            zh: "使用量"
            en: "Used Usage"
          item: vGPUCoreUsed
          divisor: 1
          unit:
            zh: "core-hours"
            en: "core-hours"
        - name: ProjectQuota
          displayname:
            zh: "项目配额"
            en: "Project Quota"
          item: vGPUCoresProjectQuota
          unit:
            zh: "core-hours"
            en: "core-hours"
          divisor: 1
    - name: vGPUMemory
      displayname:
        zh: "HAMi NVIDIA vGPU Memory"
        en: "HAMi NVIDIA vGPU Memory"
      methods:
        - name: Request
          displayname:
            zh: "请求量"
            en: "Request Usage"
          item: vGPURamBytesQuota
          divisor: 1073741824
          unit:
            zh: "Gi-hours"
            en: "Gi-hours"
        - name: Used
          displayname:
            zh: "使用量"
            en: "Used Usage"
          item: vGPURamBytesUsed
          divisor: 1073741824
          unit:
            zh: "Gi-hours"
            en: "Gi-hours"
        - name: ProjectQuota
          displayname:
            zh: "项目配额"
            en: "Project Quota"
          item: vGPURamBytesProjectQuota
          unit:
            zh: "Gi-hours"
            en: "Gi-hours"
          divisor: 1024 # Mi/1024
kind: ConfigMap
metadata:
  labels:
    cpaas.io/slark.display.config: "true"
  name: slark-display-config-for-vgpu
  namespace: kube-public

添加 yaml 后,需要重启服务端 Pod 以重新加载配置。

kubectl delete pods -n cpaas-system -l service_name=slark-server

为 vGPU 成本模型添加价格

如果 GPU 集群没有 Cost model,你需要先创建一个新的 cost model。然后就可以为 GPU 集群的 cost model 添加价格:

计费方式说明

计费项计费方式计费规则说明
vGPUUsage (Core-hours)按小时计算,使用 Pod 在过去一小时内的 AVG(Usage),并乘以 Pod 的实际持续时间(不足 5 分钟按 5 分钟计)。基于实际 vGPU 消耗
vGPURequest (Core-hours)按小时计算,使用 Pod 在过去一小时内的 Request,并乘以 Pod 的实际持续时间(不足 5 分钟按 5 分钟计)。基于 vGPU 资源请求
vGPUProject Quota (Core-hours)按小时计算,使用项目分配的 CPU 配额上限,并乘以时间长度。配额变更时按分段计算。基于项目级资源配额
vGPUMemoryUsage (GiB-hours)按小时计算,使用 Pod 在过去一小时内的 AVG(Usage),并乘以 Pod 的实际持续时间(不足 5 分钟按 5 分钟计)。基于实际 vGPU 内存消耗
vGPUMemoryRequest (GiB-hours)按小时计算,使用 Pod 在过去一小时内的 Request,并乘以 Pod 的实际持续时间(不足 5 分钟按 5 分钟计)。基于 vGPU 内存资源请求
vGPUMemoryProject Quota (GiB-hours)按小时计算,使用项目分配的内存配额上限,并乘以时间长度。配额变更时按分段计算。基于项目级资源配额

为成本模型添加价格

  1. Billing Items 中选择 vGPUvGPUMemory

  2. Method 中选择 Request Usage (core-hours)Used Usage (core-hours)Project Quota (core-hours)

  3. 设置 Default Price

  4. 配置 Price By Label(可选)。 目前仅支持两个键:modelNamedevice

    modelName:GPU 型号,例如 "Tesla P100-PCIE-16GB" 或 "Tesla T4"(可通过运行 nvidia-smi 获取)。

    device:GPU 厂商,例如 "nvidia" 或 "ascend"。

成本详情和成本统计

最后,等待 1 个或多个小时后,你可以在 Cost Details 中按 namespace 和 card uuid 维度查看成本详情。 你还可以在 Cost Statistics 中查看基于 cluster、project 和 namespace 的总成本。