How It Works
When network cost collection is enabled, the Vantage Kubernetes agent Helm chart deploys a per-node network collector that runs as a DaemonSet. The collector reads Linux connection-tracking (conntrack) data on each node, attributes each pod’s traffic, and classifies the transmitted bytes into mutually exclusive billing buckets by destination. The agent pulls these per-pod summaries each report cycle and joins them with your provider’s data transfer rates to produce a per-pod network cost.
Click to view the network cost pipeline
Click to view the network cost pipeline
Network Cost Attribution vs. Network Flow Reports
Network Cost Attribution is different from Network Flow Reports. Network Flow Reports use VPC Flow Log data to analyze source/destination flows and route classification at the cloud-provider level (answering “where is my traffic going?”). Kubernetes Network Cost Attribution allocates pod-level network cost using connection-tracking data observed inside the cluster (answering “which workload owns this network spend?”). It classifies traffic by destination type (intra-zone, intra-region, cross-region, internet, and more) rather than showing individual destination addresses. The two features are complementary: use Network Flow Reports when you need to investigate where specific traffic is going, and use Kubernetes Network Cost Attribution when you need to put a per-pod dollar amount on network spend and charge it back to a team.Supported Providers
Network Cost Attribution supports the following providers at launch:- Amazon Elastic Kubernetes Service (EKS)
- Azure Kubernetes Service (AKS)
- Google Kubernetes Engine (GKE)
Oracle Cloud (OKE) and on-premises clusters are not supported at launch. AWS network discovery and S3 path-aware pricing are available on EKS only; other supported providers use manual subnet configuration.
Prerequisites
Before you enable network cost collection, ensure you meet the following requirements:- A working Vantage Kubernetes agent integration.
- Vantage Kubernetes agent version 1.3.3 or later, available as part of Helm chart version 1.9.5 or later. This version includes the network collector, AWS network discovery, and the collector metrics endpoint.
-
Connection-tracking byte accounting must be enabled on every node. Set the
net.netfilter.nf_conntrack_acct=1sysctl cluster-wide before traffic is generated. When this is off (the default on many node images), the kernel leaves conntrack byte counters at zero, so the collector cannot attribute traffic. Only connections opened after the sysctl is set receive counters.nf_conntrack_acctis a node-level kernel setting that Vantage and the Helm chart cannot enable for you. It’s applied through your node configuration, so it’s typically handled by whoever manages your cluster’s nodes. To check whether it is already on for a node (a value of1means it is):After it’s enabled, confirm it took effect with thevantage_collector_conntrack_acct_enabledmetric (see Monitor the Collector); the collector also logs a warning at startup when byte accounting is disabled. -
The collector runs as a DaemonSet with host network access and an elevated security context (the
NET_ADMINcapability) so it can read conntrack for local pods. The Helm chart configures this for you (hostNetwork: trueandcapabilities.add: ["NET_ADMIN"]). Its ServiceAccount needs read-only (get/list/watch) access to pods, nodes, and ConfigMaps.
Enable Network Cost Collection
Enable the collector and provide your subnet configuration through the Vantage Kubernetes agent Helm chart.1
Enable
net.netfilter.nf_conntrack_acct=1 on every node (see Prerequisites).2
Set
agent.networkCost.enabled=true and populate agent.networkCost.subnets with your cluster’s destination CIDRs. See Configure Subnets for how to inventory them. For example:3
Upgrade the agent to apply the changes:
Configure Subnets
The collector compares each flow’s remote IP with your subnet map to classify it asin_zone, in_region, or cross_region. Populate agent.networkCost.subnets with the private destination CIDRs your workloads can reach: cluster subnets, peered networks, private managed services, and overlay pod CIDRs where applicable.
Keep the following guidelines in mind when defining your subnets:
- A
zoneenables same-zone classification. When only aregionis supplied, all same-region matches are reported asin_region. The region is derived from the zone when omitted (for example,us-east-1aresolves tous-east-1). - On a dual-stack cluster, add both IPv4 and IPv6 ranges. IP families are matched independently.
- The collector does not assume that an unmatched private address is internet traffic. It reports the traffic as
unknownuntil you add the CIDR or an override.
- AWS / EKS
- Azure / AKS
- Google Cloud / GKE
AWS subnets are Availability Zone scoped. List every IPv4 subnet in a VPC in the same Add the results to your Helm values:
cidr/zone shape used by the Helm value:Overlay Networks and Pod CIDRs
Overlay networking (for example, Calico, Cilium, kubenet, or GKE VPC-native networking) can allocate pod addresses outside the node’s primary VPC/VNet subnet. When a remote pod address does not match an entry insubnets, it is classified as unknown. Add the relevant pod CIDR with the cluster’s zone or region:
NAT, Peering, and Overrides
Useoverrides to force a bucket for a destination CIDR. Overrides take precedence over subnet entries, and the most-specific CIDR wins. Use them when destination ownership or topology cannot be represented accurately by a zone/region map.
A managed NAT gateway normally source-NATs traffic on its way to a public destination; it is not the remote IP visible in the pod’s conntrack flow. Do not add its private address merely to classify ordinary internet egress. The public destination already falls into
internet. Reserve NAT overrides for cases where a NAT or proxy appliance is itself the remote endpoint. For a same-region peered VPC, prefer a normal subnets entry with its actual region rather than a cross_region override.Validate the Rendered Configuration
After you apply the Helm values, inspect the ConfigMap mounted by the network collector to confirm your configuration rendered correctly:subnets: and overrides: (the latter may be an empty list).
Optional AWS Network Discovery (EKS)
On EKS, you can let the agent discover your network topology automatically instead of maintaining subnet lists by hand. Enable it withagent.networkCost.discovery.enabled=true.
Discovery has two benefits:
- Turnkey subnet inventory: Classification depends on knowing every subnet CIDR in the cluster’s VPC(s) and each subnet’s zone/region. Maintaining that list by hand is error-prone and drifts whenever someone adds a subnet, AZ, or VPC. Any missed subnet classifies traffic as
unknownorinternetinstead of the correct bucket. Discovery enumerates all subnets in the tagged VPC(s) directly from the EC2 APIs, so the inventory stays complete and current. With discovery on, the manual subnet list can be as small assubnets: []plus any human-only overrides. - Accurate S3 egress pricing: The S3 path-aware buckets exist because the cost of reaching S3 depends on how each source subnet egresses (a gateway VPC endpoint is free; a NAT gateway is not). Discovery resolves each subnet’s S3 egress path and fetches the regional S3 prefix lists automatically, so S3 traffic is priced correctly without hand-authored fields.
ec2:DescribeSubnetsec2:DescribeRouteTablesec2:DescribeManagedPrefixListsec2:GetManagedPrefixListEntries
Grant these permissions with Terraform
Grant these permissions with Terraform
Discovery is fail-closed. If the region cannot be resolved, credentials are missing, or the permission probe fails, the agent logs a warning and leaves discovery off. It does not crash-loop, and classification continues on the manual subnet configuration.
Billing Buckets
Transmitted bytes are grouped into mutually exclusive buckets. Each bucket is priced by the destination and, for S3-bound traffic, by how the source subnet egresses. The label in the first column is what appears in Cost Reports. The configuration key is the value you use in a subnet override.The S3 path-aware buckets require AWS network discovery. Without it, S3 traffic falls through to standard destination matching (often Internet Egress). Rates are blended per-GB rates derived from your provider’s actual data transfer charges over the month.
View Network Costs in Cost Reports
Pod-level network costs appear in Cost Reports under the Kubernetes provider, alongside compute, memory, GPU, and storage costs. To isolate network costs, filter the Kubernetes provider by Category and select network. Thevntg:category tag also works and is the same pattern used for CPU, RAM, GPU, and storage (see Filter by CPU, RAM, Storage, and GPU).
Network costs are not part of Kubernetes Efficiency Reports. Efficiency Reports measure utilization of provisioned capacity, whereas network traffic is charged per byte and has no notion of idle reserved capacity. Network costs can still surface optimization opportunities, such as cross-AZ traffic, NAT gateway processing, internet egress, or inefficient S3 routing, through Cost Reports.
1
Create or open a Kubernetes Cost Report.
2
Add a filter: All costs from Kubernetes where Category is network. (Filtering by Tag vntg:category is network works too.)
3
Use the report’s Group By menu to break the network costs down. Group by Subcategory to see the destination breakdown (Intra-Zone Egress, Intra-Region Egress, Cross-Region Egress, Internet Egress, and the S3 paths), which shows how a workload’s traffic is classified. To roll network costs up to the owning team or application, group by Tag and choose the
namespace tag, a workload label, or a Virtual Tag. On Kubernetes Cost Reports, namespace and labels are surfaced as tags.team tag or allocating shared costs by usage—see Virtual Tagging Examples.
Example: Charge Network Costs Back to a Team
Suppose unallocated network spend currently lands on your platform team, and you want each application team to own its network costs alongside compute. If your workloads are labeled with a team identifier (for example, ateam pod label or the app.kubernetes.io/part-of label), you can roll network costs up to that team.
1
Confirm the label is collected by the agent. Labels matching
app.kubernetes.io/* are collected by default; to collect a custom label such as team, add it to the agent’s allowed labels. Collected labels appear as tags on Kubernetes cost rows, including network rows.2
(Optional) If team names vary across clusters or providers, create a
team Custom Value Virtual Tag that maps the underlying labels and namespaces to standardized team values.3
Open a Kubernetes Cost Report and group by your
team tag. To view only the network portion, add the filter where Category is network; to show each team’s full Kubernetes bill, leave the category filter off so network rolls up alongside compute, memory, GPU, and storage.Troubleshooting
If network reporting looks empty or incomplete, check the following in order. The agent and collector expose Prometheus metrics (see Monitor the Collector) that correspond to each check.1
Collector coverage gaps
Confirm a collector is running on every node. A missing collector (from scheduling, a crash loop, or a taint without a matching toleration) means those nodes report no network costs. Add tolerations for any tainted nodes you want network costs from.
2
Connection-tracking accounting disabled
If
net.netfilter.nf_conntrack_acct is not enabled, byte counters stay at zero and no traffic is attributed, even when the collector is healthy. Enable the sysctl cluster-wide, and remember that only connections opened afterward receive counters.3
Agent cannot pull from a collector
If the agent cannot retrieve reports from a collector, or has not succeeded within your report interval, network data will be stale or missing for that node’s pods.
4
Traffic shown as Unclassified Egress
Costs appearing under Unclassified Egress (the
unknown bucket) mean a private destination CIDR is missing from your configuration. Add the subnet (or an override), or enable AWS network discovery on EKS.5
Short-lived pods
Very short-lived pods may not be captured if your collection interval is coarse. Tune the Kubernetes polling interval based on the shortest-lived workload you need to attribute.
Monitor the Collector
The agent exposes network metrics on its existing metrics endpoint (default port9010), and the network collector exposes its own metrics endpoint (default port 8883). Point your Prometheus scrape configuration at both. The following series are the most useful for catching silent failures and undercounting in cases where pods look healthy but network data is missing, stale, or incomplete.
The following Prometheus alert rules are useful starting points. Tune the stale-pull threshold to match your deployed report interval (the example assumes the default ~1 hour interval).