Skip to content
Finitizer

Kubernetes Cost Calculator

Estimate your cluster's cost on EKS, GKE or AKS, including load balancers, disks and data transfer.

Multi-cloudCalculatorA few numbers
New here? See what this tool does and how to use it.

Learn more

Kubernetes Cost Calculator

What this free tool does for you

Budget your Kubernetes clusters in full, not just the nodes: see the monthly cost on EKS, GKE or AKS with load balancers, disks and data transfer included, and what rightsizing requests could save.

How to use it

  1. Pick a scenario under Start from a scenario, or choose your Platform and number of Clusters.
  2. Enter the Total CPU requested by application pods and memory, then typical and peak CPU use.
  3. Enter your node shape: Node vCPU, Node memory and Node price per hour.
  4. Add the Disk per node, Billed load balancers, and your monthly traffic to the internet and between zones.
  5. Read the Estimated monthly cost for included components, then the Potential savings from rightsizing requests.

Good to know

  • Requests, not usage. Requests decide how many nodes run, and you pay for the nodes. Use only changes the potential savings.
  • On GKE or AKS? The node price is that cloud's list price for the same node shape; enter your own if you pay less. Disks, load balancers and internet egress use AWS rates as a stand-in.
  • Ready to measure? Scroll down to Make the change for a read-only script that lists requests and live use per pod.
  • Save or share. Use Copy link to this result to get a link with your numbers filled in.
Before you start: what to have readyShow
  • Total CPU and memory requested by your application pods. The script on this page sums them per namespace and pod. Requests, not limits and not usage: requests decide how many nodes run, and the nodes are what you pay for. Leave out DaemonSet and system pods.
  • Typical and peak use of those requests, optional. From your metrics history over a representative period, CPU and memory separately. They change the potential savings only, never the estimate. kubectl top pods is one snapshot, not a peak.
  • Your node shape, and its hourly rate if you pay less than list. vCPU and memory. Each platform prices the list machine with that shape; enter your own rate for a committed or negotiated price.
  • Disk per node, and the number of billed cloud load balancers. One Ingress can share a load balancer across many services, so count load balancers on the bill rather than Services. Only the base fee is priced.
  • Monthly egress and traffic between zones, in GB. From your bill rather than from a guess. On AWS each GB between zones is charged on both sides; a figure from a cost export already counts both, and the page has a switch for that.
Start from a scenario

Each one fills in the fields below for a typical workload of that kind. You can change any of them.

Share of the CPU request pods use, from your metrics history; it can pass 100%. It changes the potential savings only, never the bill.

Advanced assumptionsShow

Optional. Checks one indivisible pod against a node’s allocatable capacity, which the aggregate estimate cannot. 0 skips the check.

Estimated monthly cost for included components$13,641.95
Nodes (45)
$12,614.40
Everything else included
$1,027.55
Potential savings, not guaranteed
$864.96/mo

$163,703.40 a year. USD, 730 hours a month, list prices.

Estimate coverage: medium. The node price is the m5.2xlarge list price in us-east-1 (N. Virginia). The control-plane fee and the cross-zone rule are this platform’s own. The load balancer, disk and transfer rates are AWS list rates. It is list price throughout, so a committed or negotiated rate would bring this number down.
Estimated monthly cost for included components
$13,641.95
45 nodes, bound by CPU (45 by CPU, 42 by memory). 7.5% of this bill is not node compute, the part a nodes-times-price calculator never shows.

USD · 730 hours a month, steady capacity · Amazon EKS, us-east-1 (N. Virginia) · 8 vCPU / 32 GiB nodes at $0.384/hr (m5.2xlarge list price) · disk, load balancer and egress at AWS list rates.

Nodes45 x $0.384/hr x 730 h (m5.2xlarge), 15 in each of 3 clusters$12,614.40
Control plane3 clusters at $0.10/hr$219.00
Node disks100 GiB per node at $0.08/GiB-month$360.00
Load balancers, base fee only6 at $0.0225/hr each; capacity units and data processed not included$98.55
Internet egress3,000 GB charged, tiered from $0.09/GB, after 0 GB free allowance$270.00
Traffic between zones$0.01/GB in each direction, $0.02 per GB entered$80.00
Total$13,641.95

This is a simplified capacity estimate, not a scheduling guarantee. Large pods, affinity, topology, node pools, and failover requirements can increase node count.

