Nov 7, New York: Romaric speaks at SREday NYC: SRE in the era of AI

Per-Team Cost Allocation and Chargeback Across Multiple Kubernetes Clusters (Without a FinOps Team)

A practical playbook for splitting Kubernetes and cloud spend per team, service, and environment across AWS, GCP, Azure, Scaleway, or your own clusters - four metadata keys, one cost engine, one monthly 30-minute ritual, and no FinOps hire.

Mélanie Dallé
Senior Marketing Manager
NOV 4, 2026 · 15 MIN
Per-Team Cost Allocation and Chargeback Across Multiple Kubernetes Clusters (Without a FinOps Team)

Key Points:

  • Three things, nothing more. Per-team cost allocation across multiple Kubernetes clusters needs four ownership metadata keys (team, service, environment, cost-center) enforced at deploy time, a cost engine that splits shared cluster spend by namespace or label, and one automated monthly report per team. A two-person platform team can ship all three in about 90 days.
  • Enforcement comes before reporting. A cost tool prices what exists. It cannot tell you who owns a namespace that shipped with no owner label. Hold unallocated spend under 10% (attributable above 90%), or teams dispute their line and the program dies.
  • Measure with open tooling, normalize with FOCUS. Use OpenCost (CNCF incubating, runs on any cluster on any cloud) as the baseline, add Kubecost, CloudZero, Vantage, or Finout for multi-cluster and cross-cloud rollups, and normalize bills with the FinOps Foundation FOCUS specification.
  • Showback first. Report each team's cost before you move any money. Showback plus a named cost owner per team changes behavior on its own, and most organizations under roughly 25-30 teams never need a chargeback ledger.
  • Where Qovery fits. Qovery is the enforcement layer: workloads deployed through it into your own AWS, GCP, Azure, Scaleway, or existing Kubernetes account carry consistent ownership context, idle non-production environments auto-stop, and the bill and Savings Plans stay in your account.

Qovery · Infrastructure control plane
A control plane for platform teams and their coding agents
Learn more

Cost allocation on Kubernetes is a metadata enforcement problem long before it is a tooling problem. That is why buying a cost tool almost never fixes it.

I have watched this play out the same way many times. Finance asks "which team is spending what?", someone installs a dashboard, and three months later 30% of the bill sits in a bucket called "unallocated" that nobody owns. This playbook is how I would do it again across several clusters and several clouds, with no FinOps hire.

What does per-team cost allocation on Kubernetes actually require?

Per-team cost allocation on Kubernetes requires three components: four ownership metadata keys (team, service, environment, cost-center) enforced at deploy time, a cost engine that divides shared cluster spend across workloads by namespace or label, and a recurring per-team report. Unit economics, commitment optimization, and real invoicing are optional in year one.

Treat four keys as the ceiling, because every key you add lowers compliance, and compliance is the whole game. Reuse the Kubernetes recommended label app.kubernetes.io/part-of for the service, and add custom keys like acme.io/team and acme.io/cost-center so you inherit a convention instead of inventing one.

KeyExample valueWhere it must be setWhat breaks if missing
teampaymentsKubernetes label and cloud tagThe workload lands in unallocated; no team sees it
service (app.kubernetes.io/part-of)checkout-apiKubernetes label and cloud tagTeam totals exist but nobody can find the expensive workload
environmentprod, staging, previewKubernetes label and cloud tagProd and non-prod blur; you cannot target idle staging
cost-centercc-4210Cloud tag (label optional)Finance cannot map the team total to a budget line

Kubernetes breaks naive cloud cost attribution because one node hosts pods from many teams. A single EC2, GCE, or Azure VM line item has to be divided by pod CPU and memory before anyone can be billed. The cloud bill has no concept of a namespace.

What you have to split, roughly from biggest to smallest:

  • Node compute. Usually the largest line, and the one that needs pod-level division.
  • Control plane fees. EKS charges $0.10 per cluster per hour in standard support and $0.60 in extended support (AWS EKS pricing). GKE charges a flat $0.10 per cluster per hour with a $74.40 monthly credit per billing account (Google Cloud GKE pricing). AKS Standard tier is $0.10 per cluster per hour (Azure AKS pricing). That is about $73 per cluster per month, multiplied by every cluster you run.
  • Load balancers, persistent volumes, and egress. Each billed as its own resource, each needing an owner.
  • Idle capacity. Nodes you pay for that no pod requested.

