Read-only cluster cost waste scanner. Point it at any cluster
with a kubeconfig and get an estimated monthly waste report in ~30
seconds. No agent, no telemetry, no mutations — get/list only.
$ cost-scan scan
cost-scan scan — https://my-cluster
EST./MO CONF CHECK TARGET REASON
$2233.80 estimate idle-gpu node/gpu-node-1 node has 1 GPU(s), zero requested by any pod
$140.16 estimate underutilized-nodes node/worker-7 requests at 12% CPU / 31% memory of allocatable
$10.00 certain unused-pv pv/pvc-8f3a... PersistentVolume is Released — not bound to any claim
...
TOTAL $2402.51/mo estimated waste (9 findings)
Homebrew (macOS/Linux):
brew install DPS0340/tap/cost-scan
krew (as a kubectl plugin, once accepted into krew-index):
kubectl krew install cost-scan
kubectl cost-scan scan
Or with Go:
go install github.com/DPS0340/cost-scan@latest
Prebuilt binaries for linux/darwin/windows (amd64/arm64) are attached to GitHub Releases.
| Check | Needs | What it catches |
|---|---|---|
overprovisioned-requests |
metrics-server | requests far above live usage (rough right-sizing) |
underutilized-nodes |
— | nodes under 50% requested — consolidation candidates |
idle-gpu |
— | GPU nodes with zero GPU requests |
unused-pv |
— | Released/unbound PVs, PVCs no pod mounts |
idle-loadbalancer |
— | LoadBalancer services with no ready endpoints |
zombie-workloads |
— | long-term CrashLoop (reserved requests), stale finished pods/jobs |
no-requests |
— | containers without resource requests (unpredictable cost) |
Data sources are auto-detected. No metrics-server? API-only checks still run and the report says exactly what was skipped.
Several good tools overlap with parts of this. The short version: they answer "what is misconfigured or unused?", this one answers "what is that costing me per month?"
cost-scan |
popeye |
kor |
cost |
|
|---|---|---|---|---|
| Reports a dollar figure | yes, per finding | no | no | yes |
| Needs anything cluster-side | no | no | no | yes, Kubecost |
| Mutates the cluster | never, get/list only |
no | yes, has delete |
no |
| Idle-GPU detection | yes | no | no | no |
| Idle LoadBalancer | yes, zero ready endpoints | flags the type, not idleness | no | no |
| Node consolidation | yes | no | no | no |
Specifically:
popeyeis a linter: it grades resource sanity across ~30 kinds and is excellent at it. It carries no pricing model, so an over-provisioned deployment and an idle GPU node read as similar-severity findings. Its LoadBalancer rule fires on every service of that type rather than on ones with no ready endpoints.korfinds unused objects by kind (ConfigMaps, Secrets, PVCs, ...) and can delete them. It is object-centric and has no cost model or node and GPU analysis; this tool is read-only by construction.cost(Kubecost) is the most accurate on price because it reads real billing data, but it needs the Kubecost stack running in the cluster. This tool trades that accuracy for zero install: a kubeconfig is enough, and every number shows the arithmetic that produced it.craneis the CLI for the Crane FinOps platform (kubectl-crane), so it assumes that platform is deployed;lambda-gis a resource imbalance auditor. Both are broader than this tool, which is a single read-only command with no daemon and no state.
Every finding prints its CostBasis, so an estimate can be checked
rather than trusted.
Limit the scan and wire it into CI or cron:
cost-scan scan --namespace payments # one namespace only
cost-scan scan --fail-over 500 # exit 2 if waste > $500/mo
cost-scan scan -o json | jq .total_monthly_usd
Exit codes: 0 clean (or under threshold), 1 scan error, 2 waste
exceeded --fail-over. With --namespace, cluster-scoped checks
(nodes, PVs) are skipped and the report says so.
Node costs come from an embedded on-demand pricing table keyed by the
node.kubernetes.io/instance-type label, falling back to per-resource
rates. On-prem? Override with --cpu-rate / --mem-rate. Every dollar
figure carries its derivation and a confidence level (certain /
estimate) — no inflated numbers.
- Read-only by construction: no mutating API verbs exist in the codebase.
- Minimal RBAC:
deploy/rbac.yaml. - Zero network calls besides the Kubernetes API. No telemetry, ever.
Free (this repo): everything above, forever, with no cluster-size or spend caps.
A paid tier (cost-scan Pro, $299/organization/year — clusters and nodes unlimited) adds precision right-sizing from p95/p99 usage over a real window (Prometheus, OpenObserve or ClickHouse) plus a self-contained HTML executive report. Licenses verify offline: no phone-home, and an expired key keeps working forever on versions released before it expired.
Planned next, only as paying users ask for it: trend tracking, CI cost-regression mode, multi-cluster aggregation. Full details and status: ROADMAP.md.
Apache-2.0