Not included in this estimate
  • Load balancer capacity units, rules and data processed (base fee only is included)
  • NAT gateways and public IPv4 addresses
  • Persistent volumes for applications, beyond the node disks
  • Logging, monitoring, backups and other external services
  • LLM tokens, paid agent tools, vector databases and GPU inference
  • Taxes, support plans, and committed or negotiated discounts

Potential savings from rightsizing requests

Potential savings based on your entered utilization
$864.96/mo
Validate representative workload history, scheduling constraints, and reliability requirements before changing requests or nodes.
Nodes at peak-derived requests
42
3 fewer than 45, whole nodes only, same 20% headroom.
Peak-derived requests
144 CPU
CPU requests x 60% peak; memory 900 GiB (memory requests kept: memory use not set). No margin beyond the headroom.
Saving from Spot, assumed
$0.00/mo
Already in the total: 0% of node-hours at 70% off. For interruption-tolerant workloads; provider terms differ.

Requests reserve capacity for scheduling; they are not a cap. Lowering a CPU request does not throttle a pod (a CPU limit does), but under contention CPU is shared in proportion to requests. Lowering a memory request does not by itself cause an OOM kill (passing a memory limit, or the node running out, does), but pods using more than they request are evicted first when a node runs short of memory.

How the node count is worked outShow
Capacity per node and across the fleet
Per node, then fleetCPUMemory
Node capacity8 vCPU32 GiB
Kubelet and OS reservation, 12%-1-4
DaemonSet allowance-0-1
Allocatable to application pods7 vCPU28 GiB
Usable after 20% headroom5 vCPU22 GiB
Fleet usable, 45 nodes244996
Requested by application pods240900
Typical use (entered)84not set
Peak use (entered)144not set

Requests are split evenly across the 3 clusters, and each cluster rounds up to whole nodes, at least one. A cluster is full when its requests reach the usable capacity above. Headroom, the reservation and the DaemonSet allowance are capacity you need, not waste. CPU decides the count, so the other resource has slack; a different node shape may fit better.

Watch the EKS version cliff. A cluster left on a Kubernetes version past its standard support window moves to extended support at $0.60 per cluster-hour, six times the standard fee. For your 3 clusters that is $1,314.00 a month instead of $219.00.

And the carbon

Running this today: about 2.43 to 5.82 t COâ‚‚e a year in us-east-1 (343 g/kWh).

  • Rightsize requests to peak usesaves 162 to 388 kg COâ‚‚e a year (7%)

Spot nodes changes the price, not the hardware or the hours, so it saves no carbon. An estimate of the servers’ electricity (compute and memory, with data center overhead), location-based, from Cloud Carbon Footprint’s coefficients; your provider’s own carbon tool is the authoritative figure. Estimate a whole workload or see the methodology.

Make the change

Read-only measurement first. Nothing here changes requests across the cluster from the page's aggregate figures, and nothing changes limits.

Save as k8s-requests.py and run python3 k8s-requests.py. Read-only: it lists each pod's container requests beside its live use, matched by namespace and pod name, and totals the application requests this page asks for (DaemonSet and static pods apart). Needs kubectl and Python 3.8+, and metrics-server for the use columns. Live use is one snapshot: take typical and peak figures from your metrics history before changing anything.

python
#!/usr/bin/env python3
"""Application pod requests beside live use, per pod. Read-only.

Needs kubectl (read access to pods), Python 3.8+, and metrics-server for the
use columns. Offline: --pods pods.json [--metrics metrics.json], from
  kubectl get pods --all-namespaces -o json
  kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods

Pods are matched on namespace AND name. Requests are the sum over regular
containers plus restartable (sidecar) init containers. Not reproduced, only
flagged: other init containers (the effective request can be higher while
they run), pod overhead, and pod-level resources. DaemonSet and static pods
are totalled apart: the calculator's per-node allowance covers them.

Live use is ONE snapshot. It shows outliers; it does not prove a smaller
request is safe. Take typical and peak use from your metrics history over a
representative period (two weeks or more, busiest days included).
"""
import argparse, json, subprocess, sys
from decimal import Decimal

UNITS = {"Ki": 2**10, "Mi": 2**20, "Gi": 2**30, "Ti": 2**40, "Pi": 2**50, "Ei": 2**60,
         "n": Decimal("1e-9"), "u": Decimal("1e-6"), "m": Decimal("1e-3"),
         "k": 10**3, "M": 10**6, "G": 10**9, "T": 10**12, "P": 10**15, "E": 10**18}
GIB = Decimal(2**30)

