饮墨

子安饮墨馀三斗,留与卿儿作赋来

OpenCost 实战:Kubernetes 集群成本可视化与优化指南

痛点

Kubernetes 集群规模一上来,成本就成了黑洞。常见问题:

  • 无法归因:每月云账单一大坨,根本分不清哪个团队、哪个 Namespace、哪个 Pod 在烧钱
  • 资源浪费严重:开发者 request 设 4C8G,实际用了 0.5C1G,节点利用率不到 30%
  • Showback/Chargeback 无数据支撑:财务要求按部门分摊成本,运维拿不出精确数据
  • 商业方案太贵:Kubecost Enterprise 动辄几万美金/年,中小团队承受不起

OpenCost 是 CNCF 孵化的开源 Kubernetes 成本监控项目(Kubecost 开源核心),能以 Pod 粒度实时计算成本分摊,且完全免费。


方案概述

OpenCost 通过以下机制实现成本可视化:

  1. 实时资源计量:采集每个 Pod 的 CPU/Memory/GPU/Storage/Network 实际用量
  2. 云定价 API 集成:自动拉取 AWS/GCP/Azure 的按需定价(支持 Spot/RI/Savings Plans)
  3. 成本分配模型:按 Namespace、Label、Controller 等维度归因,支持闲置成本再分配
  4. Prometheus 集成:原生暴露 metrics,可直接对接 Grafana 构建成本大盘

架构图:

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│  Kubernetes  │────▶│   OpenCost   │────▶│  Prometheus  │
│  API Server  │     │   (Pod)      │     │              │
└──────────────┘     └──────────────┘     └──────────────┘
                            │                      │
                            ▼                      ▼
                     ┌──────────────┐     ┌──────────────┐
                     │  Cloud Cost  │     │   Grafana    │
                     │  API (AWS等) │     │   Dashboard  │
                     └──────────────┘     └──────────────┘

实操步骤

Step 1:Helm 部署 OpenCost

前置条件:集群已安装 Prometheus(kube-prometheus-stack 或独立部署均可)。

# 添加 Helm repo
helm repo add opencost https://opencost.github.io/opencost-helm-chart
helm repo update

# 部署 OpenCost
helm install opencost opencost/opencost \
  --namespace opencost --create-namespace \
  --set opencost.prometheus.internal.serviceName=prometheus-kube-prometheus-prometheus \
  --set opencost.prometheus.internal.namespaceName=monitoring \
  --set opencost.ui.enabled=true

关键参数说明: - prometheus.internal.serviceName:指向你集群中 Prometheus 的 Service 名称 - prometheus.internal.namespaceName:Prometheus 所在 Namespace - ui.enabled=true:启用内置 Web UI,方便快速查看

验证部署:

kubectl get pods -n opencost
# NAME                        READY   STATUS    RESTARTS   AGE
# opencost-6f8d7b9c4d-x2k9j  2/2     Running   0          60s

Step 2:配置 AWS 自定义定价(可选但推荐)

默认使用公开按需定价。如果用了 RI 或 Savings Plans,需配置 CUR(Cost and Usage Report)集成:

# values-aws.yaml
opencost:
  cloudCost:
    enabled: true
  exporter:
    cloudProviderApiKey: ""
    aws:
      secret_access_key: ""  # 建议用 IRSA
      access_key_id: ""
  customPricing:
    enabled: true
    configmapName: opencost-custom-pricing
    provider: aws

使用 IRSA(推荐生产环境):

# 创建 IAM 策略
cat > opencost-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "cur:DescribeReportDefinitions",
        "cur:GetReportData",
        "pricing:GetProducts",
        "ec2:DescribeInstances",
        "ec2:DescribeSpotPriceHistory"
      ],
      "Resource": "*"
    }
  ]
}
EOF

aws iam create-policy --policy-name OpenCostPolicy \
  --policy-document file://opencost-policy.json

# 绑定 IRSA
eksctl create iamserviceaccount \
  --name opencost \
  --namespace opencost \
  --cluster your-cluster \
  --attach-policy-arn arn:aws:iam::123456789:policy/OpenCostPolicy \
  --approve

Step 3:Grafana 成本大盘

OpenCost 暴露的核心 Prometheus 指标:

