Amazon EKS — Spot Instances

1 minute read

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.