EKS Managed Node Groups Explained: How They Work, When to Use Them, and Best Practices

Amazon EKS managed node groups let AWS handle the machinery of running EC2 worker nodes: provisioning them, registering them with your cluster, and replacing them gracefully when you trigger an update. Instead of writing bootstrap scripts and drain-and-replace automation yourself, you define what you want and AWS sets up the underlying infrastructure.

The payoff is real, but it is not total automation. You still choose instance types, set scaling boundaries, decide when updates happen, and stay responsible for your workloads. Managed node groups remove the plumbing work. They do not remove the need to understand what is running on your nodes.

What this page covers
  • What a managed node group is and how it differs from the EKS control plane
  • Exactly what AWS manages for you vs what you still own
  • How the update lifecycle works: AMI refreshes, Kubernetes version changes, and node draining
  • When to use managed node groups vs Fargate or self-managed nodes
  • Autoscaling, Spot instances, and common operational mistakes

What EKS managed node groups are#

An EKS cluster has two distinct layers: a control plane and worker nodes.

The control plane (the Kubernetes API server, scheduler, etcd, and controller manager) runs in AWS-managed infrastructure. You never provision or patch it. AWS operates it entirely on your behalf. See the Amazon EKS Overview for how the control plane fits into the full EKS architecture.

The worker nodes are EC2 instances that run in your account, in your VPC. Each node runs the kubelet agent, the containerd container runtime, and the VPC CNI plugin. When a pod is scheduled, Kubernetes picks a node, and kubelet on that node pulls the container image and starts the pod. Your application workloads live here.

A managed node group is a named collection of EC2 worker nodes managed through EKS abstractions. AWS creates an Auto Scaling Group, configures a launch template, runs the bootstrap process that registers each instance with the cluster, and exposes the group through the EKS API. You interact with the node group as a single logical object, not with individual instances or Auto Scaling Group settings directly.

The key division

The control plane is truly locked down by AWS. You cannot SSH into it, patch it, or configure it directly. The worker nodes are different: they are EC2 instances running in your AWS account, and you are responsible for their shape, security posture, and update schedule. “Managed” means the orchestration is handled for you, not that AWS owns the machines.

For a side-by-side comparison of all three EKS compute options (managed node groups, self-managed nodes, Fargate), see EKS Node Groups Explained.

Simple explanation#

A managed node group is a managed pool of EC2 worker nodes for your EKS cluster. Each node is a regular EC2 instance running in your AWS account, in your VPC, on your subnets. AWS creates the underlying Auto Scaling Group and configures the bootstrap process to register each node automatically. When you trigger an update, AWS handles the rolling replacement so you do not have to script it yourself.

The word “managed” describes the orchestration layer, not ownership. Your workloads run on EC2 instances that appear in your account and generate charges on your bill.

🏗️

Analogy

Think of managed node groups like hiring through a staffing agency that handles recruiting, onboarding paperwork, and exit processes. You still decide how many people you need, what roles they fill, and what work they do. The agency removes the administrative overhead of the hiring lifecycle. The workers still work for you.

What AWS manages vs what you still manage#

This is the most important thing to understand about managed node groups. The split is clear, but it surprises a lot of people who expect more to be handled automatically.

What AWS manages:

What you still manage:

Common misconception

AWS does not automatically patch your nodes. When AWS releases a new EKS-optimized AMI with OS patches or a Kubernetes component update, those updates sit waiting until you deploy them. Nothing applies itself. You are responsible for triggering updates on a schedule that keeps your nodes current.

Quick check

If you are currently writing scripts to bootstrap nodes, drain them before updates, or manage rolling AMI replacements — managed node groups handle all of that. If your bottleneck is something else (custom OS images, hardened kernel configs, or non-standard bootstrap logic) you may need self-managed nodes instead.

How managed node groups work#

When you create a managed node group, EKS creates an EC2 Auto Scaling Group in your account and attaches a launch template configured with the EKS-optimized AMI. That AMI includes kubelet, containerd, and the VPC CNI plugin, all pre-wired to connect to your cluster.

Each instance the ASG launches runs a bootstrap script automatically. The script calls the EKS API to fetch cluster configuration, starts kubelet, and registers the node with the Kubernetes control plane. Once registered, the node appears in kubectl get nodes and becomes available for scheduling.

Labels and taints you define on the node group are applied to every node at bootstrap time. A node group with role=gpu can receive GPU-intensive pods via node selectors. A node group with spot=true:NoSchedule ensures only tolerating pods land on Spot capacity.

For EKS networking, each node gets ENIs from the VPC CNI plugin and pods receive IP addresses directly from your subnet CIDR range.

