CubeAPM
CubeAPM CubeAPM

How to Set Up Kubernetes Cost Monitoring with OpenCost: Step-by-Step Guide

How to Set Up Kubernetes Cost Monitoring with OpenCost: Step-by-Step Guide

Table of Contents

OpenCost is an open-source CNCF project that brings cost visibility to Kubernetes clusters by measuring resource allocation at the pod, namespace, service, and label level. Without OpenCost, most teams discover cost problems only when the cloud bill arrives. With OpenCost, you see cost attribution in real time and can act before overspending compounds. According to the CNCF 2024 Annual Survey, 70% of organizations now run Kubernetes in production, yet most lack granular cost visibility beyond what their cloud provider surfaces at the VM or node level.

This guide walks through installing OpenCost on a Kubernetes cluster, configuring it to pull pricing data from your cloud provider, accessing the OpenCost UI, and troubleshooting common issues. By the end, you will have working cost allocation dashboards showing which workloads, namespaces, or teams are driving your Kubernetes spend.

Prerequisites

Before starting, ensure you have the following in place:

  • Kubernetes 1.21 or later running in your environment (1.28+ officially supported as of OpenCost v1.105)
  • kubectl CLI installed and configured to access your cluster
  • Helm 3.x installed on your local machine
  • Prometheus installed and scraping metrics from your Kubernetes cluster (OpenCost requires Prometheus for data storage and metric ingestion)
  • Cloud provider credentials if you want live pricing data from AWS, Azure, or GCP (optional but recommended for accurate cost modeling)
  • Cluster-admin permissions to create namespaces, services, and deployments

If you do not have Prometheus installed yet, you will install it as part of Step 1.

Step 1: Install Prometheus with OpenCost Scrape Configuration

OpenCost depends on Prometheus to store and query Kubernetes metrics. If Prometheus is already running in your cluster, skip to Step 2. If not, install it now with the configuration OpenCost needs.

Add the Prometheus Helm repository and install Prometheus with OpenCost’s recommended scrape config:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/prometheus \
  --namespace prometheus-system \
  --create-namespace \
  --set prometheus-pushgateway.enabled=false \
  --set alertmanager.enabled=false \
  -f https://raw.githubusercontent.com/opencost/opencost/develop/kubernetes/prometheus/extraScrapeConfigs.yaml

This installs Prometheus in the prometheus-system namespace with pushgateway and alertmanager disabled to keep the setup minimal. The -f flag pulls OpenCost’s scrape config, which adds targets for OpenCost’s metrics endpoint.

Verify Prometheus is running:

kubectl get pods -n prometheus-system

You should see prometheus-server in a Running state. If the pod is stuck in Pending, check the next troubleshooting step.

Common issue: PersistentVolumeClaim stuck in Pending

If prometheus-server remains in Pending state, the most common cause is a missing default StorageClass. Describe the PVC to confirm:

kubectl describe pvc -n prometheus-system

If you see no persistent volumes available for this claim and no storage class is set, list available StorageClasses:

kubectl get storageclass

If a StorageClass exists but is not marked as default, patch it:

kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

Replace gp2 with the name of your StorageClass. After patching, the PVC should bind and the Prometheus pod will move to Running state within a minute.

Step 2: Install OpenCost Using Helm

OpenCost is installed via its official Helm chart. Add the OpenCost repository and install:

helm repo add opencost https://opencost.github.io/opencost-helm-chart
helm repo update
helm install opencost opencost/opencost \
  --namespace opencost \
  --create-namespace

This creates the opencost namespace and deploys the OpenCost exporter pod, which queries Prometheus for metrics and calculates cost allocations.

Verify the OpenCost pod is running:

kubectl get pods -n opencost

You should see opencost-<hash> in Running state. If not, describe the pod to check for errors:

kubectl describe pod -n opencost

Step 3: Configure Cloud Provider Pricing Integration

OpenCost can pull live pricing data from AWS, Azure, or GCP to improve cost accuracy. Without this, OpenCost uses default on-demand pricing, which may not reflect your actual rates if you use reserved instances, savings plans, or spot instances.

For AWS EKS clusters:

Create a ConfigMap with your AWS pricing API key and region:

apiVersion: v1
kind: ConfigMap
metadata:
  name: opencost-cloud-config
  namespace: opencost
data:
  cloud-integration.json: |
    {
      "aws": {
        "region": "us-east-1",
        "access_key_id": "YOUR_AWS_ACCESS_KEY",
        "secret_access_key": "YOUR_AWS_SECRET_KEY"
      }
    }

