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.
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-systemandlogging.
| Policy | Effect |
|---|---|
| Platform absorbs (default) | Idle and shared stay with the platform team |
| Proportional | Redistributed in proportion to each owner's direct cost |
| Hybrid | A 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:
- A label selector mapping you defined.
- The workload's own labels:
team,owner,projectfor team;cost_center,dept,departmentfor cost center;app,application,productfor application. - A namespace mapping.
- The cluster default.
- 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.
| Figure | Calculation | At 100% |
|---|---|---|
| Reconciled to invoice | (direct + shared + idle + unallocated) / billed cost in scope | All billed cost in scope is in the ledger, with an owner or listed as unallocated |
| Ownership coverage | Cost that resolves to a team or cost center / billed cost in scope | All 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
| Cost | Treatment |
|---|---|
| Nodes, volumes and load balancers of clusters with a reporting agent | In scope, at billed net amortized cost |
| Savings Plans, reservations, EDP and bundled discounts, credits, refunds, fees and tax on AWS | Already in the net amortized cost (AWS_USE_NET_COSTS) |
| Azure and Google Cloud | The cost in the export you connect: amortized cost or FOCUS on Azure, the detailed billing export on Google Cloud |
| Data center clusters | The rate card or amortized hardware cost takes the place of the invoice |
| Shared platform namespaces and idle capacity | In 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 transfer | Priced 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 databases | Out of scope. They appear in cloud cost reports with the rest of the bill |
| Clusters in the bill with no agent | Out of scope until an agent reports. Listed as billed, no agent in the fleet view |
| Days missing usage or billing data | Not 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.
| Situation | What happens | Window |
|---|---|---|
| The provider restates recent billing line items | Automatic: the daily billing read re-reads the last 3 days | Last 3 days |
| Usage or billing for a day arrives late | Automatic: the day is allocated again once both inputs are in | Last 7 days |
| A mapping or policy fix, or a gap older than 7 days | Manual: re-run allocation for the days affected | Up 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 day | 1 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.