Crisp answer: Upgrade in three stages: control plane first, then cluster add-ons, then node groups. Each stage must be healthy before proceeding to the next. Never skip minor versions.
Pre-upgrade checklist:
# 1. Check current cluster version
aws eks describe-cluster --name my-cluster --query cluster.version --output text
# 1.28
# 2. Check if the target version is available
aws eks describe-addon-versions --kubernetes-version 1.29 --region eu-west-2 \
--query 'addons[].{name:addonName,versions:addonVersions[0].addonVersion}'
# 3. Check for deprecated API versions in your manifests
# Use kubectl-convert or pluto:
pluto detect-all-in-cluster --target-versions k8s=v1.29
# 4. Review the EKS release notes for breaking changes
# https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html
# 5. Check PodDisruptionBudgets — node drain during upgrade respects these
kubectl get pdb -A
# 6. Ensure workloads have multiple replicas and proper readiness probes
# Single-replica Deployments will have downtime during node replacement
Stage 1 — Upgrade the control plane:
aws eks update-cluster-version \
--name my-cluster \
--kubernetes-version 1.29 \
--region eu-west-2
# Monitor progress:
aws eks describe-update \
--name my-cluster \
--update-id <update-id> \
--region eu-west-2
# Or watch in a loop:
watch aws eks describe-cluster --name my-cluster \
--query cluster.version --output text
# Control plane upgrade takes 10-20 minutes
# Cluster remains available during upgrade (API server has downtime of ~30 seconds)
Stage 2 — Upgrade cluster add-ons:
Add-ons must be compatible with the new Kubernetes version:
# Check current add-on versions
aws eks list-addons --cluster-name my-cluster
# Find the recommended version for each add-on on the new K8s version
aws eks describe-addon-versions \
--addon-name coredns \
--kubernetes-version 1.29 \
--query 'addons[].addonVersions[?compatibilities[?defaultVersion==`true`]].addonVersion'
# Upgrade each add-on
aws eks update-addon \
--cluster-name my-cluster \
--addon-name coredns \
--addon-version v1.11.1-eksbuild.4 \
--resolve-conflicts OVERWRITE
aws eks update-addon \
--cluster-name my-cluster \
--addon-name kube-proxy \
--addon-version v1.29.0-eksbuild.1 \
--resolve-conflicts OVERWRITE
aws eks update-addon \
--cluster-name my-cluster \
--addon-name vpc-cni \
--addon-version v1.18.1-eksbuild.1 \
--resolve-conflicts OVERWRITE
# Monitor each add-on update:
aws eks describe-addon \
--cluster-name my-cluster \
--addon-name coredns \
--query addon.status
Stage 3 — Upgrade node groups:
# Trigger a rolling node replacement
aws eks update-nodegroup-version \
--cluster-name my-cluster \
--nodegroup-name workers \
--kubernetes-version 1.29 \
--region eu-west-2
# EKS will:
# 1. Launch new nodes with the new kubelet version
# 2. Wait for new nodes to become Ready
# 3. Cordon old nodes
# 4. Drain old nodes (respecting PodDisruptionBudgets)
# 5. Terminate old nodes
# 6. Repeat until all nodes are replaced
# Monitor:
aws eks describe-nodegroup \
--cluster-name my-cluster \
--nodegroup-name workers \
--query nodegroup.status
# Watch node versions:
kubectl get nodes -o wide
For self-managed node groups:
# 1. Update the Launch Template with new AMI (EKS-optimised AMI for 1.29)
aws ssm get-parameter \
--name /aws/service/eks/optimized-ami/1.29/amazon-linux-2/recommended/image_id \
--region eu-west-2 --query Parameter.Value --output text
# 2. Apply the updated Launch Template to the ASG
# 3. Perform a rolling instance refresh on the ASG
aws autoscaling start-instance-refresh \
--auto-scaling-group-name my-asg \
--preferences '{"MinHealthyPercentage":90}'
What to say in the interview:
"EKS upgrades are a three-step process: control plane first, add-ons second, nodes third. You cannot skip steps because the kubelet on nodes must be within one minor version of the API server. Before starting I check for deprecated API versions using pluto, verify all workloads have multiple replicas, and check PodDisruptionBudgets so the drain respects minimum availability. The control plane upgrade takes 15-20 minutes and is mostly invisible. Node group upgrade does a rolling replacement — new nodes come up, old nodes get cordoned and drained, then terminated. I have automated four consecutive minor version upgrades on my homelab cluster in a single day using this pattern."