Enable Cost Allocation for GKE
Last updated
To view pod-level GKE costs in OneLens, you need to enable GKE cost allocation on each cluster and make sure your Cloud Billing data reaches OneLens through the detailed BigQuery export:
GKE cost allocation: a per-cluster flag that stamps Kubernetes identity (cluster, namespace, workload, pod labels) onto your billing rows.
Detailed Cloud Billing export to BigQuery: the only export that carries these labels. The standard export does not.
GKE cost allocation is off by default and set per cluster. Every cluster you want split must be enabled individually.
There is no backfill. Labels only exist on usage generated after enablement, so any period before that date is permanently un-splittable. Enable this early.
Enable it per cluster using any of the following.
gcloud CLI:
gcloud container clusters update CLUSTER_NAME \
--enable-cost-allocationGoogle Cloud Console:
Go to Kubernetes Engine → Clusters and click the cluster name to open its details page.
On the Details tab, scroll to the Features section and click the edit (pencil) icon next to Cost allocation.
Tick Enable GKE cost allocation, then Save changes.
Enabling causes no node recreation, restart, or disruption. It is a control-plane metadata flag.
The Kubernetes labels are written only to the Cloud Billing detailed usage cost export. If you are on the standard export, the labels will appear to be missing.
In the Cloud Console, go to Billing → Billing export → BigQuery export.
Confirm Detailed usage cost is enabled and pointed at a BigQuery dataset.
Verify the export table name contains the _resource_ infix, e.g.:
PROJECT.DATASET.gcp_billing_export_resource_v1_XXXXXX_XXXXXX_XXXXXX
This is the same detailed export OneLens ingests, so no additional OneLens configuration is required once cost allocation is on.
Once enabled, GKE adds these Google-generated keys to the labels array of each billing row. OneLens reads them to attribute cluster spend below the node:
goog-k8s-cluster-name
Cluster name
Attribute costs by cluster (pair with project ID, since names aren't globally unique)
k8s-namespace
Namespace
Split costs by namespace
k8s-workload-name
Workload name
Attribute to a specific workload
k8s-workload-type
e.g. apps/v1-Deployment
Identify the controller (fully-qualified apiVersion-Kind)
k8s-label/${key}
Pod label value
Your own pod labels (team, env, service) propagate to billing
Request-based allocation: costs reflect resource requests, not consumption. A pod requesting 4 vCPU and using 0.1 is charged for 4.
Up to 3 days latency before data appears in Cloud Billing after enabling.
Standard clusters are the documented/tested target. On Autopilot the flag can be set but unsupported resources won't accrue (expect goog-k8s-unsupported-sku / goog-k8s-unknown / blanks).
Supported SKUs: vCPU, RAM, GPU, Persistent Disks, Cloud TPU v4+. A4/A4X instances and externally-managed nodes are not tracked.
Persistent Disks are attributed only when dynamically provisioned (PVC/ephemeral), access mode RWO/RWOP, and alive for at least 30 minutes.
Shared-CUD costs may land in goog-k8s-unsupported-sku instead of a real namespace.
50-label cap: pods with more than 50 Kubernetes labels surface none in billing.
BigQuery cost: enabling increases label/namespace cardinality, modestly raising BigQuery storage and query costs.
Last updated

