The Principles of Kubernetes Scheduling: Requests, Limits, and Allocatable Resources
Kubernetes (K8s) has become the standard platform for orchestrating containerized applications at scale. In a Kubernetes cluster, the control plane schedules containers (grouped into Pods) onto physical or virtual machine worker nodes. Sizing a cluster requires understanding the resource allocation model, specifically the difference between Pod requests, Pod limits, and Node allocatable capacity.
When a Pod is declared, developers specify Requests (the minimum CPU and memory the pod needs to run) and Limits (the maximum CPU and memory the pod is allowed to consume). The Kubernetes scheduler uses Pod requests, not limits, when deciding which node has enough space to host the pod. If your requests are set too low, nodes can become overcommitted, leading to performance degradation or Out-Of-Memory (OOM) pod evictions when traffic spikes.
To optimize your container lifecycle, you can estimate container sizes using the Docker image optimizer calculator or evaluate serverless alternatives using the serverless cost calculator. Keeping resource requests aligned with actual container resource usage is key to maintaining stable orchestration.
A physical or virtual server cannot dedicate 100% of its resources to user containers. The node must run the operating system, system daemons (systemd, sshd), and Kubernetes management agents (kubelet, container runtime like containerd, kube-proxy). These system requirements are subtracted from the node's raw hardware capacity to determine the Allocatable resource pool, which represents the actual capacity available to schedule user pods: $$\text{Allocatable} = \text{Raw Capacity} - \text{OS Reserve} - \text{Kubelet Reserve}$$.
Let's calculate the node requirements for hosting 40 pods, with each pod requesting 250 mCPU (0.25 cores) and 512 MB of memory. The total requests are: $$\text{Total Requested CPU} = 40 × 250 = 10,000\text{ mCPU (10 cores)}$$ and $$\text{Total Requested Memory} = 40 × 512 = 20,480\text{ MB (20 GB)}$$. If our virtual machine nodes have 4 cores (4,000 mCPU) and 16 GB of memory (16,384 MB), and we configure a 15% OS/Kubelet overhead reserve: Sizing allocatable resources per node yields: $$\text{Allocatable CPU} = 4000 × 0.85 = 3,400\text{ mCPU}$$ and $$\text{Allocatable RAM} = 16384 × 0.85 = 13,926\text{ MB}$$.