There are two allocation models. Requests-based allocation charges what the scheduler reserves: predictable, and it rewards right-sizing. Usage-based allocation charges what pods consume: fairer in the moment, volatile month to month, and it punishes bursty workloads. I recommend requests-based allocation, with idle capacity charged to the platform team as a visible line rather than smeared across teams. The platform team controls node sizing, so it should own the waste.

The day-one artifact is one table: cost by team, by environment, by month, with an explicit unallocated row at the bottom.

Why do most Kubernetes cost allocation projects fail in the first quarter?

Most Kubernetes cost allocation projects fail because the organization buys a cost tool and skips the metadata contract, so the unallocated bucket keeps growing until finance and engineering argue about whose numbers are wrong. The failure is almost never the tool's accuracy.

My rule of thumb from rollouts I have seen: past 10-15% unattributable spend, every team disputes its line and the report loses authority. The guardrail is attributable spend above 90%, measured weekly, with a named owner.

The failure modes repeat:

  • Retroactive labeling never happens. Nobody tags last quarter's namespaces. Every unlabeled deploy is permanent data loss, which is why enforcement has to come before reporting.
  • Shared services have no owner. Ingress controllers, the observability stack, CI runners, service mesh, secrets management, DNS. Decide upfront: split pro-rata by team consumption, or keep them as an explicit platform line. Both are defensible, as long as you write the rule down before the first report goes out.
  • Each cloud tags differently. AWS user-defined tags must be activated in the Billing console, and it can take up to 24 hours for keys to appear and another 24 hours to activate (AWS Billing docs). GCP allows 64 labels per resource, lowercase only (Google Cloud labels). Azure allows 50 tags per resource, and resources do not inherit resource group tags (Microsoft Learn).
  • The bill does not stop at the cluster. RDS, Cloud SQL, Azure Database, managed Redis, object storage, queues, and Kafka are often the larger half of the bill, and Kubernetes-only tooling routinely leaves them out.
  • Overprovisioning hides in plain sight. CAST AI measured that clusters use only 13% of provisioned CPU and 20% of memory on average across 4,000 clusters (CAST AI 2024 benchmark). Datadog found 83% of container costs tied to idle resources (Datadog State of Cloud Costs). Teams cannot right-size what they cannot see priced.
  • Forgotten preview and staging environments. The most common invisible line item and the easiest one to kill.

This is not a niche problem. Kubernetes drove cloud spend up for 49% of respondents in the CNCF FinOps microsurvey (CNCF), and organizations estimate 29% of their cloud spend is wasted (Flexera 2026 State of the Cloud).

Which tools actually give you Kubernetes cost allocation across AWS, GCP, Azure, and Scaleway?

OpenCost, a CNCF incubating project, is the vendor-neutral baseline that allocates Kubernetes spend by namespace, label, controller, or pod on any cluster on any cloud; Kubecost, CloudZero, Vantage, and Finout add multi-cluster aggregation, cross-cloud normalization, and chargeback reporting on top. None of them creates ownership labels for you, which is the most important thing to understand before buying anything.

  • OpenCost moved to CNCF incubating on October 25, 2024 (CNCF). Its allocation API aggregates by cluster, node, namespace, controller, service, pod, container, label, and annotation (OpenCost API docs). Free, but you run it, store the data, and build the cross-cluster rollup yourself. It works on Scaleway Kapsule or on-prem clusters as well as the hyperscalers.
  • Kubecost, now IBM Kubecost under Apptio, has a free Foundations tier covering unlimited clusters up to 250 cores with 15-day retention, and an Enterprise tier with a unified multi-cluster view (IBM Kubecost pricing). The natural upgrade path for an OpenCost shop.
  • CloudZero, Vantage, and Finout are billing-first. They ingest AWS, GCP, and Azure billing exports next to Kubernetes allocation data, with shared-cost rules and per-team views. Pick one when the non-Kubernetes half of the bill matters as much as the clusters.
  • Native cloud tooling is free and accurate but siloed. AWS split cost allocation data divides EC2 cost by each pod's CPU and memory share and adds aws:eks:namespace and aws:eks:workload-name tags to CUR (AWS docs). GKE and AKS offer equivalent GKE cost allocation and AKS cost analysis. None rolls up across clouds.
  • FOCUS is what makes multi-cloud normalization tractable. The current version is FOCUS 1.4, and AWS, Google Cloud, Microsoft, Oracle, and others already publish FOCUS-format exports (FinOps Foundation FOCUS). Normalize on FOCUS instead of hand-merging three billing schemas.
  • Kyverno and OPA Gatekeeper are the enforcement half of the stack, not measurement. Kyverno graduated in the CNCF on March 16, 2026 (CNCF), and Gatekeeper is part of the graduated Open Policy Agent project. Do not expect a cost tool to fix label hygiene.

