K8s Pod Density & Bin Packing Calculator
K8s hard limit: 110 pods/node. Your CNI: maybe 40. AWS VPC CNI enforces per-ENI IP limits that kick in long before the kubelet says stop. Model vCPU, memory, ephemeral storage, and provider IP ceilings — find the binding constraint before your scheduler refuses pods at 4 PM Friday.
📐 Node & Workload Configuration
Configure node specs and pod resource requests. The engine computes max schedulable pods across vCPU, memory, storage, and CNI IP limits. The smallest number wins — that is your bottleneck.
🖥️ Node Specification
📦 Pod Resource Requests (per Pod)
Kubernetes Pod Density: Why Node Sizing Determines Cluster Capacity
Pod density — the number of pods a single Kubernetes node can host — is a critical but often overestimated design parameter. The scheduler must satisfy multiple independent constraints simultaneously: CPU capacity, memory allocation, ephemeral storage, and the node's --max-pods ceiling. Misjudging any dimension leads to bin packing waste, unschedulable workloads, or cascading node-pressure evictions.
How This Calculator Works
This engine models the full Kubernetes node allocatable computation as defined by the Node Allocatable specification. The scheduler does not see the raw node capacity — it sees capacity minus system reservations (kube-reserved + system-reserved) and eviction thresholds:
| Resource Dimension | Reserved By Default | What Consumes It |
|---|---|---|
| CPU | ~10% of total cores | kubelet, container runtime (containerd/CRI-O), OS daemons, systemd services, node-exporter, log collector agents. On a 16 vCPU node, ~1.6 vCPUs are unavailable for pods. |
| Memory | ~1.5–2.5 GiB | Kernel page cache (not fully evictable), kubelet's own RSS (~200 MB), container runtime (~300–500 MB per node), CNI plugin daemonsets (Calico/Cilium ~100–300 MB), and the hard eviction threshold (--eviction-hard=memory.available<100Mi). |
| Ephemeral Storage | ~5–10 GiB | Container image layers (cached on node), pod emptyDir volumes, container log rotation, and the image GC threshold (--image-gc-high-threshold defaults to 85%). |
| Max Pods | 110 (default) | Each pod consumes one IP address from the node's assigned CIDR range. Cloud providers enforce lower limits based on ENI attachment count (AWS) or subnet prefix allocation (Azure CNI). This is the #1 binding constraint on large nodes (32+ vCPU). |
Cloud Provider Pod Density Limits
| Provider | Max Pods Formula | Example: 16 vCPU Node | Configurable? |
|---|---|---|---|
| AWS EKS | Based on ENI count × IPs per ENI. m5.4xlarge → 8 ENIs × 30 IPs = 234 pods (but limited by --max-pods). The eni-max-pods script derives the exact value. | 58–234 depending on instance | Indirectly — by choosing instance type with more ENIs |
| Google GKE | Default 110, up to 256 for larger node pools. GKE's max-pods scales with node memory: ≤15 GiB → 110, ≤30 GiB → 128, ≤60 GiB → 256. | 110 default, 256 on n1-standard-16 | Yes — --max-pods-per-node on node pool creation |
| Azure AKS | Azure CNI: 30 pods default, configurable per subnet prefix size. Kubenet: 110 default. Azure CNI Overlay (newer): 250 pods. | 30 (Azure CNI) or 250 (CNI Overlay) | Yes — via subnet prefix length and network plugin choice |
| Self-Managed | 110 default via --max-pods kubelet flag. Can be raised to 250+ with appropriate CIDR allocation (/24 subnet = 254 usable IPs). | 110 (default) | Yes — --max-pods in kubelet config |
Bin Packing: Why "12 Pods" on a 16 vCPU Node Is Normal
Engineers often expect to fit vCPUs ÷ pod CPU request pods — e.g., 16 vCPUs ÷ 500m = 32 pods. In practice, after system reservations, daemonsets, anti-affinity rules, and the IP ceiling, the real density is typically 40–60% of the naive calculation. A 16 vCPU node running production workloads at 500m/pod may only host 12–18 pods before CPU pressure triggers the scheduler's preemption logic.
Memory-bound workloads invert the constraint: a node running Redis, Elasticsearch, or Kafka sidecars at 2 GiB/pod can exhaust 64 GiB of memory with just 25–30 pods — far below the IP ceiling of 110. Always profile for your workload, not generic ratios.
CPU Sizing in millicores
Kubernetes measures CPU in milliCPU (1/1000 of a vCPU/hyperthread). A pod requesting 500m gets 0.5 vCPU cores of guaranteed compute. Unlike memory, CPU is compressible — pods exceeding their request will be throttled (CFS quota), not killed. This makes CPU the safer over-subscription target, but sustained throttling introduces tail latency spikes that cascade through upstream callers.
📖 Read the full analysis: Kubernetes Pod Density: Why 110 Pods Is a Lie — The Hidden Limits That Cap Your Node — a 14-minute deep-dive covering the four binding constraints across EKS/GKE/AKS, the DaemonSet tax, bin packing fragmentation math, CPU vs memory overcommit strategies, and a five-rule node sizing framework.