Kubernetes cluster sizing is the capacity-planning process that matches control-plane and worker-node resources to workload demand, failure tolerance, and growth needs.
For small teams, the useful question is not “How large can a Kubernetes cluster become?” It is “How much allocatable worker capacity do our workloads actually require, and how much spare capacity must remain when a node is drained, fails, or a deployment temporarily increases demand?” Kubernetes schedules Pods from declared resource requests, while each node reserves part of its raw CPU and memory for the operating system and Kubernetes components.
Raff supports both VM-based container infrastructure and managed Kubernetes, so sizing should follow the operating model rather than a generic node-count rule. Start with Container Infrastructure: Docker, K3s, and Kubernetes if you are still deciding whether a cluster is necessary. This guide assumes Kubernetes is already justified and focuses on sizing the cluster that will run it.
Kubernetes cluster sizing starts with allocatable capacity
A worker plan may advertise a certain number of vCPUs and gigabytes of memory, but raw node capacity is not the same as application capacity.
Kubernetes defines Node Allocatable as the compute available for Pods after resources reserved for the operating system, Kubernetes daemons, and eviction thresholds are accounted for. The scheduler then uses a node's allocatable resources together with Pod resource requests to decide whether a Pod fits.
That creates a practical sizing chain:
Raw worker capacity
- OS and Kubernetes overhead
- per-node platform workloads
= allocatable worker capacity
Allocatable worker capacity
- production workload requests
- failure / maintenance reserve
- chosen growth headroom
= remaining operating margin
This distinction prevents a common mistake: adding up the CPU and memory printed on a node plan and assuming every unit can be assigned to application Pods.
DaemonSets make the difference visible. Networking agents, storage components, monitoring agents, security tooling, and other per-node services may run on every worker. Each additional node therefore adds capacity and some repeated overhead.
The exact overhead depends on the cluster. There is no universal percentage that should be copied into every sizing spreadsheet. Measure the system workloads that will actually run on your nodes and keep that capacity separate from application demand.
Resource requests are the capacity signal that matters first
Kubernetes resource requests are central to sizing because the scheduler uses them when placing Pods.
If an application normally uses 300 millicores of CPU but requests 1 CPU, the scheduler plans around the 1-CPU request. If several workloads are oversized in the same way, the cluster can appear full to the scheduler even while observed CPU usage looks low.
That does not mean requests should be aggressively minimized. Requests should represent the capacity a workload needs to run predictably under the conditions your team has defined.
For initial cluster sizing, collect at least:
- CPU requests for every production workload;
- memory requests for every production workload;
- minimum replica counts;
- expected rolling-deployment overlap;
- DaemonSet and system Pod requests;
- persistent-storage requirements;
- workload placement constraints;
- normal and peak concurrency or queue demand.
Use observed workload behavior where available. For a new application without production history, begin conservatively, instrument the cluster, and plan an early review rather than treating the first estimate as permanent.
This guide intentionally stops at the capacity-planning boundary. Detailed request and limit tuning belongs in the dedicated resource-management topic, while this page uses requests only to answer the larger question: how much worker capacity should exist?
Control-plane sizing depends on who operates it
Control-plane sizing and worker sizing are related but should not be mixed together.
In a self-managed Kubernetes cluster, the team owns API server, scheduler, controller, datastore, certificates, control-plane availability, upgrades, and recovery. Control-plane machines therefore need their own capacity and high-availability design. They should not be counted as ordinary worker capacity unless the architecture deliberately schedules application workloads there.
In managed Kubernetes, the provider operates the managed control plane and the customer sizes worker capacity separately. That makes the planning model simpler:
Managed control plane
↓
Worker pool capacity
↓
Application workloads
The ownership distinction is covered in Managed vs Self-Managed Kubernetes. For cluster sizing, the important rule is that application demand should be planned against the capacity actually available on workers, not against control-plane resources that do not serve normal workloads.
Kubernetes' production guidance also distinguishes cluster-management concerns from node and workload capacity. That separation becomes more important as teams add high availability, multiple worker pools, and different workload classes.
The decision framework uses workload, failure, and growth headroom
The initial node count should come from the workload and the failure model together.
| Sizing question | What to measure or decide | Why it changes node count |
|---|
| Baseline workload | Sum of production CPU and memory requests | Defines minimum scheduled demand |
| Replica floor | Minimum healthy replicas per service | Prevents sizing below application availability needs |
| System overhead | kube-system Pods, DaemonSets, OS reserve | Raw node capacity is not fully allocatable |
| Deployment overlap | Extra replicas during rolling updates | Temporary capacity must fit during releases |
| Node failure target | Whether the cluster must tolerate one worker loss | Remaining nodes must still carry required workloads |
| Maintenance model | Whether nodes will be drained one at a time | Planned maintenance resembles a temporary node failure |
| Workload shape | CPU-heavy, memory-heavy, bursty, or mixed | Determines which node shape fits efficiently |
| Storage and placement | Persistent volumes, affinities, taints, architecture needs | May constrain which nodes can accept specific Pods |
| Growth headroom | Explicit capacity reserved for expected growth | Prevents every small change from forcing emergency expansion |
A practical failure-capacity test for identical workers is:
If one worker disappears,
do the remaining workers still have enough allocatable capacity
for the production requests that must remain healthy?
If the answer is no, the cluster is sized for normal operation but not for the failure model you expect it to survive.
Raff's sizing rule is to plan against allocatable worker capacity after system overhead and failure headroom, not the CPU and memory printed on the node plan. This keeps the capacity model tied to what Kubernetes can actually schedule.
There is no universal “30% headroom” or similar number that fits every cluster. A low-traffic internal service, a customer-facing API, and a queue-heavy batch platform have different recovery and growth requirements. Name the reason for each reserve instead of hiding it inside one arbitrary percentage.
Worker size trades bin packing against failure granularity
A cluster can often reach similar total CPU and memory with a few large workers or more small workers. Those designs do not behave identically.
Larger workers reduce node count
Larger nodes can simplify the fleet and give the scheduler more room for Pods with relatively large resource requests. Fewer nodes can also mean less repeated DaemonSet overhead and fewer machines to patch or observe.
The trade-off is failure granularity. When one large worker disappears, a larger share of total cluster capacity disappears with it. Very large nodes can also make poor workload requests less visible because the scheduler has more space to absorb them.
Smaller workers increase scheduling granularity
More smaller nodes distribute capacity across additional failure units. Losing one node removes a smaller portion of total compute, and smaller node increments can make growth more gradual.
The trade-off is repeated per-node overhead, more node objects, more DaemonSet copies, and potentially more fragmented free resources.
For small teams, the right choice is usually not “smallest nodes possible” or “largest nodes possible.” It is the node size that fits the largest normal Pod comfortably while keeping node loss, operational count, and cost understandable.
Pod density can also become a constraint before raw CPU or memory. Kubernetes v1.36 documents a supported large-cluster limit of 110 Pods per node and up to 5,000 nodes per cluster. Those are scalability ceilings, not recommended small-team sizing targets. Real clusters should leave room for system Pods, rollout overlap, and workload-specific networking or storage constraints.
Headroom must cover maintenance as well as traffic growth
Teams often think of headroom only as spare capacity for traffic spikes. Production Kubernetes needs headroom for operational events too.
Node drains consume spare capacity
During maintenance or upgrades, workloads on a drained worker need somewhere else to run. If every remaining node is already tightly packed, maintenance can leave Pods Pending even though the cluster looked healthy before the drain.
Rolling deployments temporarily increase replicas
Deployment strategies can create old and new replicas at the same time. The exact overlap depends on rollout configuration, but the sizing model should include whatever deployment behavior your team intends to use.
Autoscaling takes time
Autoscaling reduces the need to keep every possible future node running, but it does not make capacity appear instantly. New workers must be provisioned, join the cluster, become Ready, and then receive workloads.
That means the minimum worker pool still needs enough capacity for normal operation and the failure or maintenance scenarios the team considers mandatory. Autoscaling should respond to sustained additional demand; it should not be the only plan for surviving the loss of a worker that the baseline fleet could not tolerate.
Growth should have a named review trigger
Instead of choosing one permanent headroom percentage, define when the cluster will be reviewed. Useful triggers include:
- sustained high requested-to-allocatable ratio;
- repeated Pending Pods during normal rollouts;
- inability to drain one worker safely;
- frequent autoscaler expansion at baseline traffic;
- a new workload class with materially different memory or CPU needs;
- persistent storage or node-placement constraints limiting scheduling.
Headroom is useful when it protects a specific operating requirement and is reviewed as the workload changes.
Node pools should follow workload classes after the baseline is known
A single homogeneous worker pool is a good starting point when workloads have similar CPU, memory, storage, and availability characteristics.
Separate node pools become useful when a workload class needs a different capacity or placement boundary, for example:
- memory-heavy services;
- CPU-heavy batch workers;
- customer-facing workloads with stricter availability needs;
- workloads requiring isolated capacity;
- different autoscaling behavior;
- specialized storage or scheduling constraints.
Do not create a node pool for every service. Too many small pools can strand capacity because free resources in one pool may not help workloads constrained to another.
The dedicated [Kubernetes Node Pools] guide owns that architecture decision. For cluster sizing, use one important principle: size each pool from the workloads that are allowed to run there, then test whether the remaining eligible nodes can carry the required replicas when one node is unavailable.
That prevents total cluster capacity from hiding a local shortage inside one constrained pool.
Raff Kubernetes separates control-plane cost from worker sizing
Raff Managed Kubernetes makes the control-plane and worker-capacity distinction explicit.
The standard managed control plane is currently $0/month, while an optional three-master HA control plane is $30/month. Worker capacity is selected separately. Current worker plans include a Starter node with 1 vCPU / 2 GB for $9.99/month, a Standard node with 2 vCPU / 4 GB for $13.99/month, and larger Performance, High Memory, Large, and Scale shapes for heavier workloads.
That lets teams build the sizing model around the Pods rather than treating the control plane as part of application capacity.
A practical Raff sizing sequence is:
- total the baseline CPU and memory requests that must run;
- account for system Pods and per-node overhead;
- decide whether one worker can be unavailable without breaking the production target;
- choose a worker shape that fits the largest normal workloads without excessive fragmentation;
- select the initial node count from the required allocatable capacity;
- add node-pool autoscaling only after the minimum safe fleet is defined;
- review sizing after real workload measurements are available.
Raff Kubernetes includes node pools, autoscaling, monitoring and logs, private VPC networking, and a managed public endpoint. Cluster storage is currently $0.08/GB-month, so persistent storage should be sized separately from worker compute rather than hidden inside a node-count estimate.
The important operational distinction is simple: a cheaper node is not cheaper if the cluster needs many more of them to satisfy memory, scheduling, or failure constraints. Compare the worker pool as an operating unit, not one node in isolation.
Common sizing mistakes create either waste or fragile clusters
Sizing from observed CPU alone
Observed CPU is useful, but the scheduler places Pods from requests. Compare usage and requests instead of using one without the other.
Counting raw node capacity as application capacity
OS services, Kubernetes daemons, eviction reserve, and per-node platform workloads reduce what is allocatable to ordinary Pods.
Ignoring one-node failure
A three-worker cluster can look comfortable until one worker is unavailable and the remaining two cannot fit the required replicas.
Using autoscaling as the failure plan
Autoscaling is a capacity mechanism, not instant failover capacity. Keep enough baseline headroom for the failures and maintenance events you expect to tolerate.
Creating too many node pools early
More pools can improve isolation, but they can also fragment capacity. Begin with workload classes that have a real placement or scaling difference.
Treating Kubernetes scalability limits as sizing targets
The maximum supported Pod or node count says what Kubernetes can scale toward under validated conditions. It does not say how densely a small production cluster should run.
Kubernetes cluster sizing is a repeatable capacity decision
Kubernetes cluster sizing should begin with allocatable capacity, workload requests, failure tolerance, deployment overlap, and an explicit reason for growth headroom. Raw vCPU and memory totals are only the starting inputs.
For small teams, keep the first worker topology understandable. Choose node sizes that fit normal Pods cleanly, make sure required workloads still fit during a drain or worker loss, and use autoscaling after the safe minimum fleet is known. Revisit the model as real request-to-usage data and workload behavior become available.
Continue with Container Infrastructure: Docker, K3s, and Kubernetes for the broader operating model, Managed vs Self-Managed Kubernetes for ownership, and Kubernetes Cost Optimization once the initial capacity model is established.