Every measurement tool shares the same gap: it prices what exists and cannot guarantee that ownership metadata exists.

ToolMulti-cloudMulti-cluster rollupK8s granularityShared/idle splittingNon-K8s spendShowback/chargebackWho enforces labelsPricingWho runs it
OpenCostAny cloud, on-premDIYNamespace, label, controller, pod, containerYesPartial (cloud costs integration)Showback via API/UIYouFree, open sourceYou
IBM KubecostAWS, GCP, Azure, on-premEnterprise tierNamespace, label, controller, podYesPartialShowback, chargeback reportsYouFree tier, paid EnterpriseYou or SaaS
CloudZeroAWS, GCP, Azure + SaaSYesVia K8s agentYesYesYesYouCommercialVendor SaaS
VantageAWS, GCP, Azure + SaaSYesVia K8s agentYesYesYesYouFree tier, paid plansVendor SaaS
FinoutAWS, GCP, Azure + SaaSYesVia K8s integrationYesYesYesYouCommercialVendor SaaS
AWS Cost Explorer + EKS split cost dataAWS onlyAcross EKS clusters in AWSNamespace, workload, podPartialAWS servicesShowbackYouFreeAWS
GKE cost allocationGCP onlyAcross GKE clustersNamespace, labelPartialGCP servicesShowbackYouFreeGoogle
Azure Cost Management for AKSAzure onlyAcross AKS clustersNamespacePartialAzure servicesShowbackYouFreeMicrosoft
Kyverno / OPA GatekeeperAny clusterPolicy per clusterN/A (enforces labels)NoNoNoThe policy engineFree, open sourceYou
QoveryAWS, GCP, Azure, Scaleway, BYO K8sOrg-wide view of envs and clustersN/A (not a cost tool)NoNoNoThe platform: ownership is structuralQovery subscription; cloud bill stays in your accountQovery (control plane), you (cloud account)

How do you enforce ownership labels so nothing lands in the unallocated bucket?

The only enforcement that holds is making it impossible to ship without ownership metadata on the deployment path: an admission policy that rejects or mutates unlabeled workloads, a templated pipeline that injects the four keys, or an internal developer platform where metadata is structural. Documentation and Slack reminders do not work, and the unallocated bucket proves it.

Three options, from strongest coverage to most structural:

  • Option 1: admission control with Kyverno or OPA Gatekeeper. Mutate to inject defaults, validate to reject Deployments and Namespaces missing the keys. Strongest coverage per cluster. You own the policy lifecycle, the exception process, and the break-glass path, on every cluster.
  • Option 2: Terraform modules, Helm templates, and a CI check. Covers the paved road well. A manual kubectl apply or a console click bypasses it. Good first step, insufficient alone.
  • Option 3: an internal developer platform. Every workload ships through one path, so ownership is a property of the object instead of a policy someone forgets to apply.

Then mirror the same four keys into cloud resource tags, so managed databases, buckets, queues, and load balancers carry the same owner as the pods that call them.

Kubernetes labels do not automatically become cloud tags on the underlying node, EBS or Persistent Disk volume, or load balancer. You configure that mapping per cloud, through storage class parameters, load balancer annotations, and node pool tags. This is where most teams silently lose coverage.

In a multi-cluster estate, ship the policy as code from one repo to every cluster, so cluster number twelve does not drift from cluster number one. Then operationalize the guardrail:

  • A weekly "percentage of spend attributable" number posted in the platform channel.
  • One named person responsible for keeping it above 90%.
  • A hard stop on new exceptions whenever it drops below.
Ship faster on infrastructure you control.
Qovery gives your teams self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster - with per-environment ownership and auto-stop on idle environments. Start deploying in under 10 minutes.

How do you run showback and chargeback without a dedicated FinOps team?

Run it as a monthly 30-minute ritual owned by one platform engineer: one automated per-team report, one named cost owner per team, one review in the engineering leadership meeting, and three actions committed before the next one. The whole thing costs a few hours per month of one engineer's time.