Do not manually edit the auto-generated launch template

Changes made directly to the auto-generated launch template outside the EKS API will put the node group into an inconsistent state and can break future updates. If you need custom configuration, supply your own launch template from the start rather than modifying the one EKS created.

When to use managed node groups#

Managed node groups are the right default for most EKS clusters:

When not to use managed node groups#

Managed node groups are not the right fit for every situation.

Use self-managed nodes when:

Use Fargate when:

Managed node groups vs self-managed nodes vs Fargate#

CapabilityManaged Node GroupSelf-Managed NodesFargate
ProvisioningAWS creates and manages the ASG and launch templateYou create and manage the ASGNo EC2 to provision; pods run on AWS-managed infrastructure
Upgrade responsibilityYou trigger updates; AWS handles rolling replacementYou write and run your own drain-and-replace automationAWS handles pod-level updates transparently
Node drain behaviorAutomated by AWS during updates; respects PDBsManual or scripted by youNo nodes to drain
Custom AMI flexibilityLimited: AL2 and AL2023-based custom AMIs with caveatsFull control: any AMI you can bootNot applicable
DaemonSet supportYesYesNo
Spot supportYes, via capacityType SPOTYesNo
GPU instancesYesYesLimited
EKS console visibilityFull: group status, version, healthLimited: nodes visible but not as a groupYes, at the Fargate profile level
Operational overheadLow: lifecycle managed by AWSHigh: you own the full lifecycleVery low: no nodes to manage
Best fitMost production EKS clustersHighly customized OS or AMI requirementsServerless pods, irregular workloads

Autoscaling and capacity planning#

Managed node groups scale the node fleet. They do not scale individual workloads. These are separate concerns and it helps to keep them distinct.

HPA vs Cluster Autoscaler: the key mental model

HPA scales your pods. It adds or removes replicas of your application based on CPU, memory, or custom metrics. Cluster Autoscaler scales your nodes. It adds or removes EC2 instances based on whether pods can be scheduled. They work together: HPA requests more pod copies, Cluster Autoscaler provides the nodes for those copies to run on.

Horizontal Pod Autoscaling (HPA) adds or removes pod replicas based on CPU, memory, or custom metrics. HPA works within the node capacity that already exists. If all nodes are full and you have no more room to schedule pods, HPA cannot help. New replicas will sit in Pending state until more nodes arrive.

Cluster Autoscaler watches for Pending pods and increases the desired capacity on the relevant node group to add nodes. When nodes are consistently underutilised, it scales down, draining pods off lightly loaded nodes and terminating the instances. To discover your node groups, the Cluster Autoscaler requires two EC2 tags on the underlying Auto Scaling Group:

Without both tags, the Cluster Autoscaler will not manage that node group.

Karpenter is a faster, more direct approach. Instead of adjusting ASG desired capacity and waiting for instances to bootstrap, Karpenter calls the EC2 API directly, selects the optimal instance type for each batch of pending pods, and provisions nodes more quickly. Some teams using Karpenter bypass managed node groups and use EC2 NodePools instead. For most teams not yet running Karpenter, the Cluster Autoscaler with managed node groups is the simpler starting point.

Multiple node groups let you separate workloads with different requirements. A common production pattern: one on-demand group for stateful services and the API tier, one Spot group for batch jobs and stateless services, and optionally a dedicated group for GPU workloads. Use Kubernetes node labels to express what a group is for and node taints to enforce that only the right workloads land there. A pod that does not tolerate the Spot taint will never be scheduled onto the Spot node group. This makes Spot opt-in rather than accidental.

AMI updates, Kubernetes version updates, and node draining#

There are three distinct types of changes that trigger a node replacement cycle in managed node groups. They all use the same rolling replacement mechanism, but they come from different sources and happen at different times.

AMI refreshes happen when AWS publishes a new EKS-optimised AMI with OS security patches, kernel updates, or updated container runtime versions. These do not change the Kubernetes version running on the node. You check whether a new AMI version is available and trigger the update yourself. Nothing applies automatically.

Kubernetes version updates are a bigger change. When you upgrade the EKS control plane to a new minor version, your node groups still run the previous version. You must then update the node groups separately to align them with the new control plane. See Upgrading EKS Clusters Safely for the full upgrade sequence and why the ordering matters.

Version skew

EKS supports nodes running up to one minor version behind the control plane, but the specific supported skew may change across EKS releases. Check the current EKS documentation before planning upgrades. Running nodes significantly behind the control plane makes the next upgrade harder and is a common source of upgrade problems.

Launch template or configuration changes (modifying instance type, disk size, user data, or security groups) also trigger a rolling replacement when applied.

