02 / 06
도입 배경
OOM 이슈 사례, Fargate 메트릭 한계, CloudWatch vs Prometheus 비교, 실제 장애 사례
Background
도입 배경
ECS Fargate 환경에서 OOM 문제가 발생한 이력이 있었다. Fargate는 리소스가 고정되어 있고 메트릭 확인이 불편한 환경으로, 정량적 JVM 상태를 실시간으로 추적하지 않으면 문제를 조기에 발견하거나 예방할 수 없다. 현재 AWS에서 ECS에 대해서는 JVM 레벨의 상세 메트릭을 제공하지 않기 때문에, Prometheus + Grafana 기반 모니터링 체계를 도입하게 되었다.
다운타임/오류 감소
장애 전조를 조기에 탐지하여 서비스 장애를 방지한다. 특히 트래픽 급증 시 Heap 부족 등의 문제를 사전에 감지할 수 있다.
다른 문제도 조기 발견
GC pause, Thread leak 같은 JVM 내부 문제도 메트릭 기반으로 조기에 발견할 수 있다.
시각적 대시보드 리포트
시스템 안정성 지표를 시각적 대시보드로 구성하여 정기 보고가 가능하다.
OOM Issue
OOM 이슈 사례
Fargate 환경에서 OOM 발생
ECS Fargate Task에서 OutOfMemoryError가 발생하여 컨테이너가 강제 종료된 이력이 있다. Fargate는 리소스(CPU, Memory)가 Task Definition에 고정되어 있어, 런타임에 동적으로 리소스를 확장할 수 없다.
메트릭 확인의 어려움
Fargate는 EC2와 달리 호스트에 직접 접근할 수 없어 JVM 내부 상태를 확인하기 어렵다. CloudWatch에서 제공하는 CPU/Memory 사용률만으로는 JVM Heap, GC, Thread 상태를 파악할 수 없다.
AWS 미제공 영역
현재 AWS에서 ECS에 대해 JVM 레벨의 상세 메트릭(Heap Memory, GC Count/Time, Thread Count 등)을 기본으로 제공하지 않는다. 별도의 모니터링 체계 구축이 필요하다.
Comparison
CloudWatch vs Prometheus 비교
| 구분 | CloudWatch | Prometheus |
|---|---|---|
| CPU | 40% → 이상 없어 보임 | JVM CPU Usage 상세 추적 가능 |
| 메모리 | 60% → 이상 없어 보임 | Heap Used/Max, Metaspace 분리 확인 |
| GC | 확인 불가 | Full GC 20초 이상 반복 탐지 |
| Thread | 확인 불가 | Thread 수 지속 증가 → Thread Leak 발견 |
| 진단 결과 | 정상으로 판단 | Thread Leak + Heap Pressure 발견 |
Thread Leak
객체가 여전히 참조하고 있어 GC가 회수하지 못하는 객체 누수 현상이다. Thread가 종료되지 않고 계속 생성되면서 메모리를 점유하고, 결국 시스템 리소스가 고갈되어 애플리케이션이 멈출 수 있다.
Heap Pressure
GC가 빈번하게 발생하고, Full GC가 반복되면서 애플리케이션이 멈추는 현상이다. Heap 메모리가 부족해지면 GC가 자주 실행되고, Full GC 시에는 애플리케이션의 모든 Thread가 일시 정지(Stop-the-World)되어 응답 지연이나 타임아웃이 발생한다.
Real Case
실제 장애 사례
장애 발생
A 서비스가 갑자기 느려졌다. 사용자 요청에 대한 응답 시간이 급격히 증가했다.
CloudWatch 확인
CloudWatch에서 CPU 40%, 메모리 60%로 표시 → 이상 없어 보였다. 인프라 레벨에서는 정상으로 판단되었다.
Prometheus 분석
Prometheus 메트릭을 확인하니 Full GC가 20초 이상 반복되고 있었고, Thread 수가 지속적으로 증가하고 있었다.
원인 파악
문제의 원인은 Thread Leak + Heap Pressure였다. Thread가 정상적으로 종료되지 않아 메모리를 계속 점유하고, Heap이 부족해지면서 Full GC가 반복되었다.
조기 대응 가능
Prometheus + Grafana 모니터링이 있었기에 CloudWatch만으로는 발견할 수 없었던 JVM 레벨 문제를 조기에 탐지하고 대응할 수 있었다.
핵심 교훈
인프라 레벨 메트릭(CPU, Memory)만으로는 JVM 기반 애플리케이션의 실제 상태를 파악할 수 없다. Heap Memory, GC, Thread 등 JVM 내부 메트릭을 실시간으로 수집하고 시각화해야 장애를 조기에 탐지하고 예방할 수 있다.