CubeAPM
CubeAPM CubeAPM

Kubernetes Cost Monitoring with OpenCost: Step by Step Setup Guide

Kubernetes Cost Monitoring with OpenCost: Step by Step Setup Guide

Table of Contents

A Kubernetes cluster that auto scales from 20 to 80 nodes during a traffic spike can triple your infrastructure bill in hours before anyone realizes costs are compounding. Without granular visibility into which pods, namespaces, or workloads are driving spend, most teams discover the damage only at month end when the cloud bill arrives. OpenCost solves this by breaking down Kubernetes costs at the pod, namespace, deployment, and label level in real time.

This guide walks through installing OpenCost on any Kubernetes 1.21+ cluster using Helm, configuring cloud provider cost integrations for accurate allocation, and accessing cost data through the OpenCost UI and API. By the end you will have full visibility into where your Kubernetes spend is going and be able to export cost breakdowns for chargeback or showback.

Prerequisites

Before installing OpenCost, verify your environment meets these requirements:

  • Kubernetes cluster version 1.21 or higher (1.28+ officially supported as of OpenCost v1.105)
  • Prometheus installed and scraping metrics from your cluster (OpenCost requires Prometheus for data storage)
  • kubectl configured to access your cluster with cluster admin permissions
  • Helm 3 installed on your local machine
  • Access to your cloud provider billing data (AWS Cost and Usage Reports, GCP BigQuery billing export, or Azure Cost Management API) if you want accurate cloud cost allocation
  • 2 GB RAM and 1 CPU core available in your cluster for OpenCost deployment

If you do not have Prometheus installed yet, OpenCost’s Helm chart can deploy a bundled Prometheus instance for you. For production environments, point OpenCost to your existing Prometheus instance to avoid running duplicate metric collectors.

Step 1: Add the OpenCost Helm Repository

OpenCost is now installed and managed exclusively via the official Helm chart. The standalone Kubernetes manifest files were removed in 2024.

Add the OpenCost Helm repository and update it to pull the latest chart version:

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

Verify the repository was added successfully:

helm search repo opencost

You should see output listing the opencost/opencost chart with the current version number. As of early 2026, the latest stable release is v1.44.0.

Step 2: Create a Namespace for OpenCost

Create a dedicated namespace to keep OpenCost resources isolated from other workloads:

kubectl create namespace opencost

This namespace will hold the OpenCost deployment, service, and any associated config maps or secrets. Using a dedicated namespace makes it easier to manage permissions, resource quotas, and upgrades.

Step 3: Configure Cloud Provider Integration

OpenCost works out of the box without cloud provider integration, but it will only show estimated costs based on public cloud pricing. For accurate cost allocation that matches your actual cloud bill, configure OpenCost to pull real billing data from your cloud provider.

AWS Cost and Usage Report Setup

If you run on AWS, OpenCost can ingest cost data from AWS Cost and Usage Reports stored in S3.

Create an S3 bucket and enable Cost and Usage Reports in the AWS Billing Console. Configure the report to include resource IDs and save it in Parquet format for faster processing.

Create a Kubernetes secret with your AWS credentials:

kubectl create secret generic aws-credentials \
  --from-literal=aws_access_key_id=YOUR_ACCESS_KEY \
  --from-literal=aws_secret_access_key=YOUR_SECRET_KEY \
  --namespace opencost

When installing OpenCost in Step 4, pass the S3 bucket name and region as Helm values so OpenCost knows where to find your cost data.

GCP BigQuery Billing Export Setup

For GCP, export billing data to BigQuery and give OpenCost’s service account permission to query it.

Enable BigQuery billing export in the GCP Billing Console. Note the BigQuery dataset ID where billing data is stored.

Create a GCP service account with BigQuery Data Viewer permissions on the billing dataset. Download the JSON key file.

Create a Kubernetes secret from the JSON key:

kubectl create secret generic gcp-billing-key \
  --from-file=service-account.json=YOUR_KEY_FILE.json \
  --namespace opencost