def quantity(q):
    """A Kubernetes quantity ("250m", "1.5", "512Mi", "1G", "1e3") in base units."""
    q = str(q).strip()
    for suffix in sorted(UNITS, key=len, reverse=True):
        if q.endswith(suffix) and q[:-len(suffix)]:
            return Decimal(q[:-len(suffix)]) * Decimal(UNITS[suffix])
    return Decimal(q)

def load(path, cmd):
    if path:
        with open(path) as f:
            return json.load(f)
    return json.loads(subprocess.run(cmd, check=True, capture_output=True, text=True).stdout)

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--pods")
    ap.add_argument("--metrics")
    args = ap.parse_args()
    pods = load(args.pods, ["kubectl", "get", "pods", "--all-namespaces", "-o", "json"])["items"]
    try:
        metrics = load(args.metrics, ["kubectl", "get", "--raw", "/apis/metrics.k8s.io/v1beta1/pods"]) \
            if (args.metrics or not args.pods) else {"items": []}
    except Exception as e:
        print(f"# metrics unavailable ({e}); use columns show n/a", file=sys.stderr)
        metrics = {"items": []}
    use = {}
    for m in metrics.get("items", []):
        key = (m["metadata"]["namespace"], m["metadata"]["name"])
        cs = m.get("containers", [])
        use[key] = (sum(quantity(c["usage"].get("cpu", "0")) for c in cs),
                    sum(quantity(c["usage"].get("memory", "0")) for c in cs))

    totals = {"app": [0, Decimal(0), Decimal(0)], "pending": [0, Decimal(0), Decimal(0)],
              "system": [0, Decimal(0), Decimal(0)]}
    no_metrics = 0
    print("NAMESPACE\tPOD\tPHASE\tCPU_REQ\tMEM_REQ_GIB\tCPU_USED\tMEM_USED_GIB\tFLAGS")
    for p in pods:
        meta, spec = p["metadata"], p.get("spec", {})
        phase = p.get("status", {}).get("phase", "Unknown")
        if phase in ("Succeeded", "Failed"):
            continue  # finished pods hold no capacity
        flags = []
        running = list(spec.get("containers", []))
        for c in spec.get("initContainers", []):
            if c.get("restartPolicy") == "Always":
                running.append(c); flags.append("sidecar")
            elif "init" not in flags:
                flags.append("init")
        cpu = mem = Decimal(0)
        for c in running:
            req = c.get("resources", {}).get("requests", {})
            if "cpu" in req: cpu += quantity(req["cpu"])
            elif "no-cpu-request" not in flags: flags.append("no-cpu-request")
            if "memory" in req: mem += quantity(req["memory"])
            elif "no-memory-request" not in flags: flags.append("no-memory-request")
        if spec.get("overhead"): flags.append("overhead")
        if spec.get("resources"): flags.append("pod-level-resources")
        owners = [o.get("kind") for o in meta.get("ownerReferences", [])]
        system = "DaemonSet" in owners or "kubernetes.io/config.mirror" in meta.get("annotations", {})
        if system: flags.append("daemonset-or-static")
        key = (meta["namespace"], meta["name"])
        if key in use:
            cpu_used, mem_used = f"{use[key][0]:.3f}", f"{use[key][1] / GIB:.3f}"
        else:
            cpu_used = mem_used = "n/a"
            if phase == "Running": no_metrics += 1
        bucket = "system" if system else ("pending" if phase == "Pending" else "app")
        totals[bucket][0] += 1; totals[bucket][1] += cpu; totals[bucket][2] += mem
        print(f"{key[0]}\t{key[1]}\t{phase}\t{cpu:.3f}\t{mem / GIB:.3f}\t{cpu_used}\t{mem_used}\t{','.join(flags) or '-'}")

    print()
    for label, k in (("Application pods, enter these on the page", "app"),
                     ("Pending pods, not yet on a node", "pending"),
                     ("DaemonSet and static pods, left out of the page's inputs", "system")):
        n, cpu, mem = totals[k]
        print(f"# {label}: {n} pods, {cpu:.3f} CPU, {mem / GIB:.3f} GiB requested")
    print(f"# Running pods with no metrics (use unknown, not zero): {no_metrics}")
    print("# Live use is one snapshot: not evidence that a smaller request is safe.")

if __name__ == "__main__":
    main()

What this model assumes

