Cost Attribution
Overview
Cost attribution traces cloud spending back to the workloads responsible for it. Kubeadapt uses a bottom-up model that starts from cloud provider pricing and works down to individual containers.
The Cost Stack
Costs flow through four layers:
Cloud Provider Costs
Kubeadapt tracks four cost categories:
- Compute: EC2 (AWS), Compute Engine (GCP), Virtual Machines (Azure), or bare-metal nodes
- Storage: EBS (AWS), Persistent Disks (GCP), Azure Disks, and other attached volumes
- Network: cross-zone and egress traffic costs via the optional eBPF agent. The agent is developed and collects pod-to-pod traffic metrics. Cloud pricing integration (starting with AWS) is in progress and will ship alongside cloud account integration.
- Control plane: EKS, GKE, or AKS management fees (where applicable)
How pricing data is obtained
On-demand and spot pricing is fetched automatically from cloud provider public pricing APIs. No credentials or setup required. Spot prices refresh every 5 minutes, on-demand prices sync daily.
For non-cloud environments, Kubeadapt applies industry-standard default rates for CPU, memory, and GPU. You can override these with custom rates via the Kubeadapt dashboard.
How discounts are applied
Each node is priced based on its provisioning type. Spot nodes use real-time market prices fetched from cloud provider APIs. On-demand nodes use the published hourly rate for their instance type.
For AWS, connecting a cloud account lets Kubeadapt check whether on-demand nodes are covered by active Reserved Instances or Savings Plans. Covered nodes get the effective discounted rate instead of the full on-demand price. Spot nodes are not affected by RI/SP since they already use market-based pricing.
See the AWS integration guide for setup details.
Discount attribution for GCP Committed Use Discounts and Azure Reserved Instances & Savings Plans is planned. On-demand and spot pricing for both providers works out of the box today.
Node Cost Calculation
Node costs are determined by matching each node's instance type to the corresponding cloud provider pricing. Since cloud providers publish rates as hourly prices, Kubeadapt uses these hourly rates and projects them to monthly estimates.
The total hourly rate for a node is decomposed into per-unit rates for CPU (per core), memory (per GiB), and GPU (per unit). These per-unit rates are what drive container-level cost attribution.
Node cost also includes the node's own attached storage (e.g. root EBS volumes, boot disks), billed per GB-hour based on volume type and size. Persistent Volumes (PVCs) used by pods are tracked separately. See Storage costs below.
See the Metrics Glossary for detailed formulas.
Pod and Container Cost Calculation
Costs are calculated at the container level, not the pod level. Each container's cost is computed individually using the per-unit rates of the node it runs on, then aggregated upward: containers sum to pod cost, pods sum to workload cost, and so on up to namespace and cluster.
For each container:
CPU cost = max(CPU request, CPU usage) × node CPU rate ($/core/hr)
Memory cost = max(memory request, memory usage) × node memory rate ($/GiB/hr)
GPU cost = GPU request × node GPU rate ($/GPU/hr)The node CPU rate and node memory rate in these formulas are specific to the node each container is scheduled on. These rates differ based on the node's instance type, provisioning type (on-demand vs. spot), and whether it is covered by an RI or Savings Plan. The same container with identical requests will produce a different cost on a spot node than on an on-demand node.
For pods with multiple containers (e.g. sidecars, init containers), the pod cost is the sum of its container costs. For workloads with multiple replicas, each pod's cost is calculated independently based on its node. The workload detail view in the dashboard shows per-container metrics, and the Node Distribution view shows how workload cost is distributed across nodes.
The max(request, usage) approach means: if a container requests 2 cores but uses 0.5, it's charged for 2 cores (the reserved amount). If a container requests 1 core but bursts to 3, it's charged for 3 cores (the actual consumption). Over-provisioning waste and burst usage are both accounted for.
Only pods in the Running state generate cost based on actual resource consumption. Pods in non-running states (Pending, Failed, Succeeded) are tracked for observability but do not accumulate usage-based costs.
Storage costs
Persistent Volume costs are calculated per volume based on size and storage class, and tracked separately in the persistent volumes view. Storage costs are also included in namespace-level totals alongside workload compute costs.
Multi-replica workloads
Each pod's compute cost is calculated independently based on the node it runs on. Pods of the same workload can have different costs if they are scheduled on nodes with different instance types or pricing (e.g. on-demand vs. spot). Total workload cost is the sum of all its pod costs. Storage costs depend on PVC configuration (shared vs. per-replica).
Namespace and Team Allocation
Namespace cost is the sum of workload compute costs and persistent volume costs within it:
Namespace Cost = Σ (Workload Costs) + Σ (PV Costs)Costs can also be grouped by labels such as team, department, product, or owner, depending on how your workloads are labeled.
Shared and Unattributed Costs
Some costs don't map directly to workload pods:
- System overhead: kubelet, kube-proxy, and other node-level processes use resources from the gap between a node's total capacity and its allocatable capacity. Typically 0.3 to 0.5 vCPU per node. Not charged to any workload.
- Idle capacity: unused CPU and memory on nodes after all pod requests and system overhead are accounted for. Not distributed to workloads.
- Control plane fees: EKS, GKE, and AKS charge a management fee per cluster, added on top of total cluster cost. Not applicable to self-managed clusters.
These costs are reported separately in the cluster overview. Kubeadapt does not distribute shared costs to tenants. Instead, they are shown as a distinct category so you can see exactly how much of your cluster spending goes to workloads versus overhead and idle capacity.