指标 说明
opencost_pod_cpu_cost Pod CPU 成本($/h)
opencost_pod_memory_cost Pod 内存成本($/h)
opencost_pod_network_cost Pod 网络成本($/h)
opencost_namespace_cpu_cost Namespace 维度 CPU 成本
opencost_cluster_cost_total 集群总成本

Grafana 面板 PromQL 示例 — 按 Namespace 统计日成本 Top10:

topk(10,
  sum by (namespace) (
    opencost_pod_cpu_cost + opencost_pod_memory_cost
  ) * 24
)

按 Deployment 统计月度成本:

sum by (controller, namespace) (
  (opencost_pod_cpu_cost + opencost_pod_memory_cost + opencost_pod_network_cost) * 720
)

导入社区 Dashboard:Grafana Dashboard ID 18867(OpenCost 官方大盘)。

Step 4:基于成本数据的优化动作

拿到成本数据后,常见优化动作:

# 1. 找出资源严重超配的 Pod(request >> actual)
kubectl top pods -A --sort-by=cpu | head -20

# 2. 通过 OpenCost API 查询过去 7 天 Namespace 成本
curl -s "http://opencost.opencost:9003/allocation/compute?window=7d&aggregate=namespace" | \
  jq '.data[] | to_entries[] | {namespace: .key, totalCost: .value.totalCost}' | \
  jq -s 'sort_by(-.totalCost) | .[:10]'

# 3. 识别闲置资源(CPU利用率低于 10% 超过 7 天的 Deployment)
# 配合 VPA recommender 调整 request
kubectl get vpa -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}: CPU={.status.recommendation.containerRecommendations[0].target.cpu}, Mem={.status.recommendation.containerRecommendations[0].target.memory}{"\n"}{end}'

避坑指南

1. Prometheus 数据保留期不够导致月度统计失真

问题:默认 Prometheus 保留 15 天,OpenCost 月度成本统计不完整。

解决

# kube-prometheus-stack values
prometheus:
  prometheusSpec:
    retention: 32d
    # 或者使用 Thanos/Mimir 做长期存储

2. 节点 Spot 实例价格波动大导致成本数据不准

问题:Spot 实例价格每分钟变化,OpenCost 默认拉取频率可能跟不上。

解决:在 Helm values 中调整刷新频率:

opencost:
  exporter:
    aws:
      spotDataRegion: us-east-1
      spotDataBucket: your-spot-feed-bucket  # 配置 Spot Data Feed
      spotRefreshRate: 3600  # 秒

3. Shared Resources(Prometheus、Istio)成本分配争议

问题:基础设施组件(监控、Service Mesh、Ingress Controller)归属哪个团队?

解决:OpenCost 支持 idle costshared cost 配置:

# 将共享成本按比例分配给所有 Namespace
opencost:
  exporter:
    defaultIdleCost: "allocated"  # 闲置成本按使用量比例分配
    sharedNamespaces: "monitoring,istio-system,kube-system"
    shareStrategy: "weighted"  # 按 CPU/Mem 实际使用量加权

总结

维度 说明
部署成本 零成本,CNCF 开源项目
部署复杂度 Helm 一键装,5 分钟上线
精度 Pod 级别实时成本,支持 CPU/Mem/GPU/Network/PV
云厂商支持 AWS、GCP、Azure、自建(Custom Pricing CSV)
适用规模 10~1000+ 节点均可,资源占用极低(~50MB 内存)
对比 Kubecost Enterprise 功能覆盖 80%,适合中小团队 Showback 场景

核心建议

  1. 先部署再说:5 分钟部署,立刻看到成本分布,很多浪费一目了然
  2. 配合 VPA 使用:OpenCost 发现浪费 → VPA 自动调整 Request → 节点数自然下降
  3. 设置成本告警:当某 Namespace 日成本超阈值,通过 Alertmanager 通知团队
  4. 按月生成 Chargeback 报告:通过 OpenCost API 导出数据,自动化生成分摊报表

在我的实际经验中,仅通过 OpenCost 发现超配 + VPA 自动调整这一组合拳,就在 200 节点的 EKS 集群上实现了约 25% 的成本削减。关键不在工具,在于让成本对每个团队透明可见 — 当开发者知道自己的服务每月烧了多少钱,行为自然会改变。

您还没有登录,请登录后发表评论。