Azure Cost Management API Setup

OpenCost integrates with Azure Cost Management API to pull cost data for Azure Kubernetes Service clusters.

Create an Azure service principal with Cost Management Reader permissions on your subscription. Note the tenant ID, client ID, and client secret.

Create a Kubernetes secret with Azure credentials:

kubectl create secret generic azure-credentials \
  --from-literal=azure_tenant_id=YOUR_TENANT_ID \
  --from-literal=azure_client_id=YOUR_CLIENT_ID \
  --from-literal=azure_client_secret=YOUR_CLIENT_SECRET \
  --namespace opencost

Step 4: Install OpenCost with Helm

With cloud provider credentials configured, install OpenCost using Helm. This example shows a basic installation that deploys OpenCost with bundled Prometheus:

helm install opencost opencost/opencost \
  --namespace opencost \
  --set opencost.exporter.cloudProviderApiKey="YOUR_CLOUD_API_KEY" \
  --set opencost.prometheus.internal.enabled=true

For AWS with Cost and Usage Reports in S3:

helm install opencost opencost/opencost \
  --namespace opencost \
  --set opencost.exporter.cloudCost.enabled=true \
  --set opencost.exporter.cloudCost.configPath="/var/cloud-integration/cloud-integration.json" \
  --set opencost.exporter.extraEnv.CLOUD_COST_ENABLED="true"

For production environments where you already have Prometheus running, point OpenCost to your existing Prometheus instance instead of deploying a bundled one:

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

Verify the OpenCost pods are running:

kubectl get pods --namespace opencost

You should see opencost exporter and opencost ui pods in Running state. If pods are stuck in Pending or CrashLoopBackOff, check logs with kubectl logs to identify the issue.

Step 5: Access the OpenCost UI

OpenCost includes a web UI that visualizes cost allocation by namespace, deployment, pod, service, and label.

Port forward the OpenCost service to your local machine:

kubectl port-forward --namespace opencost service/opencost 9003:9003 9090:9090

Open your browser and navigate to http://localhost:9090 to access the OpenCost UI. You should see a dashboard showing cost breakdowns by namespace and workload.

To verify the API is working, query the allocation endpoint directly:

curl http://localhost:9003/allocation/compute?window=60m

This returns JSON showing compute cost allocation for the last 60 minutes broken down by pod and namespace.

Step 6: Query Cost Data with the OpenCost API

The OpenCost API exposes detailed cost data that you can query programmatically for chargeback reports, budget alerts, or integration with other tools.

The main allocation endpoint accepts parameters for time window, aggregation level, and filters. Query costs for the last 7 days aggregated by namespace:

curl "http://localhost:9003/allocation/compute?window=7d&aggregate=namespace"

Filter by a specific namespace:

curl "http://localhost:9003/allocation/compute?window=24h&aggregate=pod&filter=namespace:production"

Aggregate by label to track costs by team or application:

curl "http://localhost:9003/allocation/compute?window=7d&aggregate=label:team"

The API also supports exporting data in CSV or Parquet format for analysis in spreadsheets or data warehouses. Full API documentation is available at opencost.io/docs/api.

Step 7: Integrate OpenCost with Prometheus Metrics

OpenCost exposes a /metrics endpoint that Prometheus can scrape to store historical cost data as time series metrics.

If you deployed OpenCost with the bundled Prometheus, scraping is configured automatically. For external Prometheus, add a scrape config to your Prometheus configuration:

scrape_configs:
  - job_name: 'opencost'
    static_configs:
      - targets: ['opencost.opencost.svc.cluster.local:9003']

Reload Prometheus configuration:

kubectl rollout restart deployment prometheus-server --namespace monitoring

Verify OpenCost metrics are being scraped by querying Prometheus:

curl "http://prometheus-server.monitoring.svc.cluster.local:9090/api/v1/query?query=opencost_total_cost"

With metrics in Prometheus, you can build Grafana dashboards that show cost trends over time or set up alerts when costs exceed thresholds.

