Amazon EKS — Node Group Upgrade
After the control plane is upgraded, node groups must be updated to match. Managed node groups support rolling updates; self-managed and Karpenter nodes use different strategies.
Managed Node Group Rolling Update
Trigger Update
aws eks update-nodegroup-version \
--cluster-name my-cluster \
--nodegroup-name my-node-group
Or target a specific AMI release version:
aws eks update-nodegroup-version \
--cluster-name my-cluster \
--nodegroup-name my-node-group \
--release-version 1.30.0-20240625
eksctl
eksctl upgrade nodegroup \
--cluster my-cluster \
--name my-node-group \
--kubernetes-version 1.30
Rolling Update Process
- EKS creates new nodes with the updated AMI
- New nodes join the cluster and become Ready
- EKS cordons old nodes (prevents new pods from scheduling)
- EKS drains old nodes (evicts pods respecting PDBs)
- Pods reschedule on new nodes
- Old nodes are terminated
Update Configuration
Control how aggressive the rolling update is:
aws eks update-nodegroup-config \
--cluster-name my-cluster \
--nodegroup-name my-node-group \
--update-config '{
"maxUnavailable": 1
}'
| Setting | Description | Trade-off |
|---|---|---|
maxUnavailable: 1 |
One node at a time | Slow but safe |
maxUnavailable: 3 |
Three nodes at a time | Faster but needs capacity |
maxUnavailablePercentage: 33 |
33% of nodes at once | Scales with node count |
Terraform
resource "aws_eks_node_group" "main" {
cluster_name = module.eks.cluster_name
node_group_name = "main"
# ...
update_config {
max_unavailable = 1
}
# Triggers rolling update when AMI changes
release_version = nonsensitive(data.aws_ssm_parameter.eks_ami.value)
}
data "aws_ssm_parameter" "eks_ami" {
name = "/aws/service/eks/optimized-ami/${module.eks.cluster_version}/amazon-linux-2/recommended/release_version"
}
Force Update
If a rolling update gets stuck (e.g., PDBs blocking drain):
aws eks update-nodegroup-version \
--cluster-name my-cluster \
--nodegroup-name my-node-group \
--force
Warning: Force update ignores PDBs — pods are evicted immediately. Use only when stuck.
Self-Managed Node Upgrade
Self-managed nodes don’t support rolling updates natively. Options:
Option 1 — Update Launch Template + Instance Refresh
# Update launch template with new AMI
aws ec2 create-launch-template-version \
--launch-template-id lt-12345 \
--source-version 1 \
--launch-template-data '{"ImageId": "ami-newversion"}'
# Trigger instance refresh
aws autoscaling start-instance-refresh \
--auto-scaling-group-name my-asg \
--preferences '{"MinHealthyPercentage": 90}'
Option 2 — Create New ASG, Migrate, Delete Old
- Create a new ASG with the updated AMI
- Cordon old nodes:
kubectl cordon <node> - Drain old nodes:
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data - Scale down old ASG
Karpenter Node Upgrade (Drift)
Karpenter detects configuration drift and replaces nodes automatically:
- Update EC2NodeClass with new AMI:
spec:
amiSelectorTerms:
- alias: al2023@latest # Points to new AMI
- Karpenter detects nodes running old AMI → marks them for disruption
- Workloads are drained and rescheduled
- New nodes launched with updated AMI
To force immediate replacement:
# Delete the node claim
kubectl delete nodeclaim <name>
Fargate Pod Upgrade
Fargate pods run on AWS-managed infrastructure. To upgrade:
# Delete pods — they'll be recreated on updated infrastructure
kubectl rollout restart deployment -n production
Verifying Node Upgrade
# Check node versions
kubectl get nodes -o wide
# All nodes should show the target version
kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.kubeletVersion}'
# Check for any nodes still on old version
kubectl get nodes -o custom-columns='NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion'
Best Practices
- Set
maxUnavailablebased on capacity — ensure enough headroom for pods during drain - Always configure PDBs — protect critical workloads during rolling updates
- Upgrade node groups immediately after control plane — minimize version skew
- Use Karpenter drift for automatic node rotation — simplest approach
- Monitor node count during upgrade — ensure new nodes are joining before old ones are removed