Note

OpenCost: Kubernetes cost allocation by namespace and pod

The cloud bill knows the price of an instance, not the price of a service. OpenCost (CNCF Incubating) splits cluster spend by namespace and pod: the engine and its pitfalls, OpenCost vs Kubecost vs AWS SCAD, idle cost and the path to unit economics.

The cloud bill answers the question «how much does an EC2 instance cost», but stays silent on how much your payments-api costs. Dozens of workloads share a single node, and the bill cannot tell them apart. Per CNCF data for 2026, average Kubernetes cluster utilization sits at 35–50%: half of the paid capacity idles, and nobody sees whose half it is. Up to 35% of cloud spend is preventable waste, and the first reason it is not prevented is that there is nobody to charge it to. FinOps starts not with optimization but with allocation: who spends how much.

Why Kubernetes breaks cloud billing

Three problems that traditional cloud does not have. Shared infrastructure: billing operates on instances, not workloads — «EC2 = $X», but never «pod payments-api = $Y». The overprovisioning trap: an engineer whose service once died from OOM doubles the memory request; individually rational, collectively wasteful — and this defensive headroom is the main source of waste. The timing problem: a pod that burned excess memory for 72 hours and died three weeks ago is invisible in the monthly bill — slow billing signals never catch ephemeral resources.

Only one conclusion follows: cost has to be measured at pod level, in real time.

OpenCost: an engine, not a dashboard

OpenCost is a CNCF Incubating project (Apache 2.0) that grew out of the cost-allocation engine of Kubecost; contributors include AWS, Google and Microsoft, and the stated goal is to become «the Prometheus of cost monitoring». The mechanics are transparent: the engine takes Prometheus metrics (kube_pod_container_resource_requests) plus cloud pricing and splits it out: pod cost = CPU request × CPU-hour price + memory request × memory price + storage (PVC) + network. It installs with a single helm install pointed at Prometheus; the outside interface is an API like GET /allocation?window=1d&aggregate=namespace.

The main pitfall: the built-in OpenCost UI is a thin viewer, not a data store. It keeps a limited in-memory window and «loses» history after roughly a week — and that is not a bug. The intended architecture is different: OpenCost exports cost metrics back into Prometheus or VictoriaMetrics, and the dashboard lives in Grafana. Whoever builds reporting on the built-in UI quickly hits a wall.

OpenCost, Kubecost and AWS SCAD: two solutions, not three

A common confusion is to treat them as a three-way race. OpenCost and Kubecost are one class and one engine: real-time allocation inside the cluster. The choice between them is effort versus control: OpenCost is a vendor-neutral engine that needs Prometheus and Grafana; Kubecost is the same engine plus a UI with retention and savings recommendations, free for a single cluster, with multi-cluster and SSO starting at ~$449/month (the project is owned by IBM). For single-cluster EKS there is a free EKS-optimized bundle.

AWS SCAD is a different category: a billing feature that splits EC2 cost down to pod level right inside the billing data. The data lands only in CUR — Cost Explorer never sees it, querying goes through Athena. In return, SCAD reconciles with the real bill — Savings Plans, RI and Spot included, whereas OpenCost and Kubecost price everything at on-demand list rates and will not match the invoice. The mature setup keeps both: OpenCost or Kubecost for engineering efficiency («where is the waste right now»), SCAD for finance-grade chargeback («what to charge to which team»).

Idle cost and allocation rules

The base rule: namespace = team. Finer-grained — allocation by labels (team, cost-center, service). A pod without resources.requests is not allocated at all — there is nothing to charge it with; the requests requirement belongs in an admission policy via Kyverno or Gatekeeper.

A separate category is idle cost: (node capacity − sum of requests) × node price. Hiding it is not an option: either spread it pro rata across namespaces, or create a dedicated __idle__ namespace — so the very fact of overprovisioning stays visible on the dashboard. The anti-pattern is one namespace shared by several teams: allocation turns into fiction.

From allocation to unit economics

The next level is the cost of a business unit: cost per request, cost per tenant. A PromQL query divides the namespace cost metric by the business metric of the service — and the dashboard shows «$X per million requests, trending Y% per month». From there, cost becomes a quality gate just like error rate: an AnalysisTemplate in Argo Rollouts blocks the deploy when cost per request crosses the threshold.

For basic cases there is also a path without OpenCost: AWS imports K8s labels as Cost Allocation Tags, and «how much did team X spend» shows up directly in Cost Explorer. But idle allocation, network attribution and unit-economics queries stay out of reach on that path.

The rollout fits in a week: OpenCost exporting into Prometheus, a Grafana dashboard, labels on workloads, idle made explicit. The top 10 namespaces usually carry ~80% of the spend — start there. Mature FinOps practices reach 20–54% savings, but the first step is always the same: see who spends. Optimization without allocation is guesswork.

© 2026 axyi.ru · CC BY 4.0