이 게시물은 가시다님의 AEW 스터디 기반으로 작성한 글 입니다. 워크샵을 따라하고싶었는데.. 아무리 인증시도를 해도 들어가지지 않아서 제가 업그레이드 작업했던 이력을 공유 드립니다!!(이번주 여행이 있어서 미리 작성해야하는 핑계도 있습니다..ㅠ_ㅠ..)
작년 업그레이드 시점 당시 운영 중인 EKS 클러스터 버전은 v1.29였습니다. 저희는 매년 1~2번 업그레이드를 진행합니다.(개발, 스테이지, 운영)
업그레이드 배경은 다들 비슷하시겠지만 아래와 같습니다!
첫째, AWS의 EKS 표준 지원 종료 일정이 임박했습니다. v1.29는 표준 지원 종료가 다가오고 있었고, 연장 지원(Extended Support)으로 넘어가면 시간당 추가 비용이 발생합니다. 비용 측면에서도, 정책적으로도 표준 지원 구간 내에서 운영하는 것이 바람직했습니다.
둘째, 보안 패치 및 CVE 대응 관점에서 최신 버전 유지가 필수였습니다. Kubernetes는 분기마다 새로운 마이너 버전이 릴리즈되며, 구버전은 점차 보안 패치 우선순위에서 밀립니다.
셋째, 신규 기능에 대한 니즈가 누적되어 있었습니다. 특히 Pod Identity, 사이드카 컨테이너 정식 지원(SidecarContainers), In-place Pod 리소스 조정 등 v1.30 이후 도입된 기능들이 운영 효율성을 개선할 수 있다고 판단했습니다.
업그레이드는 v1.29 → v1.33까지 진행하였고, In-place 순차 업그레이드 방식 대신 신규 클러스터를 구축하고 트래픽을 전환하는 Blue/Green 방식을 선택했습니다. 롤백 가능성을 확보하기 위함이었습니다.
v1.30부터 v1.33까지 각 버전의 CHANGELOG와 Deprecation 항목을 모두 검토했습니다. 운영 영향이 있을 만한 항목을 우선순위로 정리했고, 특히 사용 중인 API/리소스에 영향이 있는 변경점을 중점적으로 확인했습니다.
가장 위험도가 높은 작업이었습니다. 클러스터 내 사용 중인 API를 정적·동적으로 전수 조사했습니다.
# pluto를 활용한 정적 분석
pluto detect-helm -o wide --target-versions k8s=v1.33.0
# kubent로 클러스터 내 실제 사용 API 동적 분석
kubent --target-version 1.33
# Helm Chart 매니페스트에서 사용 중인 apiVersion 추출
helm list -A -o json | jq -r '.[].name' | while read r; do
helm get manifest "$r" | grep -E "^apiVersion:" | sort -u
done
검출된 항목 중 영향이 있었던 것은 autoscaling/v2beta2 HPA, policy/v1beta1 PDB 등이었습니다. 모두 신버전 API로 마이그레이션 PR을 사전에 정리했습니다.
Ingress 트래픽은 NGINX Ingress Controller를 통해 처리하고 있었기 때문에, NGINX Ingress Controller 버전과 Kubernetes v1.33 호환 여부를 먼저 확인했습니다. 차트의 릴리즈 노트와 호환 매트릭스를 기준으로 신버전 차트를 결정했고, values 스키마 변경 사항을 함께 점검했습니다.
EKS Add-on(VPC CNI, CoreDNS, kube-proxy, EBS CSI Driver, Pod Identity Agent 등)은 AWS 공식 호환성 매트릭스를 기준으로 v1.33에 권장되는 버전을 정리했습니다.
업그레이드 작업 전 백업 절차를 Terraform 모듈 차원에서 정식화했습니다. 백업 대상은 클러스터 리소스 매니페스트, PV 스냅샷, 애플리케이션 레벨 데이터로 구분했습니다.
주의사항: 백업 도구만으로는 PV 데이터의 정합성을 100% 보장하지 않으므로, EBS 스냅샷·애플리케이션 레벨 백업을 병행하는 것을 원칙으로 삼았습니다.
왜 필요한가: aws-auth ConfigMap은 단일 리소스에 모든 권한 매핑이 모이는 구조라 변경 충돌, 휴먼 에러로 인한 클러스터 잠금(lockout) 위험이 컸습니다. EKS Access Entries는 IAM 친화적인 API 기반 관리가 가능하고, AccessPolicy로 표준 권한 셋을 부여할 수 있어 운영 부담이 줄어듭니다.
주의사항: 기존 클러스터에서 aws-auth로 부여된 권한을 반드시 사전 추출하여 매핑 표를 만든 뒤, 신규 클러스터에서 Access Entries로 1:1 재구성했습니다. 신규 클러스터의 인증 모드는 API_AND_CONFIG_MAP이 아닌 API 로 설정했습니다.
왜 필요한가: IRSA는 OIDC Provider 기반이라 클러스터마다 trust relationship을 매번 갱신해야 했고, IAM Role의 신뢰 정책이 복잡했습니다. Pod Identity는 EKS Add-on 형태의 에이전트가 자격증명을 발급하므로 IAM Role을 클러스터 간 재사용하기 쉽고, trust policy도 단순합니다.
주의사항: Pod Identity는 컨트롤러/SDK 버전에 따라 미지원인 경우가 있으므로, 전환 대상 컴포넌트별로 SDK 버전을 사전 검증한 뒤 전환했습니다.
In-place 업그레이드라면 Control Plane을 한 단계씩 올리고 그에 맞춰 Node Group과 Add-on을 따라 올리는 절차가 의미가 있지만, 이번에는 v1.33 신규 클러스터를 처음부터 새로 만드는 방식이었기 때문에 절차 자체가 달랐습니다. 아래는 실제로 Green 클러스터를 구축한 순서입니다.
신규 클러스터(Green)를 v1.33으로 직접 생성했습니다.
module "eks_green" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
cluster_name = "service-prd-green"
cluster_version = "1.33"
authentication_mode = "API"
# 이하 VPC, Subnet, Security Group 등 생략
}
Control Plane 생성 후 kubectl 접근 확인, Access Entries 동작 확인까지 완료한 뒤 다음 단계로 넘어갔습니다.
Node는 EKS Managed Node Group(MNG) 으로 구성했습니다.
설치 대상 Add-on은 VPC CNI, CoreDNS, kube-proxy, EBS CSI Driver, Pod Identity Agent였고, 각 버전은 v1.33 호환 매트릭스에 맞춰 결정했습니다.
Ingress 계층은 가장 신중하게 진행했습니다. 차트 버전이 올라가면서 values 스키마와 일부 기본값이 변경되었기 때문입니다
진행 순서는 다음과 같았습니다.
신버전 차트 values 정리
LoadBalancer로 두되, AWS Load Balancer Controller가 Internal NLB를 프로비저닝하도록 어노테이션 구성.helm 으로 배포
Ingress 리소스 이전: 기존 클러스터의 Ingress 매니페스트를 export 후, 신규 클러스터에 반영. ingressClassName이 신규 컨트롤러와 일치하는지 반드시 확인.
장애 가능 지점 및 대응:
공통 계정에서 외부/내부 ALB 각각에 대해 Blue용/Green용 Target Group을 별도로 생성했습니다.
핵심 포인트:
ip 로 설정해 NLB의 Private IP를 직접 등록 가능하게 했습니다.롤백 기준(5xx 비율 임계 초과 / latency 급증) 을 사전에 정해두고, 기준을 넘으면 즉시 가중치를 이전 단계로 되돌리는 시나리오를 준비했습니다.
신규 클러스터의 Ingress Host를 임시 검증 도메인으로 먼저 노출해 검증을 마친 뒤, 운영 도메인을 등록했습니다.
ArgoCD ApplicationSet의 cluster generator에 신규 클러스터를 등록하고, 전환 기간에는 Blue/Green 양쪽 모두에 배포되도록 운영했습니다. 이 구조 덕분에 트래픽 가중치를 옮기는 동안에도 양쪽 클러스터에 동일한 애플리케이션 버전이 항상 배포되었습니다. 트래픽 100% 전환 완료 후 Blue 클러스터를 ArgoCD 대상에서 제거했습니다.
모니터링 툴 에이전트를 업그레이드가 완료되면 신규 클러스터에도 동일 설정으로 배포했습니다. 전환 기간 동안 모니터링은 포기..했습니다(사전에 업그레이드 작업 공지 완료)
# 노드 상태
kubectl get nodes -o wide
# 시스템 Pod
kubectl get pods -n kube-system
kubectl get pods -n ingress-nginx
# Ingress 리소스
kubectl get ingress -A
# Add-on 상태
aws eks list-addons --cluster-name service-prd-green
aws eks describe-addon --cluster-name service-prd-green --addon-name vpc-cni
| 카테고리 | 항목 |
|---|---|
| ALB | 5xx, TargetResponseTime p99, RequestCount |
| 노드 | CPU/Memory 사용률, NotReady 노드 수 |
| Pod | Restart 횟수, Pending 상태 |
| 애플리케이션 | 모니터링툴 트랜잭션 응답시간, 에러율 |
사실 Blue/Green 이라고 적긴 했지만.. 엄밀히 Blue/Green 전환은 아니긴 합니다.
일단 저희는 route53이 아닌 외부 도메인 시스템 사용을 하고있기 때문에 업체측에 도메인에 대한 레코드 변경 요청을 해야합니다
또한 3rd party waf 업체의 보호대상 도메인에 대한 웹서버 주소 변경도 필요하기 때문에
서비스 중단이 필수입니다. 지금은 롤백이 가능하다는 점에 의의를 두고 작업을 진행중 입니다
그래서 업무 외 시간에 작업시간을 별도로 잡아서 진행을 하고있으며
좋은 조언..?하실 부분이 있으시다면 공유해주시면 감사드리겠습니다