Connect a Kubernetes cluster

Install OpenCost and the CostGlass exporter in your cluster so cost data is pushed to CostGlass every 15 minutes.

Connect a Kubernetes cluster

Install the open-source OpenCost agent in your cluster and a small CostGlass exporter that sends cost data to CostGlass every 15 minutes.

Where in CostGlassSettings → Cloud Accounts → Kubernetes
PlanThe Kubernetes Costs page needs the Growth plan or above
Who can do thisAnyone who can sign in can generate the instructions; you also need cluster-admin on the cluster
Time neededAbout 15 minutes
In short
  • CostGlass never connects to your cluster. A small CronJob inside the cluster sends cost data out to CostGlass over HTTPS. Nothing is opened inbound.
  • Two things are installed: OpenCost (with Prometheus, which it needs) and the CostGlass exporter (a Secret, a ServiceAccount with read-only access, and a CronJob).
  • The install commands are generated for you, with a private ingest token for that one cluster. Copy them, run them, and the cluster appears by itself.
  • The first data usually appears within about 15 to 30 minutes, once the CronJob has run and Prometheus has collected some history.
  • Disconnecting a cluster revokes its token and deletes its stored live cost data.

How it works

Kubernetes does not send you a bill. Your cloud bills you for the machines (nodes) that the cluster runs on, and Kubernetes then shares those machines between many applications. To say what each team or application costs, you need to measure how much CPU, memory and storage each one uses and price it. CostGlass does this with OpenCost, an open-source cost tool from the CNCF (the foundation behind Kubernetes).

1
Prometheus collects metrics
Prometheus is a metrics database that runs inside the cluster. OpenCost reads container CPU and memory figures from it. Without Prometheus, OpenCost cannot start properly.
2
OpenCost prices them
OpenCost works out the cost of every namespace, workload and pod, using your cloud's prices. It also reports carbon estimates when the carbon option is turned on.
3
The CostGlass exporter pushes the result
A CronJob named costglass-opencost-exporter runs every 15 minutes. It asks OpenCost for the numbers, and optionally asks the Kubernetes API for pod, node and storage health, then sends everything to CostGlass in one HTTPS request.
4
CostGlass stores and shows it
CostGlass keeps the cost allocations and a daily history, and shows them on the Kubernetes Costs page.
Nothing inbound, and read-only
The exporter only makes outbound HTTPS calls. CostGlass has no network path into your cluster and no write access to it. The one extra permission the exporter asks for is read-only: get and list on pods, nodes and persistent volume claims, used for the Health tab and to discover your nodes. It is optional.

This is separate from your cloud-account connections (AWS, Azure and so on). You do not need an AWS or Azure connection to use Kubernetes Costs, but if you have one, CostGlass can compare its Kubernetes figures with what the cloud actually billed (see reconciliation).

Supported clusters

OpenCost itself works on any Kubernetes cluster. CostGlass changes only two things per provider: one OpenCost setting and the provider label stored with the data.

Choice in the formCluster typeWhat the install command does
AWS (EKS)Amazon EKSAdds --set opencost.exporter.cloudProvider=aws.
Azure (AKS)Azure AKSAdds cloudProvider=azure.
Google Cloud (GKE)Google GKEAdds cloudProvider=gcp.
Oracle Cloud (OKE)Oracle OKENo cloudProvider flag. OpenCost detects Oracle itself and prices nodes from Oracle's public price list. No Oracle credentials are involved.
DigitalOcean (DOKS)DigitalOcean DOKSAdds cloudProvider=custom.
Linode (LKE)Linode LKEAdds cloudProvider=custom.
Bare Metal / OtherSelf-managed or any other cluster (the Cloud Accounts form option)Not specially recognised by the server, so it is treated as AWS-style settings. See the note below.
Note
The server also recognises Alibaba Cloud (ACK) and Civo if a provider of alibaba or civo is requested, but the connect forms do not offer them. For a cluster that is not listed, use the closest option and check the figures: node prices for providers without a price source in CostGlass are not added (see Kubernetes Costs). The "Bare Metal / Other" choice has not been specially tested by us.

The in-app "Connect OpenCost Agent" window on the Kubernetes Costs page offers six buttons: EKS, AKS, GKE, OKE, LKE and DOKS.