Apply the ConfigMap:

kubectl apply -f opencost-cloud-config.yaml

Update the OpenCost deployment to mount this ConfigMap:

helm upgrade opencost opencost/opencost \
  --namespace opencost \
  --set opencost.exporter.extraEnv.CLOUD_COST_ENABLED="true" \
  --set opencost.exporter.extraEnv.CLOUD_COST_CONFIG_PATH="/var/cloud-integration/cloud-integration.json"

This tells OpenCost to read the cloud config file and fetch live pricing data from AWS.

For Azure AKS or GCP GKE clusters:

The structure is similar. Replace the aws block with azure or gcp and provide the corresponding credentials. See the OpenCost documentation at https://opencost.io/docs/configuration/cloud-costs for full configuration examples.

Step 4: Access the OpenCost UI

OpenCost includes a web UI for visualizing cost allocations. The UI runs on port 9090 inside the cluster. To access it locally, use kubectl port forwarding:

kubectl port-forward -n opencost service/opencost 9090:9090

Open your browser and navigate to http://localhost:9090. You should see the OpenCost dashboard showing cost breakdowns by namespace, deployment, pod, and label.

If the UI does not load, verify the service is running:

kubectl get svc -n opencost

Confirm the opencost service exists and has an endpoint. If the service is missing, reinstall OpenCost using the Helm command from Step 2.

For production access:

Port forwarding is fine for testing but not for production use. To expose OpenCost externally, create an Ingress resource or change the service type to LoadBalancer:

kubectl patch svc opencost -n opencost -p '{"spec": {"type": "LoadBalancer"}}'

This creates a public load balancer endpoint. Retrieve the external IP:

kubectl get svc opencost -n opencost

Access the UI at http://<EXTERNAL-IP>:9090. For production, secure this endpoint with TLS and authentication.

Step 5: Query the OpenCost API for Cost Data

Beyond the UI, OpenCost exposes a REST API for programmatic access to cost data. The API runs on port 9003. Port forward to access it:

kubectl port-forward -n opencost service/opencost 9003:9003

Query cost allocations for the last 60 minutes:

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

This returns JSON with cost data aggregated by pod. You can filter and aggregate by namespace, label, or deployment using query parameters. For example, to see costs by namespace:

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

The API is useful for building custom dashboards, exporting cost data to external systems, or triggering cost-based alerts. Full API documentation is available at https://opencost.io/docs/integrations/api.

Step 6: Integrate OpenCost Metrics into Grafana

OpenCost exposes Prometheus metrics at /metrics. You can visualize these in Grafana if you already use it for infrastructure monitoring. Import the official OpenCost Grafana dashboard:

  1. Open Grafana and navigate to Dashboards > Import
  2. Enter dashboard ID 15642 (official OpenCost dashboard from Grafana.com)
  3. Select your Prometheus data source
  4. Click Import

This creates a pre-built dashboard showing cost trends, top spending namespaces, and per-pod cost breakdowns. If you prefer to build custom panels, query metrics like opencost_pod_allocation_cpu_core_hours or opencost_namespace_allocation_total directly in Grafana’s query editor.

Troubleshooting Common Issues

OpenCost pod shows “Back-off restarting failed container”

This usually means OpenCost cannot reach Prometheus. Verify Prometheus is accessible from the OpenCost namespace:

kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- \
  curl http://prometheus-server.prometheus-system.svc.cluster.local/api/v1/query?query=up

If this fails, check that the Prometheus service exists and is reachable. OpenCost expects Prometheus at http://prometheus-server.prometheus-system.svc.cluster.local by default. If your Prometheus service has a different name or namespace, update the OpenCost Helm values:

helm upgrade opencost opencost/opencost \
  --namespace opencost \
  --set opencost.prometheus.internal.serviceName=your-prometheus-service \
  --set opencost.prometheus.internal.namespaceName=your-prometheus-namespace

Cost allocations show zero or incorrect values

OpenCost calculates costs based on CPU and memory requests defined in your pod specs. If pods do not have resource requests set, OpenCost cannot allocate costs accurately. Check a deployment:

kubectl get deployment <deployment-name> -o yaml | grep -A 5 resources

If requests are missing, add them:

resources:
  requests:
    cpu: 100m
    memory: 128Mi

Without resource requests, OpenCost assigns costs to the node but cannot attribute them to specific workloads.

Prometheus scrape config not including OpenCost metrics

