Amazon EKS — Spot Instances
Spot Instances on EKS
Spot instances let you use spare EC2 capacity at 60-90% discount. The trade-off: AWS can reclaim them with 2 minutes notice.
How Spot Works on EKS
Spot Instance Lifecycle
┌──────────────────────────────────────────────────┐
│ │
│ 1. EKS requests Spot instance from EC2 │
│ 2. AWS allocates spare capacity (60-90% off) │
│ 3. Instance runs normally │
│ 4. AWS needs capacity back: │
│ → 2-minute interruption notice │
│ → Node is drained (managed node groups) │
│ → Pods rescheduled to other nodes │
│ 5. New Spot instance requested to replace it │
│ │
└──────────────────────────────────────────────────┘
Spot Node Group
managedNodeGroups:
- name: spot-workers
instanceTypes:
- m5.large # Always specify multiple types!
- m5a.large # AMD alternative
- m4.large # Previous generation
- m5d.large # With local NVMe
spot: true
desiredCapacity: 3
minSize: 0
maxSize: 20
labels:
lifecycle: spot
taints:
- key: spot
value: "true"
effect: PreferNoSchedule # Prefer On-Demand, use Spot if available
Rule: Always specify at least 3 instance types for Spot. This gives AWS more capacity pools to draw from, reducing interruptions.
When to Use Spot
| Workload | Spot Safe? | Why |
|---|---|---|
| Stateless web servers | ✅ Yes | Easily replaced, load-balanced |
| Worker/queue consumers | ✅ Yes | Jobs retry on interruption |
| Batch processing | ✅ Yes | Checkpointed, resumable |
| CI/CD runners | ✅ Yes | Builds can restart |
| Databases | ❌ No | Data loss risk |
| Single-replica services | ❌ No | No failover during interruption |
Spot + On-Demand Mix
Best practice: mix Spot and On-Demand:
managedNodeGroups:
# Baseline: On-Demand (always available)
- name: on-demand
instanceType: m5.large
desiredCapacity: 2
minSize: 2
maxSize: 4
labels:
lifecycle: on-demand
# Burst: Spot (cheap scaling)
- name: spot
instanceTypes: [m5.large, m5a.large, m4.large]
spot: true
desiredCapacity: 2
minSize: 0
maxSize: 20
labels:
lifecycle: spot
Cost Examples
| Instance | On-Demand/hr | Spot/hr | Monthly Savings (per node) |
|---|---|---|---|
| m5.large | $0.096 | $0.035 | $44 (64% off) |
| m5.xlarge | $0.192 | $0.070 | $89 (64% off) |
| c5.xlarge | $0.170 | $0.055 | $84 (68% off) |
| r5.large | $0.126 | $0.040 | $63 (68% off) |
Common Mistakes
| Mistake | Fix |
|---|---|
| Only one instance type for Spot | Use 3+ types for capacity diversity |
| Spot for databases | Use On-Demand for stateful workloads |
| No On-Demand baseline | Always have some On-Demand capacity |
| No PodDisruptionBudget | Set PDBs so draining doesn’t kill all pods |
Quick Reference
# Create Spot node group
$ eksctl create nodegroup --cluster demo --name spot \
--instance-types m5.large,m5a.large,m4.large \
--spot --nodes 3
# Check node lifecycle
$ kubectl get nodes -L lifecycle
What’s Next?
Practice: Node Groups Exercises.