Right-Sizing & Spot Strategy for Cost
Set requests honestly, diversify Spot across many pools, and protect the few pods that must never be interrupted.
Most EKS bills are bloated for two boring reasons: requests set far above real usage, and everything running on on-demand. Fix those two and you routinely cut compute cost by half.
Right-size with real data
- The scheduler packs nodes by
requests, not actual use. A pod requesting 2 vCPU but using 0.2 wastes 90% of the slot it reserves. - Use the Vertical Pod Autoscaler in recommendation mode (or metrics from Container Insights / Prometheus) to see what pods really consume, then set requests close to the p95.
- Set
requeststo reserve headroom; keep CPUlimitsloose (or unset) so bursts aren't throttled, but always set memory limits to prevent noisy-neighbor OOM.
Spot the right way
- Diversify. Spread across many instance types and AZs so one interruption event can't drain your whole fleet. This is where Karpenter or a mixed-instances ASG shines.
- Handle interruptions. Spot gives a 2-minute warning; make sure pods have
PodDisruptionBudgetsand graceful shutdown so they drain cleanly. - Keep an on-demand floor. Run stateful or single-replica critical workloads on on-demand (or a small guaranteed group) and let stateless, replicated work ride Spot.
Split by lifecycle
Label nodes by lifecycle and use nodeSelector/affinity so batch and stateless tiers prefer Spot, while databases and controllers stay on-demand.
Example
# A stateless deployment that prefers Spot but tolerates its taint
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 6
template:
spec:
nodeSelector:
karpenter.sh/capacity-type: spot
tolerations:
- key: karpenter.sh/capacity-type
operator: Equal
value: spot
effect: NoSchedule
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels: { app: web }
containers:
- name: web
image: public.ecr.aws/nginx/nginx:1.27
resources:
requests: { cpu: "200m", memory: "256Mi" }
limits: { memory: "256Mi" }When to use it
- A cost team runs the Vertical Pod Autoscaler in recommendation mode to discover that half their pods over-request CPU by 4x and corrects requests to reduce wasted Spot node capacity.
- A platform team configures node groups with 10 Spot instance types across multiple families so Spot interruptions in one pool are absorbed by available capacity in another.
- A DevOps engineer uses AWS Spot Interruption Notices via IMDS to gracefully drain batch pods before the 2-minute reclaim window expires.
More examples
Spot node group with instance diversification
Defines a Spot managed node group with five instance types so Spot capacity shortfalls in one type automatically fall back to alternatives.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: prod
region: us-east-1
managedNodeGroups:
- name: spot-workers
instanceTypes:
- m5.xlarge
- m5a.xlarge
- m4.xlarge
- m5d.xlarge
- m5n.xlarge
spot: true
minSize: 0
maxSize: 30Set honest resource requests
Resource requests set to actual measured usage rather than guesses, enabling tighter bin-packing on Spot nodes and more accurate autoscaler decisions.
containers:
- name: api
resources:
requests:
cpu: "200m" # actual P95 usage from VPA recommendations
memory: "256Mi"
limits:
cpu: "800m" # burst headroom
memory: "512Mi"Handle Spot interruption gracefully
Sets a 90-second grace period and preStop hook so in-flight requests complete before the pod is terminated on Spot interruption.
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
terminationGracePeriodSeconds: 90
containers:
- name: worker
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10"]
Discussion