interview-prep

Crisp answer: Managed node groups are EC2 Auto Scaling Groups that EKS owns and operates. AWS handles node provisioning, OS patching, and the drain-and-terminate workflow during upgrades. You configure the instance type, size, labels, and taints.

Managed vs self-managed vs Fargate:

Managed node groups:
  - AWS manages the ASG, launch template, and node lifecycle
  - AWS handles graceful drain on termination
  - Supports spot instances and multiple instance types
  - Cannot customise the bootstrap script beyond limited options
  - Best for: most workloads

Self-managed node groups:
  - You manage the ASG, launch template, and AMI updates
  - Full control over bootstrap, custom AMIs, Windows nodes
  - More operational burden
  - Best for: custom OS requirements, Windows, or GPU workloads with
    specific driver needs

Fargate profiles:
  - No nodes to manage at all
  - Each pod runs in its own micro-VM (Firecracker)
  - No DaemonSets (no node to run them on)
  - No privileged containers
  - Cannot use EBS volumes (only EFS)
  - Best for: burst workloads, compliance (workload isolation), simplicity

Creating a managed node group:

resource "aws_eks_node_group" "workers" {
  cluster_name    = aws_eks_cluster.main.name
  node_group_name = "workers"
  node_role_arn   = aws_iam_role.node.arn
  subnet_ids      = module.networking.private_subnet_ids

  instance_types = ["m5.large", "m5.xlarge"]  # multiple types for spot diversity

  scaling_config {
    desired_size = 3
    min_size     = 2
    max_size     = 10
  }

  update_config {
    max_unavailable_percentage = 25  # max % of nodes unavailable during update
  }

  launch_template {
    id      = aws_launch_template.workers.id
    version = aws_launch_template.workers.latest_version
  }

  labels = {
    role = "worker"
    team = "platform"
  }

  taint {
    key    = "dedicated"
    value  = "gpu"
    effect = "NO_SCHEDULE"
  }

  tags = local.common_tags

  depends_on = [
    aws_iam_role_policy_attachment.worker_node,
    aws_iam_role_policy_attachment.cni,
    aws_iam_role_policy_attachment.ecr_read,
  ]
}

Spot instances with managed node groups:

resource "aws_eks_node_group" "spot_workers" {
  capacity_type  = "SPOT"
  instance_types = ["m5.large", "m5.xlarge", "m4.large", "m4.xlarge"]
  # Multiple instance types = better spot availability and fewer interruptions
}

Node labels and taints for workload placement:

# Schedule only monitoring pods on the monitoring node group
# Node taint:
taint:
  key: dedicated
  value: monitoring
  effect: NoSchedule

# Pod toleration:
tolerations:
- key: dedicated
  value: monitoring
  effect: NoSchedule

# Combined with nodeAffinity for hard placement:
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: role
          operator: In
          values: ["monitoring"]

What to say in the interview:

"Managed node groups are the right default for EKS. AWS handles the node lifecycle: provisioning, OS patching, and the graceful drain-and-terminate during upgrades. You give up some customisation but gain significantly less operational burden. I use multiple instance types in a node group for spot instances so that if one type is unavailable AWS tries another. For workloads that need isolation I add taints to the node group and tolerations to the pods — that guarantees certain workloads only land on dedicated nodes."


My notes