Before you begin
  • A Kubernetes cluster you can reach with kubectl, and permission to create namespaces, ClusterRoles and CronJobs (cluster-admin is the simple way).
  • helm version 3 installed on the computer you will run the commands from.
  • Outbound HTTPS from the cluster to the CostGlass API (api.costglass.com for the UK region, your own region's API address otherwise). No inbound rules are needed.
  • A cluster that can pull images: the exporter uses the public python:3.11-alpine image and installs one Python package (requests) when it starts, so it needs internet access to the image registry and to PyPI.
  • A plan that includes Kubernetes Costs (Growth or above) to see the data page. The connection form itself is available on every plan, within your plan's connection limit.

Connect a cluster, step by step

There are three places that open the same form: Settings → Cloud Accounts (the Kubernetes tab), the onboarding page (Kubernetes, labelledOpenCost Agent), and the Connect OpenCost Agent button on the Kubernetes Costs page. The first two share exactly the same screen.

Settings → Cloud Accounts → Kubernetes: connected clusters at the top, and the form to connect a new one below.
1
Open the form
Go to Settings → Cloud Accounts and choose the Kubernetes tab. Any clusters already connected are listed under Connected Clusters.
2
Name the cluster
Under Connect a New Cluster, type a name in Cluster Identifier, for example production-eks or gke-main. This name is how the cluster appears everywhere in CostGlass. Use a short, unique name; it is part of the token, so changing it later means a new connection.
3
Choose the underlying cloud
In Underlying Cloud / Infrastructure pick AWS (EKS), Azure (AKS), Google Cloud (GKE), Oracle Cloud (OKE), DigitalOcean (DOKS), Linode (LKE) or Bare Metal / Other.
4
Generate the instructions
Click Generate Install Instructions. CostGlass creates (or reuses) an ingest token for this cluster name and shows the commands. Your token is inside the generated manifest, so treat it like a password.
5
Run the Helm commands
Copy the block under 1. Install Prometheus + OpenCost via Helm and run it in a terminal that points at the right cluster. See the next section for what it contains.
6
Apply the CostGlass agent manifest
Copy Copy Complete Manifest, save it as costglass-agent.yaml, and run kubectl apply -f costglass-agent.yaml.
7
Wait for the first push
The page checks every 15 seconds. When the cluster reports in, a message says Cluster "your-name" is reporting cost data. You can also click I've Deployed OpenCost to finish without waiting; data appears once the exporter has pushed.
Do not share the manifest
The manifest contains this cluster's ingest token. Anyone with it can send cost data into your organisation under that cluster name. Keep it out of public repositories. If it leaks, disconnect the cluster (this revokes the token) and connect it again.

What is generated, exactly

1. The Helm commands

The commands install Prometheus (skip that step if you already run Prometheus at prometheus-server.prometheus-system) and then OpenCost into a namespace called opencost. For an EKS cluster they look like this (the cloud setting changes with your choice):

Helm commands (EKS example)
Note
The Prometheus step turns off its persistent volume, so Prometheus loses its history if its pod restarts. OpenCost then measures from a fresh start. For production, use your own Prometheus setup if you need long, durable history.

opencost.carbonCost.enabled=true switches on OpenCost's own carbon estimates, which feed the Carbon tab.

2. The agent manifest (costglass-agent.yaml)

One file with four things in the opencost namespace:

ObjectNamePurpose
Secretcostglass-exporter-tokenHolds INGEST_TOKEN, the private token for this cluster.
ServiceAccountcostglass-opencost-exporterThe identity the exporter runs as.
ClusterRole and ClusterRoleBindingcostglass-opencost-exporter-health-readerRead-only: get and list on pods, nodes and persistentvolumeclaims. Optional.
CronJobcostglass-opencost-exporterRuns every 15 minutes (*/15 * * * *), one run at a time, using the python:3.11-alpine image with a small memory and CPU limit (64 to 256 MiB, 50 to 200 millicores).

The CronJob each time does the following:

  • Asks OpenCost (inside the cluster) for allocations over the last hour in 15-minute steps, grouped by namespace, controller, pod and workload kind, plus the labels app, env and team. Idle cost is included and the kube-system, istio-system and monitoring namespaces are treated as shared.
  • Asks OpenCost for its carbon estimate for the last hour. If this fails (older OpenCost, or the carbon flag was not set), it logs a warning and carries on.
  • Asks the Kubernetes API, using its own ServiceAccount, for pod phases, restart counts, node readiness and storage claims. It also reads your node sizes, region and Kubernetes version from there. If the optional RBAC was not applied, it skips this.
  • Sends it all to CostGlass with the token in the X-CostGlass-K8s-Token header.

You can view the Secret, RBAC and CronJob separately under Need individual manifests? View the Secret, RBAC and CronJob separately if your change process needs them as separate files.

Is the RBAC part optional?

Yes. Without it the cost data still arrives. What you lose: the Health tab stays empty, and CostGlass cannot read your real node count, CPU, memory, region and Kubernetes version from the cluster, so those details may be missing. If your security team rejects cluster-wide read access, remove the ClusterRole and ClusterRoleBinding from the file before applying. Because the all-in-one manifest includes them, apply the pieces separately in that case.

Check that it works

1
Check the pods
Run kubectl get pods -n opencost. The OpenCost pod should show 2/2 Running. If it is crash-looping, Prometheus is probably missing (see Troubleshooting).
2
Check the CronJob
Run kubectl get cronjob -n opencost, then after the next quarter-hour kubectl get jobs -n opencost and kubectl logs job/<job-name> -n opencost. A good run ends with a line starting CostGlass Ingest Success.
3
Check CostGlass
Open Kubernetes Costs. The header badge changes to OpenCost Connected and your cluster appears in the Cluster drop-down. A cluster counts as "active" if it pushed within the last 60 minutes.
The Connect OpenCost Agent window on the Kubernetes Costs page: cluster name, cloud buttons, the Helm step and the manifest step.

How long until data appears?

The exporter runs every 15 minutes, so the first push arrives within 15 minutes of applying the manifest. Cost figures are available from that first push. Some columns, such as actual CPU and memory usage on the Rightsizing tab, need Prometheus to have collected enough history first, which can take longer. Charts need more than one day of pushes to show a trend.

The Simulate Telemetry Push button

The Kubernetes Costs page's connect window has a button called Simulate Telemetry Push under "Test Live Push Simulation". It writes sample cost data for the cluster name into CostGlass so you can see how the page looks.

Do not use it on a real cluster name
The sample data is not from your cluster. Use it only to preview the page, and prefer a throwaway cluster name. If you ran it by mistake, disconnect that cluster name to remove the sample rows, then connect the real cluster.

Remove a cluster

1
Disconnect in CostGlass
On Settings → Cloud Accounts → Kubernetes, find the cluster under Connected Clusters and click Disconnect, then confirm.
2
Remove the agent from the cluster
Run kubectl delete -f costglass-agent.yaml, and if you no longer need OpenCost, helm uninstall opencost -n opencost (and Prometheus if you installed it only for this).

Disconnecting revokes the ingest token straight away (further pushes are refused), and deletes the cluster's stored allocations, its cluster record, its inventory entry and any matching connection record. The daily cost history already written to your cost history is not removed by this action. Note that the confirmation text says history is kept: in practice the live allocation tables are deleted.

Troubleshooting

What you seeLikely causeWhat to do
No data on the Kubernetes Costs page after 30 minutesThe CronJob has not run, or the push failed.Run kubectl get jobs -n opencost and read the latest job's logs. Look for Failed to fetch OpenCost telemetry (OpenCost not reachable) or CostGlass Ingest HTTP error (token or network problem).
OpenCost pod in CrashLoopBackOffPrometheus is missing or at a different address.Install Prometheus with Step 1, or point OpenCost at your own Prometheus. Then check kubectl logs for the OpenCost pod.
Exporter log says INGEST_TOKEN is missingThe Secret is missing or in the wrong namespace.Check kubectl get secret costglass-exporter-token -n opencost.
HTTP 401 or 403 when pushingThe token was revoked (you disconnected the cluster) or the cluster name changed.Generate new instructions and re-apply the manifest.
Pods stuck in Pending in the opencost namespaceThe cluster has no free capacity, or Prometheus is waiting for storage.Run kubectl describe pod on the pending pod and read the Events. Add node capacity or adjust the Prometheus storage settings.
Health tab says it needs the RBACThe ClusterRole and binding were not applied.Apply the RBAC part of the manifest. Costs are unaffected either way.
Carbon tab says it needs carbon estimates enabledOpenCost was installed without the carbon flag (or an older version).Re-run the Helm command, which includes opencost.carbonCost.enabled=true, then re-apply the manifest.
New cluster is missing from the Cluster drop-downYour browser may be showing an earlier list.Reload the page. The cluster list is fetched fresh on each visit and is not cached by the one-hour browser cache, so it should appear once the first push has arrived. If not, check the exporter logs.
Region or node details are blankThe optional RBAC was not applied, so node details could not be read.Apply the RBAC and wait for the next push.

Frequently asked questions

Does CostGlass need access to my cluster or cloud account for this?
No. Only the outbound push from the exporter. No inbound access, no kubeconfig and no cloud credentials are needed for Kubernetes cost data.
Why is Prometheus needed?
OpenCost reads CPU and memory metrics from Prometheus. Without it OpenCost cannot start. If you already run Prometheus at the default address, skip Step 1.
Can I connect many clusters?
Yes. Repeat the steps with a different Cluster Identifier for each one. Each cluster has its own token. Your plan sets a limit on the number of connections.
Can I change the cluster name later?
The name is tied to the token. To use another name, disconnect the cluster and connect it again under the new name.
Does it change anything in my cluster?
It adds objects only in the opencost namespace, plus one read-only ClusterRole and ClusterRoleBinding. It does not modify your workloads.
Is the cost the same as my cloud bill?
Not exactly. See Kubernetes Costs for how list prices, reconciliation and run-rate projection work.

Related guides