Step 8: Set Up Cost Alerts

Once cost data is flowing into Prometheus, configure alerts to notify your team when costs spike unexpectedly.

Create a PrometheusRule resource to define cost alert thresholds:

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: opencost-alerts
  namespace opencost
spec:
  groups:
    - name: opencost
      interval: 5m
      rules:
        - alert: NamespaceCostHigh
          expr: sum(opencost_namespace_cost_total) by (namespace) > 500
          for: 1h
          labels:
            severity: warning
          annotations:
            summary: "Namespace {{ $labels.namespace }} cost exceeded $500 in the last hour"
            description: "Current cost: {{ $value }}"

Apply the alert rule:

kubectl apply -f opencost-alerts.yaml

Route alerts to Slack, PagerDuty, or email using Alertmanager. This lets teams respond to cost spikes in real time instead of discovering them weeks later when the bill arrives.

Step 9: Enable Multi Cluster Cost Visibility

For teams running multiple Kubernetes clusters, OpenCost supports aggregating cost data across clusters into a single view.

Deploy OpenCost in each cluster following the steps above. Each OpenCost instance exposes its own API endpoint with cost data for that cluster.

Use the OpenCost federation feature to query multiple clusters from a single endpoint. Configure a central OpenCost instance with the cluster endpoint URLs:

opencost:
  federation:
    enabled: true
    clusters:
      - name: prod-us-east
        address: http://opencost.prod-us-east.svc.cluster.local:9003
      - name: prod-eu-west
        address: http://opencost.prod-eu-west.svc.cluster.local:9003

Query the federated endpoint to see cost allocation across all clusters:

curl "http://localhost:9003/allocation/compute?window=7d&aggregate=cluster,namespace"

This returns cost breakdowns showing which clusters and namespaces are driving total spend.

Troubleshooting Common Issues

OpenCost Pod Fails to Start with Prometheus Connection Error

If the OpenCost exporter pod logs show errors connecting to Prometheus, verify the Prometheus URL is correct.

Check the Helm values you passed during installation. The Prometheus URL must be reachable from inside the cluster. If you are using the bundled Prometheus, the default URL is http://opencost-prometheus-server.opencost.svc.cluster.local:9090.

For external Prometheus, use the full service DNS name including namespace. Test connectivity from inside the OpenCost pod:

kubectl exec -it opencost-exporter-xxxxx --namespace opencost -- curl http://prometheus-server.monitoring.svc.cluster.local:9090/-/healthy

Cost Data Shows Zero or Inaccurate Values

If OpenCost shows zero costs or wildly inaccurate numbers, the most common cause is missing cloud provider integration.

Without cloud billing data, OpenCost falls back to estimating costs based on public pricing. These estimates do not account for reserved instances, savings plans, spot instances, or negotiated discounts.

Verify your cloud provider credentials are configured correctly in the Kubernetes secret created in Step 3. Check OpenCost logs for errors accessing billing data:

kubectl logs deployment/opencost-exporter --namespace opencost | grep "cloud cost"

For AWS, confirm the Cost and Usage Report is being generated and stored in the S3 bucket you specified. For GCP, verify the service account has BigQuery Data Viewer permissions.

OpenCost UI Loads but Shows No Data

If the UI loads but displays no cost data, check that Prometheus is successfully scraping metrics from your cluster.

Verify Prometheus has metrics for your pods by querying directly:

curl "http://prometheus-server.monitoring.svc.cluster.local:9090/api/v1/query?query=container_cpu_usage_seconds_total"

If Prometheus is not scraping pod metrics, OpenCost has no data to allocate costs to. Check that kube state metrics and node exporter are running:

kubectl get pods --all-namespaces | grep -E "kube-state-metrics|node-exporter"

High Memory Usage in OpenCost Exporter Pod

In large clusters with hundreds of pods and thousands of metric series, the OpenCost exporter can consume significant memory.

If the exporter pod is being OOMKilled, increase the memory limit in your Helm values:

opencost:
  exporter:
    resources:
      limits:
        memory: 4Gi
      requests:
        memory: 2Gi

Upgrade the release to apply the new resource limits:

helm upgrade opencost opencost/opencost --namespace opencost -f values.yaml

For extremely large clusters, consider running OpenCost with infrastructure monitoring platforms that handle high cardinality metric ingestion more efficiently.

Monitoring OpenCost with CubeAPM

CubeAPM provides a unified platform to monitor both OpenCost itself and the Kubernetes infrastructure it tracks. Since OpenCost exposes Prometheus metrics, CubeAPM can ingest those metrics alongside your application traces and logs for full context visibility.

Deploy CubeAPM in your cluster as a self hosted observability stack. Configure it to scrape OpenCost metrics from the /metrics endpoint:

receivers:
  prometheus:
    config:
      scrape_configs:
        - job_name: 'opencost'
          static_configs:
            - targets: ['opencost.opencost.svc.cluster.local:9003']

With OpenCost cost metrics in CubeAPM, you can correlate cost spikes with application performance events. For example, if a deployment scales up and drives higher cloud spend, CubeAPM shows both the cost increase from OpenCost and the APM traces showing why the scale up happened.

CubeAPM’s self hosted deployment keeps all cost and telemetry data inside your VPC with no external data egress. This eliminates the per GB transfer fees that compound when sending monitoring data to SaaS platforms. At $0.15/GB for unified metrics, traces, and logs, CubeAPM provides full stack observability at a fraction of the cost of tools like Datadog or New Relic.

For teams running OpenCost alongside other monitoring tools, CubeAPM reduces tool sprawl by consolidating APM, logs, infrastructure monitoring, and cost visibility into one platform. Learn more at cubeapm.com/platform.

Conclusion

OpenCost transforms Kubernetes cost visibility from a monthly surprise into real time allocation data that teams can act on. By installing OpenCost with Helm, integrating cloud billing data, and exposing cost metrics to Prometheus, you gain granular visibility into which pods, namespaces, and workloads drive your cloud spend. The steps covered here set up a production ready OpenCost deployment that scales with your cluster and integrates with your existing monitoring stack.

Disclaimer: The information in this article reflects the latest details available at the time of publication and may change as technologies and products evolve. Features, pricing, and plan limits can change over time. Always verify the latest information directly with the vendor before making purchasing or deployment decisions.

Frequently Asked Questions

What is OpenCost and why do I need it for Kubernetes?

OpenCost is an open source tool that breaks down Kubernetes costs by pod, namespace, deployment, service, and label. Without it, you only see total cloud spend with no way to allocate costs to specific workloads or teams.

Does OpenCost work without cloud provider billing integration?

Yes, OpenCost estimates costs based on public pricing if you do not configure cloud billing integration. However, these estimates do not reflect reserved instances, savings plans, or negotiated discounts, so actual costs will differ.

Can I run OpenCost on multiple clusters?

Yes, deploy OpenCost in each cluster and use the federation feature to aggregate cost data across all clusters into a single view. Each cluster reports its own costs and the federated endpoint combines them.

How much overhead does OpenCost add to my cluster?

OpenCost typically uses 1 CPU core and 2 GB RAM in production clusters with hundreds of pods. For very large clusters with thousands of pods, you may need to increase memory limits to 4 GB.

What is the difference between OpenCost and Kubecost?

OpenCost is the open source core that Kubecost originally developed and donated to the CNCF. Kubecost is a commercial product built on top of OpenCost with additional features like recommendations, anomaly detection, and enterprise support.

Can OpenCost show costs for services outside Kubernetes?

OpenCost focuses on Kubernetes workload costs. It can allocate cloud provider costs for managed services like RDS or S3 if those resources are tagged with labels that match Kubernetes workloads, but this requires manual tagging setup.

How do I export OpenCost data for chargeback reports?

Use the OpenCost API to query cost data in JSON format or enable CSV or Parquet exports. You can automate report generation by scheduling API queries with cron jobs or integrating with data pipelines.

×
×