The report contains exactly five things in version one:

  • Cost by team
  • Prod versus non-prod split
  • Month-over-month trend
  • Top five movers
  • Unallocated percentage

Extra columns kill adoption. Push the report to people: a Slack or email digest beats a dashboard nobody opens. Put the unallocated percentage on the first line so it stays embarrassing.

The quick wins that usually pay for the whole program:

  • Stop idle non-production environments outside working hours. A dev environment running 11 hours a day on weekdays runs 55 of 168 weekly hours, so you stop paying for roughly two thirds of its compute.
  • Right-size requests once teams see requested versus used priced in dollars.
  • Delete orphaned persistent volumes and idle load balancers.
  • Set TTLs on preview environments.

This matches where the industry is. Workload optimization and waste reduction is the top priority in the State of FinOps 2026, across 1,192 respondents representing more than $83bn in cloud spend (FinOps Foundation State of FinOps). The Foundation's crawl/walk/run model also notes that chargeback is not required in every organization (FinOps Foundation).

You genuinely need a FinOps hire when you have one of these: commitment and Savings Plan portfolio management across hundreds of accounts, true inter-business-unit invoicing with finance sign-off, audited or regulated cost reporting, per-customer unit economics, or roughly 25+ teams sharing one bill. Below that line, tooling plus a ritual beats a headcount.

How does Qovery give you per-team cost allocation across clusters and clouds?

Qovery makes attribution structural instead of policy-enforced: every application, environment, and cluster deployed through Qovery runs in your own cloud account and carries its organization, project, and environment context across AWS, GCP, Azure, Scaleway, or your existing Kubernetes clusters. Qovery does no cost measurement itself; it supplies the enforcement layer that makes OpenCost, Kubecost, CloudZero, Vantage, or Finout produce a split teams accept.

What that means in practice:

  • The bill stays yours. With BYOC, the cloud bill, negotiated discounts, and Savings Plans or committed-use discounts stay in your own account and your own name. Your billing data never passes through a vendor's billing layer.
  • The hierarchy is the chargeback dimension set. Qovery's organization, project, environment, and service hierarchy maps onto team, product, environment, and workload before anyone writes a label policy.
  • Labels are centrally managed. Labels and annotations groups are defined once at the organization level and attached to applications, cron jobs, lifecycle jobs, and databases. The "Propagate as Tag" option forwards labels to cloud resources; today it covers managed databases and AWS clusters.
  • The cost owner is a platform object. Per-environment RBAC names who owns each environment instead of a spreadsheet column.
  • Idle non-prod stops itself. Deployment Rules set auto-start and auto-stop schedules by day and timezone, for example weekdays 8 AM to 7 PM, applied by pattern to dev-* or every preview environment.
  • Preview environments are ephemeral. One per pull request, removed when the PR closes, so they never pile up as unowned spend.
  • Managed databases stay in your account. They land in the same billing export as everything else and carry the same tags.

What does a realistic 90-day rollout look like?

A realistic rollout takes three phases over 90 days: instrument and baseline in weeks 1-4, enforce and clean up in weeks 5-8, report and act in weeks 9-12. The day-90 definition of done is one automated monthly per-team report with unallocated spend below 10% across every cluster.

  • Weeks 1-4. Agree the four keys with engineering leadership. Deploy OpenCost or enable native cost allocation on every cluster, aggregate into one store (FOCUS-normalized if you run more than one cloud), and record today's unallocated percentage.
  • Weeks 5-8. Enforce the keys on the deploy path. Tag managed services with the same keys. Publish the shared-cost policy in writing. Drive unallocated below 10%.
  • Weeks 9-12. Automate the monthly digest, name a cost owner per team, run the first leadership review, and ship the top three savings actions.

Skip in year one: per-customer unit economics, true inter-business-unit invoicing, and cross-cloud commitment optimization.

PhaseWeeksDeliverableOwnerSuccess metric
Instrument1-4Four keys agreed and documentedVP Eng + platform leadKeys published, signed off
Instrument1-4Cost engine on every clusterPlatform engineerEvery cluster reporting into one aggregate
Enforce5-8Deploy-path enforcement livePlatform engineerNew unlabeled workloads rejected or defaulted
Enforce5-8Managed services taggedPlatform engineer + team ownersSame four keys on databases, buckets, LBs
Enforce5-8Shared-cost policy publishedPlatform leadWritten rule for ingress, observability, idle
Report9-12Monthly per-team digestPlatform engineerFirst digest sent, unallocated below 10%
Act9-12Top three savings actionsTeam cost ownersNon-prod auto-stop, worst offenders right-sized, orphans deleted

