Skip to content
NewFinOps, Kubernetes and AI, on one platform
Book a demo
UnitVane docs
API referenceReleases

Cost allocation methodology

How a node's billed cost becomes a pod's cost, a team's cost and an idle line, step by step.

On this page

Node cost

For each node and day, KubeOn takes the billed, net amortized cost of the instance, VM or rate card entry behind it, joined on the node's provider ID. Discounts, commitments and credits are already in that number.

Pod cost

Node cost is split between CPU and memory (50/50 by default, set with CPU_COST_WEIGHT and MEMORY_COST_WEIGHT). Each pod receives the share of each resource equal to max(request, usage) divided by node capacity, for every hour it ran.

Where AWS split cost allocation data exists for a cluster-day, KubeOn uses AWS's per-pod cost directly and lays the agent's measured usage over it for efficiency. The collector-based split is the fallback.

Idle and shared cost

  • Infrastructure idle: node cost not claimed by any pod.
  • Workload idle: cost of requested capacity a pod did not use.
  • Shared: cost of platform namespaces such as kube-system, monitoring, ingress-nginx, cert-manager, istio-system and logging.
PolicyEffect
Platform absorbs (default)Idle and shared stay with the platform team
ProportionalRedistributed in proportion to each owner's direct cost
HybridA share you set stays with the platform; the rest is proportional

In views and reports you can also choose to share idle within each cluster, within each node, across everything by cost, show it separately, or hide it.

Ownership

Each workload resolves to a team, cost center and application, in this order:

  1. A label selector mapping you defined.
  2. The workload's own labels: team, owner, project for team; cost_center, dept, department for cost center; app, application, product for application.
  3. A namespace mapping.
  4. The cluster default.
  5. Unallocated.

Label keys are normalized at read time: case, separators and prefixes such as kubernetes.io/ are ignored, and aliases map other names to the same key. Values that look generated (hashes, long IDs) are not turned into teams.

Reconciliation and ownership coverage

KubeOn reports two separate figures for the same clusters, period and cost basis. A cost can be fully reconciled without having an owner: it stays visible as unallocated until someone claims it.

FigureCalculationAt 100%
Reconciled to invoice(direct + shared + idle + unallocated) / billed cost in scopeAll billed cost in scope is in the ledger, with an owner or listed as unallocated
Ownership coverageCost that resolves to a team or cost center / billed cost in scopeAll billed cost in scope has an owner

Daily, KubeOn compares the billed cost of each cluster's nodes, volumes and load balancers with the cost it allocated. Billed resources it cannot attribute are listed as unallocated with up to 200 resource IDs, never spread into idle. The node-to-billing match rate is reported per cluster and is healthy at 90% or above.

What is in scope

CostTreatment
Nodes, volumes and load balancers of clusters with a reporting agentIn scope, at billed net amortized cost
Savings Plans, reservations, EDP and bundled discounts, credits, refunds, fees and tax on AWSAlready in the net amortized cost (AWS_USE_NET_COSTS)
Azure and Google CloudThe cost in the export you connect: amortized cost or FOCUS on Azure, the detailed billing export on Google Cloud
Data center clustersThe rate card or amortized hardware cost takes the place of the invoice
Shared platform namespaces and idle capacityIn scope, in their own columns. They count toward ownership coverage once the idle and shared policy assigns them: to the platform team by default
Data transferPriced in the network cost view by transfer class and, with VPC flow logs, by namespace. Not part of the node, volume and load balancer reconciliation
Services outside Kubernetes, such as managed databasesOut of scope. They appear in cloud cost reports with the rest of the bill
Clusters in the bill with no agentOut of scope until an agent reports. Listed as billed, no agent in the fleet view
Days missing usage or billing dataNot allocated until both arrive, and named in Data health. Repaired automatically if the data arrives within 7 days; older days are re-run by hand, up to 92 days back. See late data and re-runs

Worked example

One cluster's in-scope bill for a month is $900: $600 for pods with team labels, $200 for kube-system and monitoring, and $100 for an EBS volume with no PersistentVolume. The same account also has $100 of Amazon RDS.

  • Reconciled to invoice: ($600 + $200 + $100) / $900 = 100%.
  • Ownership coverage, with the default policy that gives shared cost to the platform team: ($600 + $200) / $900 = 88.9%.
  • Unallocated: $100, or 11.1%, listed with the volume ID.
  • The $100 of RDS appears in cloud cost reports and in neither figure.

Late data and re-runs

KubeOn repairs recent days on its own. Older days are re-run by hand from Data health, by admins and platform engineers, and every run is logged.

SituationWhat happensWindow
The provider restates recent billing line itemsAutomatic: the daily billing read re-reads the last 3 daysLast 3 days
Usage or billing for a day arrives lateAutomatic: the day is allocated again once both inputs are inLast 7 days
A mapping or policy fix, or a gap older than 7 daysManual: re-run allocation for the days affectedUp to 92 days back
Billing for a day has left the hub (raw rows are kept 90 days by default)Manual: a billing backfill re-reads it from your export; run it before re-running that day1 to 366 days

Efficiency

Efficiency is cost-weighted: the sum of each resource's efficiency times its cost, divided by total cost. Waste is measured against usage the agent observed.

Need help with this guide?Contact support