포스팅은 CloudNet@팀 서종호(Gasida)님이 진행하시는 AWS EKS Workshop Study 내용을 참고하여 작성합니다.
이번 강의는 AWS 정영준님께서
EKS 클러스터 업그레이드의 모범 사례에 대해서
열강 해주셨는데요, 강의 내용을 기반으로 포스팅해보려 합니다.
01. EKS 클러스터 업그레이드 전략
업그레이드의 두 가지 접근 방식
EKS 클러스터 업그레이드는 크게 In-Place 방식과 Blue/Green 방식 두 가지로 나뉩니다.
1) In-Place 업그레이드
기존 클러스터를 그대로 유지하면서 컨트롤 플레인과 데이터 플레인(노드그룹)을 순차적으로
버전을 올리는 방식입니다. 이 워크샵에서 실습하는 방식이 바로 In-Place입니다.
📌동작 방식
컨트롤 플레인을 먼저 올리고, 이후 노드그룹을 롤링 방식으로 교체합니다.
Managed Node Group 기준으로는 EKS가 내부적으로 새 버전 노드를 프로비저닝 → 기존 노드 drain →
기존 노드 종료 순서를 자동으로 처리합니다. maxUnavailable 설정으로 한 번에 교체되는 노드 수를 조절
2) Blue/Green 업그레이드
새 버전의 클러스터를 별도로 프로비저닝(Green)하고, 워크로드를 기존 클러스터(Blue)에서
새 클러스터(Green)로 이전한 뒤 Blue를 제거하는 방식입니다.
📌동작 방식
새 버전의 EKS 클러스터를 별도로 생성합니다. 워크로드를 Green 클러스터에 배포하고 검증이 완료되면
Route 53이나 ALB의 가중치 기반 라우팅으로 트래픽을 점진적으로 Green으로 전환합니다.
Blue는 롤백을 위한 대기 상태로 두다가 안정화되면 삭제합니다.
두 방식을 비교하면 아래와 같습니다.
항목
In-Place
Blue/Green
다운타임
PDB 설정에 따라 최소화 가능
트래픽 전환 시점에만 발생
비용
추가 인프라 없음
전환 기간 중 두 배 비용
복잡도
상대적으로 단순
워크로드 이전 계획 필요
롤백
어려움 (다운그레이드 불가)
쉬움 (Blue로 트래픽 되돌리기)
적합한 상황
점진적 업그레이드, 비용 민감
대규모 버전 점프, 중단 허용 불가
EKS는 다운그레이드를 지원하지 않습니다.
In-Place 업그레이드 중 문제가 생겨도 이전 버전으로 롤백할 수 없기 때문에, 업그레이드 전 사전 검증이 매우 중요합니다. Blue/Green 방식은 이 롤백 문제를 해소할 수 있지만 비용과 운영 복잡도가 높아집니다.
In-place vs Blue/Green 장 단점 비교
1) In-Place 업그레이드
장점
운영 중인 클러스터와 동일한 VPC, 서브넷, 보안그룹, IAM, DNS, 인그레스 설정을 그대로 유지합니다.
인프라를 별도로 프로비저닝할 필요가 없어서 추가 비용이 발생하지 않습니다
Terraform 코드 기준으로도 cluster_version과 mng_cluster_version 두 변수만 변경하고 apply하면 되기 때문에 운영 부담이 낮습니다.
업그레이드 도중에도 워크로드는 계속 실행됩니다. PDB를 적절히 설정해두면 서비스 다운타임 없이 롤링 업그레이드가 가능하고, kube-ops-view 같은 도구로 파드가 이동하는 과정을 실시간으로 모니터링할 수 있습니다.
클러스터 이름, API 엔드포인트, OIDC issuer, 서비스 어카운트 토큰 등 기존 설정이 전혀 변경되지 않습니다. IRSA 설정도 건드릴 필요 없고, 외부 시스템에서 클러스터 엔드포인트를 참조하는 경우에도 변경 작업이 없습니다.
단점
EKS는 다운그레이드를 지원하지 않습니다. 업그레이드 도중 심각한 문제가 발생해도 이전 버전으로 롤백이 불가능합니다. 이 점이 In-Place 방식의 가장 큰 리스크입니다.
한 번에 한 마이너 버전씩만 올릴 수 있습니다. 1.28에서 1.31로 바로 올리는 것은 불가능하고, 1.28 → 1.29 → 1.30 → 1.31 순서로 세 번의 업그레이드를 거쳐야 합니다. 버전이 많이 밀려 있을수록 시간과 공수가 늘어납니다.
노드그룹 롤링 교체 중에는 일시적으로 클러스터 용량이 줄어듭니다. maxUnavailable: 35%라면 노드 교체 중 전체 용량의 35%가 동시에 사용 불가능한 상태가 됩니다. 이 시점에 트래픽이 급증하면 파드가 Pending에 걸릴 수 있어요.
Deprecated API를 사용하는 워크로드가 있으면 업그레이드 자체가 블록됩니다.
업그레이드 전에 Upgrade Insights로 사전 점검하고 API를 교체해두지 않으면, 업그레이드 후 특정 리소스가 동작하지 않는 상황이 생깁니다.
2) Blue/Green 업그레이드
장점
롤백이 명확합니다. Green에서 문제가 생기면 트래픽을 다시 Blue로 되돌리면 됩니다. 서비스는 계속 살아있고 클러스터만 바꾸는 것이기 때문에 롤백 결정과 실행이 빠릅니다.
업그레이드 검증을 실제 트래픽으로 할 수 있습니다. 카나리 방식으로 전체 트래픽의 10%만 Green으로 보내면서 오류율, 레이턴시, 리소스 사용량을 모니터링한 뒤 이상이 없으면 100%로 전환하는 방식이 가능합니다.
여러 마이너 버전을 한 번에 건너뛸 수 있습니다. Blue가 1.28이고 Green을 1.32로 바로 생성하는 것이 가능합니다. In-Place처럼 단계적으로 올리지 않아도 돼서 버전이 많이 밀린 상황에서 유리합니다.
새 클러스터를 처음부터 구성하기 때문에 레거시 설정이나 누적된 기술 부채를 정리할 기회가 됩니다. 네트워크 설계, 노드그룹 구성, 보안 설정 등을 처음부터 모범 사례 기준으로 재구성할 수 있습니다.
단점
전환 기간 동안 두 클러스터를 동시에 운영해야 합니다. Blue와 Green이 동시에 돌아가는 기간에는 EC2, EBS, 데이터 전송 등 모든 리소스가 두 배로 과금됩니다. 대규모 클러스터라면 전환 기간의 비용이 상당할 수 있어요.
클러스터 엔드포인트가 바뀝니다. 외부 시스템이나 CI/CD 파이프라인에서 클러스터 API 서버 주소를 직접 참조하고 있다면 전부 업데이트해야 합니다. OIDC issuer도 변경되기 때문에 IRSA를 사용하는 서비스 어카운트들의 신뢰 정책을 새 클러스터의 OIDC issuer로 업데이트해야 합니다.
Stateful 워크로드의 데이터 이전이 복잡합니다. 이 실습 환경 기준으로 order-mysql-pvc, catalog-mysql-pvc, checkout-redis-pvc 같은 EBS 볼륨 데이터를 Green 클러스터로 이전해야 하는데, EBS 볼륨은 클러스터 간에 직접 공유할 수 없습니다. 스냅샷을 떠서 새 볼륨을 만들거나, 애플리케이션 레벨에서 데이터를 덤프/복원하는 과정이 필요합니다.
워크로드 이전 자체도 공수가 큽니다. ArgoCD를 새 클러스터에 설치하고, CodeCommit 리포를 새 클러스터와 연결하고, 모든 Application이 정상적으로 Synced 상태가 되는 것을 검증하는 과정이 필요합니다. RabbitMQ처럼 메시지가 큐에 남아 있는 상태에서 이전하면 메시지 유실이 발생할 수 있어서 타이밍도 중요합니다.
In-Place 업그레이드 순서
In-Place 방식에서 업그레이드는 반드시 아래 순서를 지켜야 합니다.
1. 사전 점검
└─ Upgrade Insights 확인 (Deprecated API, 버전 skew)
└─ PDB, TopologySpreadConstraints 설정
2. EKS 컨트롤 플레인 업그레이드
└─ 한 번에 한 마이너 버전씩만 가능 (1.30 → 1.31 → 1.32 순서)
└─ Terraform: cluster_version = "1.31" → terraform apply
3. EKS Managed Addon 업그레이드
└─ coredns, kube-proxy, vpc-cni, ebs-csi-driver
└─ 컨트롤 플레인 업그레이드 직후 처리
4. 데이터 플레인(노드그룹) 업그레이드
└─ Managed Node Group: AWS가 롤링 교체 처리
└─ Self-Managed Node Group: AMI 교체 후 drain 직접 수행
└─ Karpenter 노드: NodePool 버전 업데이트 후 자동 교체
└─ Fargate: 파드 재시작으로 자동 반영
컨트롤 플레인이 노드그룹보다 항상 먼저 올라가야 합니다.
EKS 정책상 컨트롤 플레인은 노드보다 최대 2개 마이너 버전 앞설 수 있습니다.
예를 들어 컨트롤 플레인이 1.31이면 노드는 1.29, 1.30, 1.31 중 어느 버전이어도 됩니다.
하지만 그 반대(노드가 컨트롤 플레인보다 높은 버전)는 허용되지 않습니다.
Blue/Green 업그레이드 순서
1. 사전 준비
└─ Blue 클러스터 현재 상태 스냅샷
└─ 노드그룹 구성, Addon 버전, Helm 릴리즈 목록
└─ PV/PVC 목록 및 AZ 매핑 확인
└─ OIDC issuer ARN, IRSA Role ARN 목록 수집
└─ Stateful 워크로드 데이터 백업
└─ EBS 볼륨 스냅샷 (order-mysql, catalog-mysql, checkout-redis)
└─ RabbitMQ 메시지 큐 drain (이전 중 메시지 유실 방지)
2. Green 클러스터 프로비저닝
└─ 새 버전으로 EKS 클러스터 생성 (Terraform 신규 workspace 또는 별도 디렉토리)
└─ VPC는 Blue와 공유하거나 신규 생성 (피어링 필요 여부 검토)
└─ 동일한 노드그룹 구성, 보안그룹, IAM Role 재생성
└─ Addon 설치 (coredns, kube-proxy, vpc-cni, ebs-csi-driver)
└─ Helm 차트 재설치 (ArgoCD, ALB Controller, Karpenter 등)
3. IRSA 재설정
└─ Green 클러스터의 신규 OIDC issuer 확인
aws eks describe-cluster --name $GREEN_CLUSTER \
--query cluster.identity.oidc.issuer --output text
└─ 기존 IRSA IAM Role 신뢰 정책에 Green OIDC issuer 추가
(또는 Green용 신규 IAM Role 생성)
└─ Karpenter, ALB Controller, EBS CSI, EFS CSI SA Annotation 업데이트
4. 워크로드 이전
└─ ArgoCD를 Green 클러스터에 설치 후 CodeCommit 리포 연결
└─ ArgoCD Application Sync → 전체 워크로드 Green에 배포
└─ Stateful 워크로드 데이터 복원
└─ EBS 스냅샷으로 새 볼륨 생성 (같은 AZ에 생성 필수)
└─ PV/PVC를 새 볼륨에 바인딩
└─ Green 클러스터에서 전체 서비스 동작 검증
└─ kubectl get pods -A (모두 Running 확인)
└─ ArgoCD 전체 Application Synced/Healthy 확인
└─ 실제 API 호출 테스트
5. 트래픽 전환
└─ 카나리 방식 (권장)
└─ Route 53 가중치 라우팅: Blue 90% / Green 10%
└─ 오류율, 레이턴시, 로그 모니터링
└─ 이상 없으면 Blue 50% / Green 50% → Blue 0% / Green 100%
└─ 즉시 전환 방식
└─ DNS를 Green ALB/NLB 엔드포인트로 일괄 변경
└─ TTL을 미리 낮춰두어야 전환 속도 확보 가능
6. 안정화 및 Blue 제거
└─ Green에서 일정 기간(최소 1~2주) 모니터링
└─ 이상 없음 확인 후 Blue 클러스터 삭제
└─ 전환 기간 중 발생한 이중 과금 종료
In-Place와 비교했을 때 Blue/Green에서 추가로 신경 써야 하는 포인트:
1) OIDC issuer가 바뀐다
Blue와 Green은 서로 다른 클러스터이기 때문에 OIDC issuer ARN이 완전히 달라집니다. Karpenter, ALB Controller, EBS CSI Driver처럼 IRSA를 사용하는 컴포넌트들의 IAM Role 신뢰 정책을 전부 Green의 OIDC issuer로 업데이트하지 않으면 파드가 AWS API를 호출할 수 없어서 동작 X
2) EBS 볼륨은 AZ를 넘어갈 수 없습니다
스냅샷으로 새 볼륨을 만들 때 반드시 기존 볼륨과 동일한 AZ에 생성해야 하고, Green 클러스터의 해당 노드도 같은 AZ에 떠야 마운트가 됩니다. Blue/Green 전환 시 노드그룹 서브넷 설계를 Blue와 동일하게 가져가야함.
3)RabbitMQ 같은 메시지 큐는 이전 타이밍이 중요합니다.
Blue에서 메시지가 계속 들어오는 상태에서 Green으로 이전하면 Blue의 큐에 남은 메시지가 유실됩니다. 이전 직전에 Checkout 서비스의 메시지 발행을 일시 중단하거나, Blue와 Green이 동시에 동일한 큐를 바라보도록 임시 브릿지를 구성하는 방법을 고려해야 합니다.
4) DNS TTL을 미리 낮춰두지 않으면 트래픽 전환이 느립니다.
Route 53 TTL이 300초(5분)라면 DNS 변경 후 최대 5분간 일부 클라이언트는 여전히 Blue로 요청을 보냅니다. 전환 며칠 전부터 TTL을 60초 이하로 낮춰두고, 전환 완료 후 다시 올리는 패턴을 사용합니다.
02. EKS Upgrade Insights : 업그레이드 전 사전 점검
Upgrade Insight란?
EKS는 클러스터를 특정 버전으로 올리기 전에 문제가 될 수 있는 항목들을 자동으로 검사해주는
Upgrade Insights 기능을 제공합니다. 콘솔의 Insights 탭이나 CLI로 확인할 수 있어요.
검사 항목은 크게 두 가지입니다.
첫째는 Deprecated API 사용 여부입니다.
업그레이드 대상 버전에서 제거되는 API를 현재 클러스터에서 사용하고 있으면 경고를 띄워줍니다.
앞서 설명한 autoscaling/v2beta2가 대표적인 예입니다.
둘째는 컴포넌트 버전 skew 검사입니다.
kube-proxy, coredns 같은 컴포넌트가 컨트롤 플레인 버전과 너무 차이나면 업그레이드 후 문제가
생길 수 있어서 이 부분도 체크해줍니다.
02. 1.31 업그레이드 기준 Insights 확인
# 1.31로 업그레이드할 때 발생하는 이슈 목록 확인
aws eks list-insights \
--filter kubernetesVersions=1.31 \
--cluster-name $CLUSTER_NAME | jq .
실제 출력:
{
"insights": [
{
"name": "kube-proxy version skew",
"category": "UPGRADE_READINESS",
"kubernetesVersion": "1.31",
"insightStatus": {
"status": "PASSING",
"reason": "kube-proxy versions match the cluster control plane version."
}
}
]
}
PASSING 상태라는 건 현재 kube-proxy 버전이 1.31 업그레이드 기준을 만족한다는 의미입니다.
만약 ERROR나 WARNING이 뜬다면 업그레이드 전에 반드시 해결해야 합니다.
EKS 콘솔에서도 동일한 정보를 확인할 수 있습니다.
클러스터 → Insights 탭에서 각 항목별 상세 설명과 권장 조치를 확인할 수 있어요.
커스텀 AMI나 self-managed 노드그룹에서 이 플래그를 사용하고 있다면 bootstrap 스크립트에서 제거해야 합니다. 이 실습 환경의 default-selfmng는 cloudinit_pre_nodeadm으로 kubelet 설정을 주입하는데, 해당 플래그가 없으므로 문제없습니다.
2) VolumeAttributesClass beta 활성화
EBS CSI Driver를 통해 PV의 속성(볼륨 타입, 처리량 등)을 동적으로 변경할 수 있는 기능이 beta로 활성화됩니다.
이 기능을 사용하려면 EBS CSI Driver v1.35.0 이상이 필요합니다.
현재 실습 환경의 aws-ebs-csi-driver는 v1.58.0이므로 조건을 만족합니다.
다른 엔드포인트에 인증 없이 접근하면 401 Unauthorized가 반환됩니다. 또한 1.32가 AL2 AMI를 지원하는 마지막 버전입니다. 1.33부터는 AL2023 또는 Bottlerocket만 지원하므로 AL2 기반 노드그룹이 있다면 미리 마이그레이션 계획을 세워야 합니다.
03. EKS 업그레이드 HA 전략
PDB와 TopologySpreadConstraints 설정이 왜 필요한가?
앞서 확인한 것처럼 현재 실습 환경에서 샘플 앱 서비스에는 PDB가 전혀 없습니다.
노드 drain 시 파드가 즉시 강제 eviction되어 서비스 다운타임이 발생할 수 있어요.
EKS 관리형 노드그룹 업그레이드는 내부적으로 노드를 하나씩 drain하면서 새 노드로 교체합니다.
이때 PDB가 있으면 drain이 PDB를 존중해서, 최소 가용 파드 수가 유지될 때까지 eviction을 블록합니다.
즉, PDB는 업그레이드 중 서비스 가용성을 보장하는 안전장치입니다.
Orders 서비스에 PDB 추가
현재 orders 디렉토리에 pdb.yaml이 없는 걸 먼저 확인합니다.
tree eks-gitops-repo/apps/orders/
kubectl get pdb -n orders
# 아무것도 없음
GitOps 방식으로 추가합니다. 직접 kubectl apply를 하면 ArgoCD의 selfHeal에 의해 즉시 삭제되므로,
PDB 없이 업그레이드를 진행하면 노드 drain 시 Orders 파드가 즉시 종료됩니다.
blue-mng는 단일 AZ 단일 노드이고, Orders 파드는 dedicated=OrdersApp Taint 때문에 다른 노드로
이동이 불가능합니다. 즉 새 blue-mng 노드가 완전히 Ready 상태가 될 때까지 Orders 서비스가 완전히 다운됌.
PDB를 추가하면 drain이 블록되어 배포 자동화 도구(EKS managed upgrade)가 새 노드를 먼저
프로비저닝하고 Orders 파드가 새 노드에서 Running이 된 이후에야 기존 노드를 종료하는 순서를
강제할 수 있습니다. 실제 운영 환경에서 업그레이드 전 PDB 설정이 권장되는 이유가 여기에 있습니다.
단, minAvailable을 현재 replicas보다 크게 설정하면 drain이 영원히 블록되므로 주의해야 합니다.
replicas가 1이라면 minAvailable: 1은 결국 "파드가 새 노드에 뜨기 전까지 drain 금지"를 의미하고, 이건 의도한 동작입니다. 만약 replicas를 2 이상으로 늘린다면 ALLOWED DISRUPTIONS: 1이 되어 drain이 즉시 진행됩니다.