Amazon EKS — Node Groups — Practice Exercises

2 minute read

Chapter 5 — Practice Exercises


Exercise 1: Node Group Design

Question: Design node groups for a cluster running: 3 microservices (steady load), a Redis cache (memory-intensive), and batch ML training jobs (GPU, intermittent). Include instance types, scaling, and labels/taints.

Show Solution
managedNodeGroups:
  - name: general
    instanceType: m5.large
    desiredCapacity: 3
    minSize: 2
    maxSize: 8
    labels: { workload: general }

  - name: memory
    instanceType: r5.large
    desiredCapacity: 2
    minSize: 1
    maxSize: 4
    labels: { workload: memory }
    taints:
      - key: dedicated
        value: memory
        effect: NoSchedule

  - name: gpu-training
    instanceType: g4dn.xlarge
    desiredCapacity: 0
    minSize: 0
    maxSize: 4
    spot: true
    labels: { workload: gpu }
    taints:
      - key: nvidia.com/gpu
        value: "true"
        effect: NoSchedule

GPU nodes start at 0 and scale up only when training jobs are submitted.


Exercise 2: Max Pods Calculation

Question: Calculate the maximum number of pods for an m5.xlarge instance. It has 4 ENIs with 15 IPs per ENI. Show the formula.

Show Solution

Formula: Max Pods = (ENIs × IPs per ENI) - 1

m5.xlarge:
  ENIs: 4
  IPs per ENI: 15
  Max Pods = (4 × 15) - 1 = 59

The EKS default is 58 (slightly lower due to reserved IPs).

With prefix delegation enabled: Max Pods = (ENIs × (IPs per ENI - 1) × 16) + 2 = much higher (110+).


Exercise 3: Spot Strategy

Question: Why should you specify at least 3 instance types for Spot node groups? What happens if you only specify one?

Show Solution

Why 3+ instance types:

  • Each instance type in each AZ is a separate Spot capacity pool
  • More pools = more chances of getting capacity
  • If one pool is interrupted, others may still have availability
  • AWS Spot best practice documentation recommends diversification

With only 1 type:

  • Single capacity pool per AZ
  • Higher interruption rate
  • Possible complete capacity loss during demand spikes
  • All nodes could be reclaimed simultaneously

Example: m5.large only → 1 pool per AZ = 2-3 pools m5.large + m5a.large + m4.large → 3 pools per AZ = 6-9 pools


Exercise 4: Bottlerocket vs AL2

Question: Your security team requires minimal attack surface, no SSH, and immutable infrastructure. Which AMI should you use and why?

Show Solution

Use Bottlerocket.

Requirement Bottlerocket
Minimal attack surface ✅ No shell, no package manager
No SSH ✅ SSH disabled by default (use SSM)
Immutable infrastructure ✅ Read-only root filesystem, atomic updates

Additional benefits:

  • Automatic security updates via atomic A/B partition swap
  • Only container runtime + kubelet installed
  • Smaller base image = faster boot
  • CIS benchmarks compliance built-in

Exercise 5: Node Troubleshooting

Question: A node shows NotReady status. List 5 things you would check and the commands to check them.

Show Solution
# 1. Check node conditions
$ kubectl describe node <node-name> | grep -A5 "Conditions:"

# 2. Check kubelet logs (SSH or SSM into node)
$ journalctl -u kubelet -n 100 --no-pager

# 3. Check system pods on that node
$ kubectl get pods -A --field-selector spec.nodeName=<node-name>

# 4. Check EC2 instance status
$ aws ec2 describe-instance-status --instance-ids <instance-id>

# 5. Check security groups (node-to-control-plane communication)
$ aws ec2 describe-security-groups --group-ids <sg-id>

Common causes of NotReady:

  • kubelet can’t reach API server (security group issue)
  • Disk pressure (volume full)
  • Memory pressure (OOM)
  • VPC CNI IP exhaustion
  • Certificate expired

What’s Next?

Serverless pods: Chapter 6 — Fargate.