In-place Upgrdae Hands-on
CloudNet 팀의 2026년 AWS EKS Workshop Study 4기 7주차 학습 내용을 담고 있습니다.
Amazon EKS Upgrades: Strategies and Best Practices 워크샵을 정리하였습니다.
1. Control Plane Upgrade
콘솔/CLI/eksctl/CloudFormation/Terraform 의 방법 중, 워크샵 가이드에 따라 Terraform의 변수를 수정하여 Control Plane을 업그레이드합니다. "1.30" -> "1.31"
2. Add-ons / Custom controller Update
CoreDNS, kube-proxy, VPC CNI, EBS CSI Driver의 버전을 업그레이드합니다.
# 가능한 업그레이드 버전 정보 확인
$ eksctl get addon --cluster $CLUSTER_NAME
NAME VERSION STATUS ISSUES IAMROLE UPDATE AVAILABLE CONFIGURATION VALUES
aws-ebs-csi-driver v1.59.0-eksbuild.1 ACTIVE 0 arn:aws:iam::558235332608:role/eksworkshop-eksctl-ebs-csi-driver-2026050211254631980000001d
coredns v1.11.4-eksbuild.32 ACTIVE 0
kube-proxy v1.30.14-eksbuild.28 ACTIVE 0 v1.31.14-eksbuild.12,v1.31.14-eksbuild.9,v1.31.14-eksbuild.6,v1.31.14-eksbuild.5,v1.31.14-eksbuild.2,v1.31.13-eksbuild.2,v1.31.10-eksbuild.12,v1.31.10-eksbuild.8,v1.31.10-eksbuild.6,v1.31.10-eksbuild.2,v1.31.9-eksbuild.2,v1.31.7-eksbuild.7,v1.31.3-eksbuild.2,v1.31.2-eksbuild.3,v1.31.2-eksbuild.2,v1.31.1-eksbuild.2,v1.31.0-eksbuild.5,v1.31.0-eksbuild.2
vpc-cni v1.21.1-eksbuild.8 ACTIVE 0
# coredns - EKS 1.31 버전과 호환되는 애드온 버전 확인
$ aws eks describe-addon-versions --addon-name coredns --kubernetes-version 1.31 --output table \
--query "addons[].addonVersions[:10].{Version:addonVersion,DefaultVersion:compatibilities[0].defaultVersion}"
# kube-proxy - EKS 1.31 버전과 호환되는 애드온 버전 확인
$ aws eks describe-addon-versions --addon-name kube-proxy --kubernetes-version 1.31 --output table \
--query "addons[].addonVersions[:10].{Version:addonVersion,DefaultVersion:compatibilities[0].defaultVersion}"
# addons.tf 수정
eks_addons = {
coredns = {
addon_version = "v1.11.4-eksbuild.33" # EKS 1.31 권장버전
}
kube-proxy = {
addon_version = "v1.31.14-eksbuild.9" # EKS 1.31 권장버전
}
vpc-cni = {
most_recent = true
}
aws-ebs-csi-driver = {
addon_version = "v1.59.0-eksbuild.1" # EKS 1.31 권장버전
service_account_role_arn = module.ebs_csi_driver_irsa.iam_role_arn
}
}
$ terraform plan
$ terraform apply -auto-approve
# 업그레이드 된 Add-on 확인
# 내부적으로 롤링 업데이트가 진행됩니다.
$ kubectl get pod -n kube-system -l 'k8s-app in (kube-dns, kube-proxy)'
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
8 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/aws-ebs-csi-driver:v1.59.0
2 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/coredns:v1.11.4-eksbuild.33
6 602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/kube-proxy:v1.31.14-eksbuild.9
3. Node Group Upgrade
3.1 In-Place Managed Node group Upgrade
Terraform의 variable.tf에서 mng_cluster_version을 1.30 → 1.31로 변경합니다.
사용자 지정 AMI를 직접 지정한 custom 노드그룹의 경우, K8s 1.31에 해당하는 AMI ID를 별도로 조회하여 반영합니다.
# initial 노드그룹: variable.tf에서 mng_cluster_version을 "1.31"로 변경
# custom 노드그룹: 1.31 AMI ID 조회
aws ssm get-parameter --name /aws/service/eks/optimized-ami/1.31/amazon-linux-2023/x86_64/standard/recommended/image_id \
--region $AWS_REGION --query "Parameter.Value" --output text
# ami-02b487869ba8cadfd
# 모니터링
watch -d "aws autoscaling describe-auto-scaling-groups --query 'AutoScalingGroups[*].AutoScalingGroupName' --output json | jq; echo ; kubectl get node -L eks.amazonaws.com/nodegroup; echo; date ; echo ; kubectl get node -L eks.amazonaws.com/nodegroup-image | grep ami"
# 약 20분 소요
terraform apply -auto-approve
업그레이드 진행 중 노드 상태 변화를 확인할 수 있습니다. 기존 노드는 SchedulingDisabled 상태로 전환된 후 새 노드로 교체됩니다.
다음 실습을 위해 custom 노드그룹은 base.tf에서 제거 후 재적용합니다.
3.2 Blue-Green Managed Node Group Upgrade
상태 저장 워크로드(orders-mysql, EBS PVC 사용)가 배포된 blue-mng 노드그룹을 B/G 방식으로 업그레이드합니다.
blue-mng은 특정 AZ, Taint/Label이 지정된 노드그룹입니다.
# blue-mng 노드 확인
kubectl get nodes -l type=OrdersMNG
# Taint 확인
kubectl get nodes -l type=OrdersMNG -o jsonpath="{range .items[*]}{.metadata.name} {.spec.taints[?(@.effect=='NoSchedule')]}{\"\n\"}{end}"
# 해당 노드에서 실행 중인 파드 확인
kubectl describe node -l type=OrdersMNG
base.tf에 동일한 AZ, Taint/Label을 가진 green-mng 노드그룹을 추가합니다. (cluster_version은 1.31 사용)
# 모니터링
watch -d "aws autoscaling describe-auto-scaling-groups --query 'AutoScalingGroups[*].AutoScalingGroupName' --output json | jq; echo ; kubectl get node -L eks.amazonaws.com/nodegroup; echo; date"
# 약 3분 소요
terraform apply -auto-approve
# green-mng 노드 생성 확인 (동일 AZ, 1.31 버전)
kubectl get node -l type=OrdersMNG -L topology.kubernetes.io/zone
# NAME STATUS ROLES AGE VERSION ZONE
# ip-10-0-0-159.us-west-2.compute.internal Ready <none> 109s v1.31.14-eks-bbe087e us-west-2a
# ip-10-0-7-77.us-west-2.compute.internal Ready <none> 46h v1.30.14-eks-bbe087e us-west-2a
PDB로 인한 블로킹을 방지하기 위해 orders 파드 replicas를 2로 늘린 후 blue-mng를 base.tf에서 제거합니다.
# replicas 증가
kubectl scale deploy -n orders orders --replicas 2
# blue-mng 제거 후 적용 (약 10분 소요)
terraform apply -auto-approve
# 최종 노드그룹 확인 (green-mng만 남아있어야 함)
aws eks list-nodegroups --cluster-name eksworkshop-eksctl
# {
# "nodegroups": [
# "green-mng-20260424075552962200000007",
# "initial-2026042209254538750000002b"
# ]
# }
3.3 Upgrading Karpenter Managed Nodes
Karpenter의 Drift 기능을 활용하여 AMI를 업데이트하면 기존 노드가 새 노드로 자동 교체됩니다.
# 현재 카펜터 노드 버전 확인
kubectl get nodes -l team=checkout
# 현재 사용 중인 AMI 확인
kubectl get ec2nodeclass default -o yaml | grep 'id: ami-' | uniq
# 1.31 AMI ID 조회
aws ssm get-parameter --name /aws/service/eks/optimized-ami/1.31/amazon-linux-2023/x86_64/standard/recommended/image_id \
--region ${AWS_REGION} --query "Parameter.Value" --output text
default-ec2nc.yaml의 spec.amiSelectorTerms AMI ID를 1.31 버전으로 교체하고, default-np.yaml의 spec.disruption에 중단 예산을 추가합니다.
# 변경사항 적용 (ArgoCD를 통해 동기화)
cd ~/environment/eks-gitops-repo
git add apps/karpenter/default-ec2nc.yaml apps/karpenter/default-np.yaml
git commit -m "disruption changes"
git push --set-upstream origin main
argocd app sync karpenter
# 카펜터 컨트롤러 로그에서 Drift 이벤트 확인
kubectl -n karpenter logs deployment/karpenter -c controller --tail=33 -f
# 1.31 버전 노드로 교체 완료 확인
kubectl get nodes -l team=checkout
3.4 Upgrading Self-managed Nodes
base.tf의 self_managed_node_groups에서 ami_id를 1.31 버전으로 교체 후 적용합니다.
# 1.31 AMI ID 조회
aws ssm get-parameter --name /aws/service/eks/optimized-ami/1.31/amazon-linux-2023/x86_64/standard/recommended/image_id \
--region $AWS_REGION --query "Parameter.Value" --output text
# 모니터링
while true; do kubectl get nodes -l node.kubernetes.io/lifecycle=self-managed; echo ; \
aws ec2 describe-instances --query "Reservations[*].Instances[*].[Tags[?Key=='Name'].Value | [0], ImageId]" \
--filters "Name=tag:Name,Values=default-selfmng" --output table; echo ; date; sleep 1; echo; done
# 적용
cd ~/environment/terraform/
terraform apply -auto-approve
# 1.31 버전 노드 확인
kubectl get nodes -l node.kubernetes.io/lifecycle=self-managed
신규 버전 EC2가 Ready된 후 기존 노드를 순차적으로 종료합니다. ASG가 자동으로 처리합니다.
3.5 Upgrading Fargate Nodes
Fargate 노드는 Deployment를 재시작하는 것만으로 새 버전의 노드에 스케줄됩니다.
# 현재 Fargate 노드 버전 확인
kubectl get node $(kubectl get pods -n assets -o jsonpath='{.items[0].spec.nodeName}') -o wide
# Deployment 재시작
kubectl rollout restart deployment assets -n assets
# 새 파드가 Ready 될 때까지 대기
kubectl wait --for=condition=Ready pods --all -n assets --timeout=180s
# 1.31 버전 Fargate 노드 확인
kubectl get node $(kubectl get pods -n assets -o jsonpath='{.items[0].spec.nodeName}') -o wide