How do I set this up from Claude Code or Cursor?

Install the Qovery Agent Skills once and your coding agent can create environments, inspect them, and apply cost actions against your own cloud account, with every write action requiring your explicit approval. The Qovery MCP Server is read-only by default.

Install globally for every compatible agent (Claude Code, Cursor, Codex, OpenCode, Gemini CLI):

BASH
curl -fsSL https://skill.qovery.com/install.sh | bash

Or scope it to one project:

BASH
curl -fsSL https://skill.qovery.com/install.sh | bash -s -- --project

Add the MCP Server to Claude Code (OAuth, read-only by default):

BASH
claude mcp add --transport http qovery https://mcp.qovery.com/mcp --callback-port 4242

Enable write access only when you want it. This also requires enabling write access in the Qovery Console:

BASH
claude mcp add --transport http qovery "https://mcp.qovery.com/mcp?read_write=true" --callback-port 4242

Skills deploy (qovery-onboard, qovery-deploy, qovery-troubleshoot, qovery-optimize, qovery-speedup, qovery-preview, qovery-terraform); the MCP Server operates what already exists. qovery-optimize is the one for cost work. Then ask in plain language: "show me which environments cost the most this month and stop the idle non-production ones."

Docs: AI agent quickstart and Qovery for Claude Code. For the wider tool landscape, see our FinOps tools roundup.

Frequently asked questions
How do you get per-team cost allocation and chargeback across multiple Kubernetes clusters?

Enforce four ownership keys (team, service, environment, cost-center) on every workload at deploy time, run a cost engine such as OpenCost on every cluster, and aggregate the results into one store. Send each team a monthly report with an explicit unallocated row, and keep unallocated spend under 10%. Start with showback and add chargeback only if finance requires it.

How do you allocate shared Kubernetes costs like the control plane, ingress, and idle nodes to teams?

Split node compute by each team's CPU and memory requests, then pick one written rule for shared services: pro-rata by consumption or a visible platform line. Control plane fees are about $73 per cluster per month on EKS, GKE, and AKS Standard, so split them by the team's share of the cluster. Charge idle capacity to the platform team, because it controls node sizing.

What is the difference between showback and chargeback in Kubernetes FinOps?

Showback reports each team's cost with no money moving. Chargeback is an internal invoice that debits a business unit's budget. The FinOps Foundation says showback is always required, while chargeback depends on your accounting policies.

Can you do multi-cloud cost allocation across AWS, GCP, Azure, and Scaleway without a dedicated FinOps engineer?

Yes. Run OpenCost on every cluster, normalize cloud bills with the FOCUS specification (currently version 1.4), and enforce the same four keys as labels and cloud tags everywhere. One platform engineer can run it in a few hours per month after a 90-day setup.

Is OpenCost enough for per-team chargeback, or do you need Kubecost, CloudZero, Vantage, or Finout?

OpenCost is enough for single-cluster or small multi-cluster showback if you build the aggregation and reporting yourself. Move to IBM Kubecost Enterprise when you need a unified multi-cluster view and longer retention than the free tier's 15 days. Pick CloudZero, Vantage, or Finout when managed services and SaaS spend matter as much as the clusters.

How do you stop untagged workloads from creating an unallocated cost bucket?

Block them on the deploy path with Kyverno or OPA Gatekeeper admission policies, templated pipelines, or an internal developer platform where ownership is structural. Mirror the same keys to cloud tags, because Kubernetes labels do not propagate to volumes, nodes, or load balancers on their own. Track the attributable percentage weekly with a named owner.

At what point does a company actually need to hire a FinOps specialist?

Hire when you manage commitments across hundreds of accounts, need true inter-business-unit invoicing with finance sign-off, have audited cost reporting, track per-customer unit economics, or have roughly 25+ teams on one bill. Below that, tooling plus a monthly 30-minute ritual is enough.

Mélanie Dallé
About the author
Mélanie Dallé

Melanie leads content at Qovery. She covers platform engineering trends, Kubernetes operations, FinOps, and the tools that help engineering teams ship faster.

Next step

Ship faster on infrastructure you control.

Qovery gives your teams self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster - with per-environment ownership and auto-stop on idle environments. Start deploying in under 10 minutes.