OpenCost
随着越来越多的企业和组织开始上云,云上的成本管理 Cost Management 越来越成为人们关注的重点。OpenCost1 是 KubeCost2 的开源版本,并且在最近刚刚加入 CNCF Sandbox3 。本文主要将介绍 OpenCost 的使用,架构和实现。
背景
参见 Cost Management,主要介绍在当前用云模式下成本管理的重要性,以及越来越多的解决方案。
使用
架构
实现
现在最大的问题就是,不知道 KubeCost 怎么算的钱,钱是否准确?
- BaseCPUPrice
- BaseMemoryPrice
- DownloadPricingData
从前端页面展示开始
http://kubecost.test.hulu.com:9090/model/allocation/view?aggregate=team&window=2023-01-08T00%3A00%3A00Z%2C2023-01-15T00%3A00%3A00Z&accumulate=true&shareIdle=false&idle=true&idleByNode=false&shareTenancyCosts=true&shareNamespaces=&shareCost=NaN&shareSplit=weighted&chartType=1&costMetric=1&startIndex=0&maxResults=0&req=1674974173877?req=1674974173877
对应 payload
aggregate: team
window: 2023-01-08T00:00:00Z,2023-01-15T00:00:00Z
accumulate: true
shareIdle: false
idle: true
idleByNode: false
shareTenancyCosts: true
shareNamespaces:
shareCost: NaN
shareSplit: weighted
chartType: 1
costMetric: 1
startIndex: 0
maxResults: 0
req: 1674974173877
Response
|
|
前端请求响应处理: 参数:
- aggregate:聚合类型
- window: 聚合时间窗口
|
|
问题,前端的请求,是怎么传递给后端的 cost-model 的呢?这里 /allocation 处理后,进一步转给了 /allocation/compute ,但是在前端代码里面没有找到 /allocation/compute 的处理逻辑。在 cost-model 里面找到了对应的 webserver handler
https://github.com/opencost/opencost/blob/develop/pkg/costmodel/router.go#L1744
|
|
ComputeAllocationHandler
https://github.com/opencost/opencost/blob/develop/pkg/costmodel/aggregation.go#L2131
主要作用是解析 HTTP 参数,这里有一个核心数据结构 AllocationSet
|
|
以 CPU 为例:
- 对于每一个 Pod
- Spec 中有对应的 CPU Request 和 Limit
- 可以通过 Prometheus 计算出 Pod 实际使用了多少 CPU,以及对应的 CPU 时间
- 如果有一个基本的 CPU Price
- 我们就可以算出 CPU Cost 和对应的 CPU 使用率
- 问题:
- 不同机型的 CPU Price 是相同的吗
- `idle 所耗费的成本是如何计算出来的
__unallocated__怎么计算出来的
|
|
关键计算代码:
|
|
ComputeAllocation
实际计算函数
|
|
同样以 CPU 为例:
|
|
关键指标:
- queryCPUCoresAllocated: container_cpu_allocation
- queryCPURequests: kube_pod_container_resource_requests
- queryCPUUsageAvg: avg(container_cpu_usage_seconds_total)
- queryCPUUsageMax: max(container_cpu_usage_seconds_total)
这些都是可以从 Prometheus 查询到的。
还有一些不常见的指标,比如 LB 相关,这个是怎么来的呢?
|
|
从 Prometheus 查询到这些 metrics 之后,需要通过计算将其转换为我们的 Allocation 数据结构
|
|
具体成本计算
对于每个 Node,都有其独特的价格,这个也是从 Prometheus 查到的
|
|
那么是谁写的呢?OpenCost 会暴露出来对应的 Metrics
https://github.com/opencost/opencost/blob/develop/pkg/costmodel/metrics.go#L139
并且在这里暴露出来: https://github.com/opencost/opencost/blob/develop/pkg/costmodel/metrics.go#L539
具体的计算 CPU/RAM/GPU 等成本的方法:
|
|
|
|
|
|
这个可以通过 AWS Pricing API 计算得到 https://pilotcoresystems.com/insights/how-to-use-aws-price-list-api-examples/ 对应于 OpenCost 的 Code 就是 https://github.com/opencost/opencost/blob/develop/pkg/cloud/awsprovider.go#L762
入口是: https://github.com/opencost/opencost/blob/develop/pkg/cloud/awsprovider.go#L762
基本思路是,可以通过 k8s 获取 Node 相关的 label 信息,包括 region/machine type/CPU count 等,然后通过 AWS Pricing API 下载价格并解析出来。
|
|
AggregateBy
OpenCost 会在 AggregateBy 讲 ComputeAllocation 中计算出来的 Allocation 进行计算,包括 Idle、Unallocated 和各种 label 维度进行聚合
https://github.com/opencost/opencost/blob/develop/pkg/kubecost/allocation.go#L865
Provider
|
|
NodePricing
|
|
PVPricing
NetworkPricing
|
|