You can have a perfectly healthy Kubernetes cluster and still have no idea who is driving the bill. The cloud invoice will tell you what the cluster cost. It will not tell you which namespace, workload, or team consumed that capacity, or how much of the spend was simply idle headroom nobody requested. OpenCost fills that gap. It gives you a vendor-neutral way to allocate Kubernetes cost down to cluster objects, query it over an API, and build showback without buying into a commercial platform first.
As of v1.121.0 (July 2026), the current release, OpenCost is a CNCF Incubating project. The useful mental split is straightforward: OpenCost is the open-source engine and specification; Kubecost is the commercial product line in the same space. The OpenCost repository notes that the project was originally developed and open-sourced by Kubecost, while Kubecost's public site is now branded IBM Kubecost. For this post, we are staying on the OSS side: self-hosted OpenCost, standard Helm install, standard API, standard Prometheus queries.
The allocation model is the part to understand first
If you only remember one detail from OpenCost, make it this one: workload cost is not just raw usage. In the OpenCost specification, workload costs are defined as max(request, usage) for resources with allocation costs such as CPU and GPU. That matters because the bill follows reserved and allocatable capacity rather than whatever a container happened to burn in a five-minute slice.
A pod that requests 2 CPU and uses 200m is still consuming scheduling capacity someone else cannot have. OpenCost treats that as real cost, which is why its numbers are useful for showback and bill reconciliation instead of just efficiency charts.
Idle cost is the second half of the picture. The specification defines cluster idle cost as:
Cluster Idle Cost = Cluster Asset Costs - Workload Costs
That is the spend you are carrying in the cluster but have not allocated to workloads. It is the cost of spare node capacity, overprovisioned requests, and all the other room you are paying for so the platform can absorb change.
OpenCost also treats shared costs as first-class. The specification calls out three common ways to distribute them:
- uniformly across tenants
- proportionally to a tenant's consumption
- by a custom metric such as network egress
That means the honest answer to “what does this namespace cost?” is often “its direct workload cost, plus its share of idle and shared platform cost”. If you skip that second part, your showback report will look cleaner than the bill you actually pay.
Install it with Helm against an existing Prometheus
The current Helm docs assume you already have Prometheus. That is still the normal path.
helm repo add opencost-charts https://opencost.github.io/opencost-helm-chart
helm repo update
Then point OpenCost at the Prometheus service it should read from:
opencost:
prometheus:
internal:
namespaceName: monitoring
serviceName: prometheus-kube-prometheus-prometheus
port: 9090
exporter:
defaultClusterId: production-eks
And install it:
helm install opencost opencost-charts/opencost \
--namespace opencost \
--create-namespace \
-f values.yaml
That gives you the full OpenCost deployment plus the API and UI. The docs use localhost:9003 as the default API address, so a quick validation path is:
kubectl -n opencost port-forward deployment/opencost 9003 9090
Port 9003 is the API; 9090 is the UI.
There is a lighter path worth knowing about too. The Prometheus integration docs note that you do not need a Prometheus client just to emit cost metrics, and a "Promless" mode has been taking shape across releases since late 2025. Treat that as a fast-moving area rather than a settled default. If you want the most documented path today, use the Helm install against an existing Prometheus stack. If you want the leaner route, pin the version and read the release notes for the exact build you are adopting.
Start with the Allocation API, not a hand-rolled dashboard
The fastest way to get useful showback is the Allocation API. It already applies the OpenCost cost model, which means you are querying the model's own output instead of rebuilding the logic yourself out of raw metrics.
A seven-day namespace breakdown looks like this:
curl 'http://localhost:9003/allocation?window=7d&aggregate=namespace&shareIdle=true'
Two parts of that query earn their keep:
-
aggregate=namespacegives you a shape platform teams can actually hand to someone. Most organisations do not want “cost by pod” as the first report; they want “what did team-a's namespace cost this week?” Namespace is a good default grain because it is close enough to ownership to start a useful conversation. -
shareIdle=trueis what keeps the number honest. Without idle-cost sharing, namespace totals can look impressively low while a large chunk of the bill sits outside the report as unallocated capacity — fine for an efficiency drill-down, but weak showback.
If you label workloads by team, you can roll the same data up at the ownership layer instead:
curl 'http://localhost:9003/allocation?window=7d&aggregate=label:team&shareIdle=true'
The Allocation API accepts label-based aggregation, so you are not forced into namespace as the only billing dimension. That is useful when a single team owns several namespaces, or when shared namespaces are unavoidable and labels are the cleaner boundary.
This is the point where OpenCost usually becomes operationally useful. You stop arguing about the cluster bill as one opaque number and start asking better questions: which teams carry the most idle share, which namespaces reserve far more than they use, and which platform defaults are making the bill harder to attribute than it should be.
Prometheus is still useful, but use it for the right layer
OpenCost also exposes metrics for Prometheus, which is what you want for dashboards and trend lines.
For a simple monthly node-cost view, the documentation's example is:
sum(node_total_hourly_cost) * 730
That is deliberately blunt. It tells you what the currently provisioned nodes cost over a rough 730-hour month. It is good for keeping an eye on baseline cluster spend, but it is not showback yet.
For a namespace-level dashboard, you can build a query from OpenCost's allocation and node-cost metrics, for example:
sum by (namespace) (
container_cpu_allocation * on (node) group_left node_cpu_hourly_cost +
container_memory_allocation_bytes * on (node) group_left node_ram_hourly_cost / (1024 * 1024 * 1024)
)
That is closer to what most teams expect to see in Grafana: cost broken down by namespace, derived from allocation metrics multiplied by node pricing. It is useful for trends, deltas, and “what changed this week?” views.
The caveat is which layer you treat as authoritative. When you need a number to hand to finance or to another engineering team, start from the Allocation API. When you need a graph that shows whether cost by namespace is climbing, Prometheus is the right tool.
The honesty box: what the numbers are, and what they are not
Two assumptions trip people up:
-
That the allocation metrics are pure usage metrics. They aren't. In the current code (v1.121.0) the synthetic
container_cpu_allocationandcontainer_memory_allocation_bytesmetrics are built frommax(request, usage), matching the specification — which is exactly why they beat a plain CPU-usage graph for cost allocation. - That pricing is magically exact out of the box. OpenCost's own API docs describe the standard reporting path as on-demand list pricing, with cloud-provider cost-and-usage data available through integrations. The allocation model is useful immediately, but to reflect your committed discounts, private pricing, or billing exports, you have to wire that data in.
Neither of these is a flaw. They are just the boundaries of what the tool can do for you automatically.
Showback first, chargeback if your organisation actually wants it
FinOps discussions often make chargeback sound like the inevitable end state. In practice, most teams should start with showback.
Showback means the spend is visible to the people who influence it. The namespace or team sees a monthly figure, understands what drove it, and can act on it. Chargeback adds the accounting decision on top: that cost is posted back to a budget, cost centre, or P&L.
The FinOps Foundation's allocation guidance frames allocation as the foundation for either route. That is the useful way to think about OpenCost as well. It gives you a defensible allocation model and enough reporting surface to support showback immediately. Whether you turn that into formal chargeback is an organisational decision, not a Kubernetes feature flag.
The practical takeaway
If your current Kubernetes cost story is “the cluster costs £X and nobody can explain why”, OpenCost is a solid place to start. Install it against the Prometheus stack you already run, use the Allocation API for the numbers you want people to trust, include idle cost when you report by namespace or team, and use Prometheus for dashboards rather than trying to rebuild the cost model yourself. That gets you from one undifferentiated cluster bill to a showback report people can actually argue with usefully, which is a much better place to be than arguing with the invoice alone.
Top comments (0)