4. 部署OpenCost

OpenCost 本身是一个轻量的成本计算与暴露组件,但它并不自带指标存储能力。它依赖 Prometheus 中已有的容器资源指标(CPU、内存、网络、存储等)来推算成本,因此部署 OpenCost 实际上包含两条主线:一条是把 OpenCost 以 Deployment 形式跑起来,另一条是确保它能稳定查询到一个可用的 Prometheus。理解这两条主线的连接关系,是后续所有配置和排错的基础。

下面这张图展示了 OpenCost 部署后的核心数据流:Prometheus 从 kubelet、cAdvisor、kube-state-metrics 采集指标并存储;OpenCost 通过 HTTP 查询 Prometheus 的 /api/v1/query 接口,结合内置的云厂商价格表(或自定义价格配置)计算成本,最终通过自身 /metrics 端点暴露给 Prometheus 或 Grafana 消费。

数据源层 kubelet / cAdvisor 容器 CPU/内存/网络 kube-state-metrics Pod/Node/Deploy 状态 Prometheus TSDB 存储 + 查询 API /api/v1/query scrape OpenCost 成本计算引擎 价格表 + 资源用量 /metrics 端点 :9003 query Grafana 成本看板 Prometheus 二次抓取 关键依赖关系 OpenCost 必须能访问 Prometheus 的查询 API,地址由 OPENCost_PROMETHEUS_URL 指定 Prometheus 需保留至少 7 天指标,否则成本趋势图会出现断点 kube-state-metrics 提供 Pod 归属信息,缺失会导致成本无法按 Namespace/Deployment 聚合 OpenCost 自身暴露的 /metrics 可被 Prometheus 再次抓取,形成成本指标闭环

Helm 安装:从仓库到运行

OpenCost 官方推荐使用 Helm 安装,仓库地址为 https://opencost.github.io/opencost-helm-chart。安装前先确认集群中已有可用的 Prometheus,并记录其服务地址。以下命令以命名空间 opencost 为例:

helm repo add opencost https://opencost.github.io/opencost-helm-chart
helm repo update

helm install opencost opencost/opencost \
  --namespace opencost \
  --create-namespace \
  --set opencost.prometheus.internal.enabled=false \
  --set opencost.prometheus.external.url=http://prometheus-server.monitoring.svc:9090 \
  --set opencost.ui.enabled=true

这里有两个关键选择:如果集群中已有 Prometheus,应设置 opencost.prometheus.internal.enabled=false,并通过 opencost.prometheus.external.url 指向外部 Prometheus 的 Service 地址;如果希望 OpenCost 自带一个轻量 Prometheus,则保持 internal 为 true,但生产环境通常不推荐,因为自带实例的指标保留周期和采集范围有限。

核心配置参数

OpenCost 的配置集中在 values.yaml 中,以下参数直接影响成本计算的准确性:

参数作用示例值
opencost.prometheus.external.url外部 Prometheus 查询地址http://prometheus-server.monitoring.svc:9090
opencost.prometheus.internal.enabled是否启用内置 Prometheusfalse
opencost.cloudProvider云厂商价格表来源aws / gcp / azure / custom
opencost.customPricing.enabled是否使用自定义价格true
opencost.ui.enabled是否部署 Web UItrue
opencost.exporter.defaultClusterId多集群场景下的集群标识prod-cluster-01

当 cloudProvider 设为 custom 时,需要额外提供价格配置文件,通常以 ConfigMap 形式挂载。价格文件至少应包含 CPU 每核时价格、内存每 GiB 时价格、存储每 GiB 月价格,以及可选的网络出流量价格。例如:

# custom-pricing.yaml 示例(单位:美元)
CPU: 0.031611        # 每 CPU 核时
RAM: 0.004237        # 每 GiB 时
storage: 0.000138    # 每 GiB 时
zoneNetworkEgress: 0.01
regionNetworkEgress: 0.01

验证部署

安装完成后,按以下顺序验证。首先确认 Pod 处于 Running 状态:

kubectl get pods -n opencost
# 期望输出类似:
# NAME                        READY   STATUS    RESTARTS   AGE
# opencost-6b8f7c9d4f-x2k9m   1/1     Running   0          2m

接着检查 OpenCost 是否能正常查询 Prometheus。最直接的方式是访问 OpenCost 的 /allocation 接口,它会返回当前集群的成本分配数据:

kubectl port-forward -n opencost svc/opencost 9003:9003
curl -s http://localhost:9003/allocation/compute?window=1h | head -c 500

如果返回 JSON 中包含 cpuCost、ramCost 等字段且数值非零,说明 Prometheus 查询和成本计算链路已打通。若返回空对象或报错,则进入排错环节。

常见排错

问题一:Pod 启动后立即 CrashLoopBackOff。查看日志 kubectl logs -n opencost deploy/opencost,常见原因是 Prometheus URL 不可达。检查 Service 名称和端口是否正确,并确认 OpenCost Pod 所在命名空间能否解析该 DNS。可以用 kubectl exec 进入 Pod 后执行 curl -v http://prometheus-server.monitoring.svc:9090/-/healthy 验证连通性。

问题二:/allocation 返回空数据。这通常意味着 Prometheus 中没有匹配的指标。OpenCost 依赖 container_cpu_usage_seconds_total、container_memory_working_set_bytes 等指标。在 Prometheus 中执行 count(container_cpu_usage_seconds_total),若结果为 0,说明采集配置未覆盖 cAdvisor 或 kubelet。此时需要检查 Prometheus 的 scrape config,确保 job 中包含 kubelet 的 /metrics/cadvisor 端点。

问题三:成本数值明显偏低或为 0。优先检查价格配置。若 cloudProvider 设为 aws 但集群实际运行在自建机房,OpenCost 会拉取 AWS 公开价格表,导致价格与实际不符。此时应切换为 custom 并挂载自定义价格文件。另外,若 Prometheus 保留周期过短(如仅 1 天),查询 7 天成本时会返回部分空值,表现为成本曲线断裂。

问题四:UI 无法访问。确认 opencost.ui.enabled=true,并检查 Service 是否暴露了 9090 端口。默认 UI 通过 kubectl port-forward svc/opencost-ui 9090:9090 访问。若使用 Ingress,需确保路径重写规则正确,OpenCost UI 的静态资源路径对前缀敏感。

排错时建议先固定一个最小验证路径:Pod Running → Prometheus 可达 → /allocation 有数据 → 成本数值合理。每一步只验证一个环节,避免同时修改多个参数导致问题定位困难。

最后,若希望 OpenCost 的成本指标被长期存储和可视化,可在 Prometheus 中增加一个 scrape job 抓取 OpenCost 的 /metrics 端点,再在 Grafana 中导入 OpenCost 官方看板(Dashboard ID 通常为 15714 或社区维护版本)。这样成本数据就与资源指标进入同一套可观测体系,便于做趋势对比和预算告警。