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 消费。
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 | 是否启用内置 Prometheus | false |
opencost.cloudProvider | 云厂商价格表来源 | aws / gcp / azure / custom |
opencost.customPricing.enabled | 是否使用自定义价格 | true |
opencost.ui.enabled | 是否部署 Web UI | true |
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 或社区维护版本)。这样成本数据就与资源指标进入同一套可观测体系,便于做趋势对比和预算告警。