Show
  • Requests set the node count; nodes set the bill. Requests influence how many nodes you need. You pay for provisioned nodes. Lower requests reduce your invoice only if nodes can be removed or future capacity purchases avoided. Observed utilization never changes the estimate, only the potential savings.
  • Allocatable is less than capacity. Each node loses 12.0% to the kubelet and OS and a DaemonSet allowance of 0.25 vCPU and 0.5 GiB before application pods are placed. These are planning figures, not measurements: real reservations are tiered by node size. So the request inputs are application pod requests only; counting DaemonSet requests there too would count them twice.
  • Potential savings use your peaks, per resource. Rightsized requests are current requests times peak use, CPU and memory separately, then the same headroom as the baseline is applied once. With memory use not set, memory requests are kept. Savings count whole nodes only, and peak use above the request shows as extra capacity needed, not a saving.
  • Each platform prices its own machine. With the node shape above, EKS uses the EC2 list price in us-east-1, GKE the Compute Engine N2 list price in us-central1 and AKS the Azure Dsv5, Esv5 or Fsv2 list price in East US. A shape no listed machine has needs your price.
  • Steady monthly capacity. Every node runs 730 hours a month. Autoscaling that removes nodes for part of the month is not modeled. Spot is a fleet-average share of node-hours at an assumed discount, applied to compute only.
  • Load balancers are charged at the base fee only. Capacity units, rules and data processed depend on traffic, which this model does not ask for, and load balancer types are priced differently, so the real line is higher.
  • Egress has one allowance for the whole estimate. AWS’s 100 GB of free internet egress is shared across services and Regions, so the default assumes none of it is left. Money is rounded half-up to the cent for display only.
Rates used and their sourcesShow
  • Amazon EKS control plane, source, read 17 Oct 2026
  • EC2 on-demand (Linux, shared tenancy), source, read 13 Oct 2026
  • EBS volumes and snapshots, source, read 13 Oct 2026
  • Elastic Load Balancing, source, read 13 Oct 2026
  • Data transfer, NAT gateway and public IPv4, source, read 13 Oct 2026

Prices verified 13 Oct 2026. List prices in USD for us-east-1, us-central1 or East US, by platform, plus the rates you enter.

Want this done on your real bill?

Cloud Cost Audit: We go through your real AWS or Google Cloud bill and hand you a ranked list of what to cut first. From $1,500, fixed. Nothing paid upfront.

See the service

Questions

How much does a Kubernetes cluster cost?

The control plane is the small, predictable part: $0.10 per cluster-hour on EKS, GKE and AKS Standard, or about $73 a month; nothing on the AKS Free tier; $0.60 on EKS and GKE extended support and AKS Premium. Everything else is nodes, load balancers, node disks and network transfer. On a small cluster the non-node charges can exceed the compute, which is why a nodes-times-price estimate is usually well under the real bill.

Is EKS, GKE or AKS cheaper?

The standard control-plane fee is $0.10 per cluster-hour on all three, so the difference is rarely there. GKE grants a $74.40 monthly credit that covers one zonal or Autopilot cluster, not a regional one, and AKS has a free tier with no SLA. Beyond that the cost is node prices, which this page reads from each cloud's own list for the same node shape, and cross-zone traffic: AWS charges it both ways, Google once, and Azure lists no charge.

Why do I need more nodes than my pod requests suggest?

Because allocatable capacity is less than node capacity. The kubelet, the OS and daemonsets reserve a share of every node before an application pod is scheduled, typically 10% to 15%, proportionally more on small nodes. Add scheduling headroom for rolling updates and bursts, and a naive division understates node count by a fifth or more.

What is the biggest source of Kubernetes waste?

Often requests set well above what pods use at their peak. The scheduler places pods by their requests, so requests decide how many nodes run, and you pay for the nodes whatever the pods use. Headroom for rollouts and the reservation for the kubelet and DaemonSets are not waste. Lowering requests toward measured peak use, workload by workload, is what can let a cluster run fewer nodes; check each change against restarts, throttling and latency.

What is EKS extended support and why did my bill jump?

When a Kubernetes version passes the end of its standard support window, EKS moves the cluster to extended support at $0.60 per cluster-hour, six times the standard $0.10. For a three-cluster estate that is roughly $1,314 a month instead of $219. It is the most common unexplained jump on an EKS bill and it is avoided entirely by upgrading on schedule.

Related tools

More tools for: Kubernetes and containers, Network and data transfer, Compute and utilization

Requests drift. So does the gap.

Finitizer tracks requested versus used capacity per namespace and workload over time, attributes cluster cost back to the teams causing it, and flags the version cliffs and idle node groups before they show up on an invoice.

See how Finitizer works

Rate this tool

How would you rate the Kubernetes Cost Calculator?