Cost Allocation Model
Understanding how CostPilot calculates costs helps you interpret the numbers you see and identify the highest-value optimisation opportunities. This page explains the allocation model without getting into implementation details.
The core problem
A Kubernetes node has a single hourly cost (e.g. an AWS m5.xlarge at $0.192/hour). But it runs many pods simultaneously. How do you attribute that $0.192 fairly between them?
CostPilot uses a weighted allocation model that considers both CPU and memory requests to divide the node’s cost between the pods running on it.
How allocation works
Step 1 — Determine node cost
CostPilot fetches current pricing for each node’s instance type from your cloud provider, using the node’s region and pricing type (on-demand, spot, or reserved). This gives an hourly cost per node.
For spot instances, the spot price at the time of ingestion is used. For reserved instances, CostPilot applies the equivalent effective hourly rate.
Step 2 — Split into CPU and memory fractions
Node costs are split into a CPU fraction and a memory fraction based on ratios typical for each cloud provider and instance family:
| Provider | CPU fraction | Memory fraction |
|---|---|---|
| AWS (general purpose) | 50% | 50% |
| GCP (general purpose) | 50% | 50% |
| Azure | 50% | 50% |
| Custom (self-hosted) | Configurable | Configurable |
These ratios can be overridden per-cluster in Settings → Clusters if you have specific knowledge of your pricing structure.
Step 3 — Allocate to pods by requests
Within each node, CPU cost is distributed proportionally to each pod’s CPU requests. Memory cost is distributed proportionally to each pod’s memory requests.
Example:
A node costs $1.00/hour. Split 50/50: $0.50 for CPU, $0.50 for memory.
| Pod | CPU requested | Memory requested |
|---|---|---|
| Pod A | 500m | 512Mi |
| Pod B | 250m | 256Mi |
| Pod C | 250m | 256Mi |
| Total | 1000m | 1024Mi |
CPU allocation:
- Pod A: 500/1000 × $0.50 = $0.25
- Pod B: 250/1000 × $0.50 = $0.125
- Pod C: 250/1000 × $0.50 = $0.125
Memory allocation follows the same logic. Each pod’s total cost is the sum of its CPU + memory allocation.
Allocation is based on requests, not actual usage. A pod that requests 1 CPU and uses 100m CPU still gets billed for 1 CPU’s worth of cost — this is intentional, as requests represent the capacity that was reserved for that pod.
Step 4 — Idle cost
After allocating to pods, the remaining node capacity (capacity with no pod requesting it) is accounted for as idle cost. CostPilot tracks idle cost separately and shows it as a distinct line in the Dashboard and Cost Explorer.
See Understanding Idle Costs for details.
Storage costs
For clusters with PersistentVolumes, CostPilot includes storage costs where pricing data is available. Storage costs are attributed directly to the pod or StatefulSet using the volume.
System pods
Kubernetes runs system pods in the kube-system namespace (CoreDNS, kube-proxy, etc.). CostPilot includes these in the namespace breakdown under kube-system. Their cost is typically small but non-zero.
Accumulation and aggregation
Raw metric records are stored at 1-minute granularity. When you view a 7-day or 30-day time range, CostPilot aggregates these records into hourly or daily summaries. Costs in aggregated views are the sum of the underlying per-minute allocations.
Custom pricing
For self-hosted clusters or clusters where CostPilot doesn’t have access to provider pricing, you can set a custom per-node hourly rate in Settings → Clusters. This rate is applied uniformly across all nodes in that cluster.