If the OpenCost metrics endpoint is not being scraped, Prometheus will not store cost data. Verify the scrape config includes OpenCost:

kubectl get configmap prometheus-server -n prometheus-system -o yaml | grep opencost

If missing, add a scrape job manually to the Prometheus ConfigMap or reinstall Prometheus with the OpenCost scrape config from Step 1.

Cloud pricing integration not working

If you configured cloud credentials but OpenCost still shows default pricing, check the logs:

kubectl logs -n opencost deployment/opencost

Look for errors like failed to fetch AWS pricing API or invalid cloud config path. Common issues include incorrect credentials, missing IAM permissions, or a misconfigured ConfigMap path. Ensure CLOUD_COST_CONFIG_PATH points to the correct mount location inside the container.

Monitoring OpenCost with CubeAPM

If you need unified visibility across Kubernetes costs, application performance, and infrastructure metrics, CubeAPM offers an integrated approach. CubeAPM runs on-prem or inside your VPC and correlates OpenCost data with APM traces, logs, and Kubernetes events in a single dashboard. Unlike SaaS tools where telemetry data leaves your infrastructure, CubeAPM keeps everything local, which is critical for teams with data residency requirements or strict compliance mandates.

CubeAPM ingests OpenCost metrics via Prometheus and surfaces cost allocations alongside application traces, so you can see which services or endpoints are driving both latency and cloud spend. For example, if a specific API endpoint shows high cost attribution in OpenCost, CubeAPM correlates that with trace data to show whether it is caused by inefficient queries, retry storms, or over-provisioned pods.

To connect CubeAPM to OpenCost:

  1. Deploy CubeAPM in your cluster or VPC following the setup guide at https://cubeapm.com
  2. Configure CubeAPM’s Prometheus integration to scrape the same Prometheus instance OpenCost uses
  3. OpenCost metrics will appear in CubeAPM’s metrics explorer automatically

CubeAPM also supports creating cost-based alerts. You can trigger alerts when namespace costs exceed a threshold, when a deployment’s cost spikes unexpectedly, or when cost per request crosses a defined limit. This brings cost visibility into the same alerting workflow as your performance and error alerts, which is especially useful for platform teams managing shared Kubernetes clusters across multiple product teams.

CubeAPM pricing is $0.15/GB for all ingested telemetry, with no separate charges for metrics, users, or retention. Compare this to SaaS observability tools where metrics ingestion, dashboards, and alerting incur separate line items. For teams running OpenCost at scale, CubeAPM provides a predictable cost model that does not compound as your telemetry volume grows.

OpenCost is now installed and surfacing cost data across your Kubernetes workloads. The next step is using this data to optimize resource requests, identify over-provisioned deployments, and allocate costs accurately across teams or projects. Cost visibility alone does not reduce spend, but it gives engineering and finance teams the shared language they need to make informed decisions about where to optimize.

Frequently Asked Questions

What is OpenCost and why should I use it?

OpenCost is an open-source tool that calculates real-time Kubernetes costs by analyzing resource usage and applying cloud provider pricing. It helps teams see which workloads, namespaces, or labels are driving spend before the cloud bill arrives.

Does OpenCost require Prometheus?

Yes. OpenCost queries Prometheus for Kubernetes metrics like CPU and memory usage. Without Prometheus, OpenCost cannot calculate cost allocations. Install Prometheus first if it is not already running in your cluster.

Can OpenCost integrate with AWS, Azure, or GCP for accurate pricing?

Yes. OpenCost supports cloud provider integrations to pull live pricing data from AWS, Azure, and GCP. This improves cost accuracy by reflecting your actual rates instead of default on-demand pricing.

How do I access the OpenCost UI?

Use kubectl port forwarding to access the UI locally at http://localhost:9090, or expose it externally using a LoadBalancer or Ingress resource for production use.

Why are my cost allocations showing zero?

OpenCost calculates costs based on CPU and memory resource requests in pod specs. If pods do not define resource requests, OpenCost cannot allocate costs to them. Add resource requests to your deployments to see accurate cost data.

Can I export OpenCost data to external systems?

Yes. OpenCost exposes a REST API for querying cost data programmatically. You can export this data to CSV, Parquet, or external analytics platforms using the API.

How does OpenCost differ from Kubecost?

OpenCost is the open-source core of Kubecost. Kubecost adds enterprise features like multi-cluster management, savings recommendations, and anomaly detection. OpenCost is free and community-maintained.

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.

×
×