All three use the same rolling replacement flow:

  1. A new node launches with the updated AMI.
  2. Once ready and registered, one old node is cordoned: no new pods will schedule onto it.
  3. The old node is drained using the Kubernetes eviction API and existing pods are rescheduled elsewhere.
  4. The drained node is terminated.
  5. This repeats for every node in the group.
🚗

Analogy

A rolling update is like replacing the tyres on a moving car one at a time. You jack up one wheel, swap it out, lower the car, and move to the next. The car keeps rolling throughout because you never have more than one wheel off the ground at a time. maxUnavailable is how many wheels you are allowed to swap at once.

The updateConfig.maxUnavailable setting controls concurrency. maxUnavailable: 1 means one node is replaced at a time: safest, but slowest for large groups. Setting it to 2 or 3 speeds up replacements for big node groups.

# Check the current AMI release version your node group is running
aws eks describe-nodegroup \
  --cluster-name my-cluster \
  --nodegroup-name general-workers \
  --query 'nodegroup.releaseVersion'

# Trigger an AMI update to the latest published version
aws eks update-nodegroup-version \
  --cluster-name my-cluster \
  --nodegroup-name general-workers
PDB behavior during updates

Managed node group updates respect pod disruption budgets. If a PDB prevents safe eviction, the drain waits until it can proceed. If the drain cannot complete within the timeout, the update fails. Before triggering node group updates, check that your PDBs and replica counts allow at least one pod per deployment to be evicted per node. A PDB set so tightly that no pod can be removed will stall the update and force a manual intervention.

Using Spot with managed node groups#

Managed node groups support Spot instances via capacityType: SPOT. For batch jobs, stateless web services, dev environments, and other interruption-tolerant workloads, Spot can reduce EC2 costs substantially compared to on-demand pricing.

Never run these workloads on Spot

Databases, message queue brokers, stateful caches, and any workload where a 2-minute shutdown window causes data loss or a service outage must run on on-demand nodes. Spot interruptions are not gradual — AWS gives a 2-minute notice and reclaims the instance. There is no negotiation.

Spot and on-demand should be separate node groups. Mixing them in a single group makes it harder to prevent critical workloads from landing on interruptible instances. Run one on-demand node group for services that must stay up, and one or more Spot node groups for cost-sensitive workloads.

Use a taint on the Spot node group so only pods that explicitly tolerate it are scheduled there:

managedNodeGroups:
  - name: on-demand-workers
    instanceType: m5.large
    capacityType: ON_DEMAND
    minSize: 2
    maxSize: 10
    privateNetworking: true

  - name: spot-workers
    instanceTypes:
      - m5.large
      - m5.xlarge
      - m4.large
      - m4.xlarge
    capacityType: SPOT
    minSize: 0
    maxSize: 20
    labels:
      lifecycle: spot
    taints:
      - key: spot
        value: "true"
        effect: NoSchedule
Use multiple instance types

When you specify multiple instance types, AWS can source Spot capacity from several pools. If m5.large capacity is unavailable, it falls back to m4.large or m5.xlarge. The more instance types you list, the more resilient your Spot node group is to interruptions and capacity shortages.

Install the AWS Node Termination Handler so nodes drain gracefully when a Spot interruption notice arrives:

helm repo add eks https://aws.github.io/eks-charts
helm install aws-node-termination-handler \
  --namespace kube-system \
  eks/aws-node-termination-handler

Launch templates, custom AMIs, and node auto repair#

By default, EKS generates a launch template for your managed node group. If you need custom configuration such as a hardened AMI, additional packages at boot, or custom user-data, you can supply your own launch template. There are constraints:

Node auto repair is an optional feature that detects nodes in a degraded or unresponsive state and replaces them automatically. When enabled, EKS monitors node health and initiates replacement without manual intervention. This is useful in production clusters where a silently failed node might otherwise go unnoticed until it affects workloads.

Private subnet and networking considerations#

Managed node groups support privateNetworking: true, which places nodes in private subnets with no public IP. This is the recommended configuration for production clusters and is required for private EKS clusters.

Nodes in private subnets still need outbound access to several services:

Without these routes, node bootstrap can fail silently or pods will fail to start because images cannot be pulled. See EKS Networking Model for a full walkthrough of how VPC CNI and subnet routing work together.

eksctl configuration example#

A production-ready managed node group configuration in an eksctl cluster file:

managedNodeGroups:
  - name: general-workers
    instanceType: m5.large
    capacityType: ON_DEMAND
    minSize: 2
    maxSize: 12
    desiredCapacity: 4
    privateNetworking: true
    availabilityZones:
      - eu-west-1a
      - eu-west-1b
      - eu-west-1c
    labels:
      role: general
      environment: production
    iam:
      withAddonPolicies:
        autoScaler: true
        cloudWatch: true
        albIngress: true
    updateConfig:
      maxUnavailable: 1

  - name: spot-workers
    instanceTypes:
      - m5.large
      - m5.xlarge
      - m4.large
      - m4.xlarge
    capacityType: SPOT
    minSize: 0
    maxSize: 20
    desiredCapacity: 2
    privateNetworking: true
    labels:
      role: spot
      lifecycle: spot
    taints:
      - key: spot
        value: "true"
        effect: NoSchedule
    updateConfig:
      maxUnavailable: 2

The Spot node group specifies multiple instance types for capacity diversity and applies a taint requiring tolerations. Critical workloads that lack the toleration will never be scheduled onto interruptible Spot capacity.

Common mistakes#

  1. Assuming AWS patches nodes automatically. AWS publishes new EKS-optimized AMIs but does not apply them. Nodes only update when you trigger an update. Set a schedule and check for new AMI releases after every EKS version update.

  2. Treating managed node groups as fully hands-off Kubernetes. Managed node groups reduce node lifecycle work. They do not remove responsibility for workload design, update timing, security group configuration, IAM policy correctness, or cost control.

  3. Mixing Spot and on-demand in the same node group. Without separation, critical workloads can land on Spot nodes and get interrupted. Always taint Spot node groups to make Spot placement opt-in.

  4. Upgrading the control plane but forgetting node groups. After a Kubernetes control plane upgrade, node groups still run the previous version. EKS supports nodes one minor version behind the control plane, but running further behind is unsupported. See Upgrading EKS Clusters Safely for the right upgrade sequence.

  5. Not planning PDBs and replica counts before upgrades. If all replicas of a deployment sit on the same node, draining that node takes the service offline. If a PDB is set too restrictively, the drain stalls and the update fails. Before triggering updates, confirm replica counts are spread across nodes and PDBs allow at least one eviction per node.

  6. Using one node group for every workload. A single flat node group makes it hard to isolate workloads with different resource profiles, compliance requirements, or Spot tolerance. Use multiple node groups with labels and taints from the start.

  7. Misunderstanding Cluster Autoscaler tag requirements. Managed node groups are automatically discoverable by the Cluster Autoscaler. The k8s.io/cluster-autoscaler/enabled and k8s.io/cluster-autoscaler/<cluster-name> tags are required for standard discovery. If you also want the autoscaler to honor specific node labels or taints for scale-from-zero behavior, you need additional k8s.io/cluster-autoscaler/node-template/ tags. Those extra tags are not required for basic scaling.

Pricing#

There is no additional charge for using managed node groups. You pay for the EC2 instances, EBS volumes, and any other AWS resources the node group creates, the same charges you would incur with self-managed nodes. The managed lifecycle layer itself is free.

Using Spot instances in managed node groups can reduce EC2 compute costs substantially for the right workloads. See AWS EC2 Spot Instances Explained for how Spot pricing and interruption work.

Frequently asked questions

What does AWS manage in an EKS managed node group?

AWS provisions the EC2 instances, creates and manages the underlying Auto Scaling Group and launch template, registers nodes with the cluster, and handles rolling node replacement during updates, including graceful pod draining. You manage instance type selection, scaling bounds, labels, taints, security group rules, add-ons, and the timing of when updates are applied.

Do managed node groups update automatically?

No. AWS makes new AMI versions available when EKS-optimised AMIs are updated, but your node group does not update automatically. You choose when to trigger an update via the console, CLI, or IaC, and AWS performs the rolling replacement. This gives you control over your maintenance windows.

Can I use custom AMIs or launch templates with managed node groups?

Yes, with limitations. You can provide a custom launch template to specify a custom AMI (AL2 or AL2023 based), user data, and other instance configuration. However, some launch template fields are reserved for AWS. For fully custom OS images or kernel configurations, self-managed node groups give you more control.

Can I run Spot instances in managed node groups?

Yes. Set capacityType: SPOT (or spot: true in eksctl) and specify multiple instance types to improve Spot availability. When a Spot interruption occurs, EKS drains the node before it is reclaimed. You should also install the AWS Node Termination Handler DaemonSet to react to Spot interruption notices more reliably.

When should I choose managed node groups over Fargate or self-managed nodes?

Choose managed node groups for most production workloads where you need DaemonSets, persistent storage, GPU instances, or fine-grained control over instance types and placement. Choose Fargate for workloads that need strong isolation or where you want zero node management. Choose self-managed nodes only when you need custom AMIs, specific kernel versions, or configurations that managed node groups do not expose.

Last verified: 4 April 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.