Use ops0 Kubernetes cost analysis to identify over-provisioned workloads, idle namespaces, and orphaned resources — then right-size and cut spending.
Your production Kubernetes cluster bill jumped 40% last quarter. Engineering says they didn't deploy anything major. You need to find where the money is going and cut waste without impacting production workloads.
What you'll accomplish:
OpenCost calculates cost based on resource requests (not actual usage). Pods without requests set will show $0 — fix this first if you see missing data.
Namespace CPU/mo Mem/mo Storage/mo Total/mo
──────────────────────────────────────────────────────────────
ml-training $520 $210 $65 $795 ← investigate
api-services $185 $90 $20 $295
monitoring $75 $145 $60 $280
dev-sandbox $310 $125 $0 $435 ← investigate
frontend $40 $25 $5 $70
Two namespaces stand out: ml-training (expensive — is it justified?) and dev-sandbox (high compute cost, no storage — likely idle).
In Cost Analysis → select a namespace → Workload view, look for workloads where Requested >> Actual usage. ops0 shows both columns when metrics are available.
Signs of over-provisioning:
| Signal | Example |
|---|---|
| CPU over-requested | CPU requested: 4 cores, CPU used: 0.3 cores consistently |
| Memory over-requested | Memory requested: 8Gi, Memory used: 1.2Gi |
Steps to right-size:
kubectl applyBefore (over-provisioned):
resources:
requests:
cpu: "4"
memory: "8Gi"
limits:
cpu: "8"
memory: "16Gi"
After (right-sized):
resources:
requests:
cpu: "500m"
memory: "1.5Gi"
limits:
cpu: "2"
memory: "3Gi"
Right-sizing one workload from 4 CPU to 0.5 CPU on a 3-replica deployment saves approximately $180/month on a standard cloud instance type.
The dev-sandbox namespace costs $435/month with no persistent storage — it's burning compute outside business hours.
Option A — Add resource quotas to cap dev spending:
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-sandbox-quota
namespace: dev-sandbox
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
Option B — Schedule shutdown outside business hours using a Workflow:
0 20 * * 1-5): kubectl scale deployments --replicas=0 -n dev-sandbox0 8 * * 1-5): kubectl scale deployments --replicas=1 -n dev-sandboxThis stops dev workloads at 8 PM and restarts at 8 AM on weekdays — approximately 65% cost reduction for the namespace.
Go to Kubernetes → [cluster] → Resources → Orphan Resources tab.
Look for:
| Resource type | Why it costs money |
|---|---|
| PersistentVolumeClaims not attached to any pod | Charged even when unused |
| LoadBalancer Services with no active backends | Cloud LB hourly charges still apply |
| Completed Jobs that were never cleaned up | Linger as clutter, may hold PVCs |
For each orphan:
Orphaned PVCs at 100 GB SSD cost approximately $12/month each. Orphaned cloud LoadBalancers cost approximately $18/month each. These accumulate silently over time.
After completing the steps above, confirm:
| Check | Expected result |
|---|---|
| OpenCost status | Shows Running in the Cost Analysis tab |
| Cost data | All namespaces show cost data (not $0 across the board) |
| Right-sized workload | CPU usage stays below new limits with no throttling events after 24 hours |
| Idle namespace shutdown | Cost Analysis shows reduced spend the following day |
requests: {cpu: "100m", memory: "128Mi"} enables cost tracking.opencost namespace. It may be failing due to insufficient RBAC permissions — the cluster connection needs cluster-admin or a custom ClusterRole that grants the required access.get, list, and watch on all API groups.