AWS 기술 블로그
백패커의 Amazon EKS 운영 최적화 여정 2부: 운영 심화 및 장애 대응 사례
백패커는 국내 최대 핸드메이드 마켓 플레이스인 아이디어스와 크라우드 펀딩 플랫폼 텀블벅를 운영하고 있습니다. 2022년 백패커는 지속적으로 성장 중인 서비스를 안정적이고 유연하게 운영하기 위하여 안정성, 확장성, 보안성, 비용절감, MSA 환경에 보다 친화적인 컨테이너 환경을 제공하는 Amazon EKS를 도입하여 현재까지 사용자에게 안정적으로 서비스를 제공하고 있습니다. 지난 블로그 <백패커의 Amazon EKS 운영 최적화 여정 1부: 운영 핵심 요소 최적화>에 이어서 백패커가 Amazon EKS를 운영하면서 직면하고 해결하는 과정에서 얻은 경험을 공유합니다.
이번 게시글에서 다루는 내용은 다음과 같습니다.
- Spot 인스턴스 활용 과정에서 발생하였던 이슈 해결
- 트래픽 급증에 의한 서비스 장애 해결
Spot 인스턴스 활용 과정에서 발생하였던 이슈 해결
백패커는 Spot 인스턴스를 효율적으로 활용하여 EKS 클러스터에서 약 60-70%의 서비스를 Spot 인스턴스를 통해 구동하고 있습니다. Spot 인스턴스는 AWS의 남은 용량을 활용해 온디맨드 가격보다 최대 90% 할인된 가격으로 사용할 수 있는 인스턴스로, 비용 효율성을 크게 높일 수 있지만 AWS가 필요시 인스턴스를 회수할 수 있어 가용성 관리가 중요합니다.
현재 백패커의 EKS 환경은 매니지드 노드 그룹을 사용하여 ASG(Auto Scaling Group)와 연동해 Node를 운영하고 있습니다. 이 구성에서 특히 중요한 것이 ‘재조정 활동(Rebalancing activities)‘입니다. 이는 AWS가 AZ간의 불균형을 맞추기 위한 재조정과, 중단 위험이 있는 Spot 인스턴스를 미리 재조정하는 메커니즘으로, 이를 모니터링하고 적절히 대응함으로써 갑작스러운 서비스 중단을 방지할 수 있습니다.
아래에서는 Spot 인스턴스를 활용하면서 발생했던 이슈와 이를 해결한 방법을 설명합니다.
1. ASG(Auto Scaling Group)의 AZ Rebalance 이벤트로 인한 인스턴스 종료
문제 발생 원인
첫 번째 이슈는 많은 리소스를 사용하는 API 서비스를 배포하는 상황에서 발생했습니다. 백패커에서는 블루/그린 배포 전략으로 API 서비스를 배포하고 있습니다. 배포 과정을 살펴보면, 우선 블루/그린 방식으로 새로운 버전을 배포합니다.
배포가 성공적으로 진행되면, 기존 블루 버전은 종료되고 새로운 그린 버전이 활성화됩니다.
이 과정에서 새롭게 실행된 노드들로 인하여 Auto Scaling Group의 가용 영역 간에 불균형이 발생하게 되었습니다. Auto Scaling Group에서는 이 불균형을 해결하기 위해 AZ Rebalance를 수행하여 운영 중인 5개 노드 중 4개가 종료되었습니다.
이로 인해 Pod들이 evict과 SIGTERM이 발생하면서 종료되었고, 그 순간 트래픽 부하가 남은 Pod에 집중되면서 응답 지연 및 타임아웃 에러로 인한 부분 장애가 발생했습니다.
문제 해결 방법
이 문제는 여러 회피 방법이 있지만, 백패커는 간단한 해결책을 선택했습니다.
ASG 그룹의 기본 설정인 AZ Rebalance 기능을 비활성화하여 문제를 해결했습니다. 이 기능은 용량 재조정에 유용하지만, 빈번한 리밸런싱 작업으로 인해 Node 가용성에 문제가 생길 수 있습니다. 따라서 백패커는 해당 설정을 비활성화하여 안정성을 확보했습니다.
2. Spot 인스턴스 리밸런스 이벤트로 인한 종료로 인한 서비스 Pod 중단
문제 발생 원인
Spot 리밸런스 이벤트는 AWS가 Spot 인스턴스의 중단 위험이 높아질 때 발생하는 알림입니다. 이 신호는 스팟 인스턴스 중단 2분 전에 알람이 발생하여, 워크로드를 중단 위험이 낮은 신규 또는 기존 스팟 인스턴스로 사전에 이동할 기회를 제공합니다. 두 번째 장애 케이스는 바로 이러한 스팟 인스턴스들이 동시에 종료되면서 특정 서비스의 모든 Pod가 중단되어 발생한 부분 장애 사례입니다. 다음과 같은 상황에서 발생했습니다:
- Spot 인스턴스 2개에 서비스 Pod가 각각 1개씩 배치되어 총 2개 Running 중
- 두 Spot 인스턴스에서 동시에 종료 이벤트 발생
- PDB(PodDisruptionBudget) 설정에 의해 1개 Pod만 Evict됨
- 새 Spot 인스턴스 할당이 지연되면서 서비스가 Pod 1개로 유지됨
- 예정대로 Spot 인스턴스 2개가 종료되고, 남아있던 Pod는 강제로 SIGKILL됨
- 모든 Pod가 중단되면서 서비스에서 503 에러와 부분 장애 발생
이 이슈의 원인은 다음과 같이 정리할 수 있습니다.
- 낮은 확률로 해당 서비스가 존재했던 Node만 Spot 종료 이벤트가 발생
- 서비스의 Replica 개수 부족
- 가장 큰 원인은 Spot 인스턴스 할당 지연으로 인한 문제
스팟 인스턴스를 사용할 경우 이러한 문제가 발생할 가능성은 항상 존재하므로, 효과적인 회피 전략을 마련할 필요가 있었습니다.
문제 해결 방법
백패커는 모든 서비스 Pod의 최소 1개 이상을 On-Demand Node에 배치하여 가용성을 높이는 방안을 선택했습니다. AWS 공식 블로그에서 제시된 Custom Scheduler를 사용하여 특정 annotation 설정에서 label의 key-value를 확인하고, 이를 기반으로 Pod의 nodeSelector 값을 패치하여 배치되는 Node를 선택하는 방법을 활용하였습니다. 아래는 저희 서비스 중 하나의 Rollout 예시 코드입니다:
위 설정에서 capacityType이 ON_DEMAND
인 경우 weight는 0, SPOT
인 경우 weight는 1입니다. 이를 통해 아래 계산식이 적용됩니다:
예를 들어 baseNum
값이 1이라면:
- ON_DEMAND: 최소 Pod 수는 baseNum 값(1)
- SPOT: 전체 replica 개수에서 ON_DEMAND에 배치된 Pod 수를 뺀 나머지
단, Custom Scheduler 샘플 코드를 실제 환경에 맞게 커스터마이징해야 합니다. 아래는 해당 코드를 활용하여 구성할 시 참고했던 내용입니다.
- Watching 가능한 Kind 객체를 Deployment, StatefulSet, DaemonSet 외에도 Rollout 객체를 지원하도록 수정.
- Label 기준으로 Count하는 대신 ReplicaSet 단위로 Count하도록 변경.
- EKS API와 통신하기 위한 Private 인증서 세팅 시 적절한 만료 기간 설정 필요(짧게 설정하면 인증서 만료 시 신규 Pod 생성이 Pending 상태로 멈출 수 있음).
아래는 일부 서비스에 적용된 결과입니다:
해당 서비스는 baseNum
값이 1로 설정되어 있어 On-Demand Node에 최소 Pod 1개가 배치되고, 나머지 Pod는 모두 Spot Node에 배치되었습니다. 이를 통해 Spot 인스턴스 종료 이벤트로 인한 서비스 안정성을 높이고, 비용 효율성을 유지하면서도 가용성을 확보할 수 있었습니다. 백패커는 위와 같은 Custom Scheduler를 활용해 전체 서비스에서 On-Demand와 Spot 인스턴스를 적절히 조합함으로써 안정성과 비용 최적화를 동시에 달성할 수 있었습니다.
트래픽 급증에 인한 서비스 장애 해결
2024년 1월 설날 이벤트 당시, 예상치 못한 트래픽 급증으로 인해 서비스 장애가 발생했습니다. 개발자 한 명이 Slack에 장애 의심 메시지를 제보했지만, 여러 관련자가 확인하는 동안 웹 및 앱 서비스 전면 장애로 이어졌고 결국 이벤트 중단을 결정해야 했습니다.
문제 발생 원인
서비스 트래픽 급증이 주요 원인이었지만, 아래의 부수적인 문제들이 겹치면서 장애로 이어졌습니다:
- 아키텍처 및 구조적 이슈(아래 그림 참고): 모든 외부/내부 트래픽이 istio Node의 ingressGateway를 통해 전달되는 구조로 인해 부하가 집중됨. 점점 서비스가 고도화 되고 도메인이 분리되면서 istio Node의 역할은 더욱 높아짐
- nf_conntrack 테이블 이슈: 트래픽 급증으로 테이블이 초과되어 패킷 드랍 발생
- 시스템 자원 사용률 이슈: istio Node의 네트워크 성능 한계에 도달
아래는 저희 서비스를 AWS 리소스 기준, K8S 리소스 기준으로 표현한 간단한 아키텍처입니다.
결국 이 문제의 근본적인 Root Cause는 istio Node의 네트워크 성능 이슈였습니다. 정확히 말하면 nf_conntrack 테이블 이슈였습니다.
nf_conntrack이란?
nf_conntrack은 네트워크 커넥션을 기록하고 추적하는 Linux 커널 모듈입니다. 컨테이너 환경에서는 NAT 및 포트 포워딩 기능 때문에 활성화되며, 연결 기록 테이블 크기(default: 65536)를 초과하면 이후 수신되는 패킷이 드랍됩니다. 설날 이벤트 당시 트래픽이 평소 대비 3배 이상 급증하며 istio Node의 nf_conntrack 테이블이 100% 초과되어 패킷 드랍과 ingressGateway 응답 실패로 전면 장애가 발생했습니다.
문제 해결 방법
장애 이후, 백패커는 아래 4가지 액션 아이템을 통해 후속 조치를 진행했습니다:
1. nf_conntrack max 값 상향 조정
전체 Node의 nf_conntrack_max 값을 상향 조정했습니다. 권장 계산식은 다음과 같습니다:
- (인스턴스 전체 메모리 바이트)/16384/2
- 특히 istio Node의 경우, (인스턴스 전체 메모리 바이트)/16384/2*3(3배)
- 만약 16GB 메모리를 사용하는 인스턴스라면 net.netfilter.nf_conntrack_max 값은 약 50만으로 설정됩니다.
이를 자동화하기 위해 앞서 소개한 nodeOptimizer 데몬셋에 해당 설정을 추가하여 모든 Node에 적용했습니다. 아래는 예시 코드입니다:
2. istio Mesh 네트워크 설정
ingressGateway를 통하지 않고 사이드카끼리 직접 통신할 수 있도록 Mesh 네트워크를 설정했습니다. 이는 ingressGateway의 부하를 줄이고 네트워크 성능을 개선하는 데 효과적입니다.
VirtualService 예시 코드:
단, 도메인 호출 시 HTTPS를 사용하는 경우 TLS offloading이 필요하므로 ingressGateway나 NLB를 통과해야 합니다. 하지만 HTTP 호출을 통해 Mesh 통신을 활성화할 수 있습니다.
3. istio Node 인스턴스 타입 업그레이드
istio Node를 고성능 인스턴스로 업그레이드하여 네트워크 대역폭을 개선했습니다. 기존 c6.xlarge 인스턴스(12.5Gbps)를 최대 25Gbps 대역폭을 제공하는 n타입 인스턴스로 변경함으로써 안정성을 확보했습니다.
4. 모니터링 강화
모니터링 시스템을 더욱 강화하여 장애 예방 및 대응 능력을 높였습니다:
- ENA 네트워크 관련 모니터링: 네트워크 대역폭, 패킷 드랍 등 주요 지표 확인
- istio 상세 지표 모니터링: ingressGateway 및 사이드카 프로세스 상태 점검
- 퍼포먼스 및 자원 사용률 모니터링: CPU, 메모리 사용률 및 Saturation 상태 분석
마무리
2부에 걸쳐 백패커의 Amazon EKS 운영 최적화 여정을 소개해드렸습니다. 백패커는 다양한 운영 환경에서 발생한 장애 사례들을 통해 EKS 및 AWS 기반 클라우드 환경에서의 안정성과 가용성을 확보하기 위한 중요한 교훈을 얻었습니다. 특히, Spot 인스턴스 활용, istio Service Mesh 구성, 트래픽 급증 대응 등에서 발생한 문제들을 체계적으로 분석하고 해결함으로써 서비스 운영의 신뢰성을 높일 수 있었습니다. 앞으로도 백패커는 지속적인 개선과 혁신을 통해 더 나은 클라우드 운영 환경을 구축하며 사용자들에게 안정적이고 신뢰할 수 있는 서비스를 제공할 수 있길 기대합니다.