이 글은 Velog에서 이전한 글입니다. Velog 원문 보기
1. 문제 상황 (Issue Description)
개발 서버 환경에서 실행 중인 EC2 인스턴스가 약 48시간(2일) 간격으로 주기적으로 비정상 종료되고, Auto Scaling Group(ASG)에 의해 재생성되는 현상이 발생했습니다.
1-1. 발생 패턴 및 로그 (Logs & Patterns)
ASG 활동 이력(Activity History)을 분석한 결과, 인스턴스 실행 후 약 2일이 경과하면 종료되는 패턴이 일정하게 반복됨을 확인했습니다.
| 날짜 (UTC) | 작업 유형 | 인스턴스 ID | 비고 |
|---|---|---|---|
| 2026-02-05 10:21 | Launch | i-0f75... | 생성 |
| 2026-02-07 11:55 | Terminate | i-0f75... | 약 2일 후 종료 |
| 2026-02-07 11:55 | Launch | i-0a97... | 재생성 |
| 2026-02-09 06:20 | Terminate | i-0a97... | 약 2일 후 종료 |
| 2026-02-09 06:20 | Launch | i-0dc7... | 재생성 |
| 2026-02-11 11:49 | Terminate | i-0dc7... | 약 2일 후 종료 |
1-2. 원인 추론 과정 (Root Cause Analysis)
단순한 설정 오류가 아닌, 리소스 누적에 의한 장애로 판단하여 다음과 같은 흐름으로 원인을 좁혔습니다.
- Health Check 설정 검증: 로드 밸런서(ELB)의 Health Check 경로는 정상이며, 배포 직후에는 응답이 올바르게 반환됨을 확인했습니다.
- 장애 위치 특정: 설정 문제가 아니므로, 시간이 지남에 따라 EC2 인스턴스 내부에서 문제가 발생한 것으로 판단했습니다.
- 지연된 장애(Delayed Failure): 배포 직후가 아니라 2일 뒤에 Health Check가 실패한다는 것은, 시간이 지날수록 시스템 상태가 악화되어 응답 불능(Unresponsive) 상태에 빠짐을 시사합니다.
- 가설 수립: 애플리케이션 실행 중 리소스가 서서히 고갈되는 패턴이므로, 메모리 누수(Memory Leak) 또는 메모리 부족(OOM)을 가장 유력한 원인으로 특정했습니다.
2. 원인 분석 1: 기존 환경(t3.micro) 진단
가설을 검증하기 위해 기존 t3.micro 환경의 메모리 상태를 정밀 분석했습니다.
2-1. EC2 전체 메모리 상태 (free -m)
total used free shared buff/cache available
Mem: 988 842 41 12 104 73
Swap: 1024 512 512
- Available (73MB): 즉시 사용할 수 있는 메모리가 거의 고갈됨.
- Swap Used (512MB): 물리 메모리 부족으로 스왑 영역을 과도하게 사용 중.
- 해석: 이 상태에서는 작은 트래픽 스파이크에도 OOM Killer가 동작하거나, 심각한 성능 저하가 발생할 수 있습니다.
2-2. JVM 힙 사용률 확인 (jstat)
S0 S1 E O M YGC FGC
0.00 0.00 85.12 92.45 88.31 120 8
- Old Gen (92%): 장기 객체가 포화 상태.
- Full GC 발생: 메모리 회수를 위해 Full GC가 반복적으로 발생하며 Stop-The-World 시간이 길어짐.
2-3. 결론: EC2 종료 매커니즘 규명
- 메모리 부족 발생 및 스왑 사용
- GC 빈도 증가 및 CPU 사용률 급증
- 애플리케이션 응답 지연 (Stop-The-World)
- ELB Health Check 타임아웃 발생
- Auto Scaling Group이 인스턴스를 'Unhealthy'로 판정하고 종료
3. 해결 과정 1: 인프라 스케일업 (t3.micro → t3.small)
물리적 메모리 한계를 극복하기 위해 인스턴스 유형을 t3.small(2GB RAM)로 변경했습니다.
3-1. 변경 후 메모리 상태 (Default 설정)
total used free shared buff/cache available
Mem: 1910 790 469 2 815 1120
Swap: 1023 0 1023
- Available (1120MB): 메모리 여유가 충분해짐.
- Swap (0): 스왑 의존성이 사라짐.
3-2. 새로운 문제점 발견 (리소스 낭비)
물리 메모리는 늘어났으나, JVM 옵션을 따로 설정하지 않아(Default) Java는 여전히 보수적인 메모리 정책을 유지하고 있었습니다.
- Max Heap: 약 512MB (물리 램의 1/4 자동 설정)
- 문제: 나머지 1GB 이상의 메모리가 유휴 상태로 방치되며, 힙 공간 부족으로 인한 잦은 GC 위험은 여전히 존재함.
4. 해결 과정 2: JVM 메모리 최적화 (Tuning)
인스턴스 스펙업의 효과를 극대화하기 위해, 물리 메모리의 50%를 힙 메모리로 고정 할당하는 최적화 설정을 적용했습니다.
4-1. 실행 명령어 변경
[변경 전 (Default)]
nohup java -jar app.jar ...
[변경 후 (Optimized)]
nohup java -Xms1024m -Xmx1024m -XX:+UseG1GC -XX:MaxMetaspaceSize=256m -jar ...
4-2. 최적화 의도
- 메모리 활용 극대화:
-Xms1024m -Xmx1024m으로 1GB를 확보하여 비용을 지불한 자원을 100% 활용. - GC 빈도 감소: 힙 공간(Eden)이 넓어져 Minor GC 주기가 길어지고 CPU 효율 증가.
- 운영 안정성: 초기 힙 확보(
-Xms)로 트래픽 급증 시에도 할당 지연 방지.
5. 최종 검증 (Verification)
최적화 설정 배포 후 시스템 상태를 최종 점검했습니다.
5-1. JVM 힙 메모리 할당 확인 (jstat)
jstat -gc <PID> 1000 5
결과:
S0C S1C S0U S1U EC EU OC OU
0.0 29696.0 0.0 29696.0 280576.0 246784.0 738304.0 14839.0
- Total Heap Capacity: 약 1,048,576 KB (1GB) (정상 확장됨)
- Old Generation Usage: 14MB / 738MB (사용률 약 2%)
- 분석: 기존 대비 힙 용량이 8배 이상 증가했으며, 메모리가 매우 여유로워 Full GC 발생 가능성이 희박함.
5-2. 물리 메모리 점유율 확인 (top & free)
top 결과:
PID USER RES SHR S %CPU %MEM
3427 ubuntu 667680 25980 S 0.0 34.1
- RES (667MB): JVM이 1GB를 예약했으나, OS의 Lazy Allocation 특성으로 인해 실제 사용량은 효율적으로 관리되고 있음.
free -m 결과:
total used free shared buff/cache available
Mem: 1910 1069 158 2 846 840
- Available (840MB): JVM에 1GB를 할당하고도 OS 운영을 위한 충분한 여유 공간 확보.
6. 최종 결론
- 인프라 확장 (Scale-up) 성공:
t3.micro의 메모리 고갈 및 스왑 문제를t3.small도입으로 해결했습니다. - JVM 튜닝을 통한 효율 극대화: 하드웨어 확장에만 그치지 않고,
Xms/Xmx튜닝을 통해 늘어난 자원을 애플리케이션이 온전히 사용하도록 설정했습니다. - 안정성 확보: 현재 시스템은 메모리 부족으로 인한 셧다운이나, 잦은 GC로 인한 성능 저하 없이 안정적으로 운영 가능한 상태입니다.
'Project > 척척학사' 카테고리의 다른 글
| [척척학사] 포털 연동 과정 16초를 0.8초로 94.8% 개선한 과정 (0) | 2026.08.04 |
|---|---|
| 트래픽 피크형 서비스의 운영 구조를 요청 기반 구조로 바꾼 과정 (0) | 2026.08.04 |
| DB 커넥션 23초 점유 해결: 비동기 상태 머신으로 가용성 100% 확보하기 (0) | 2026.08.04 |
| [척척학사 | DevOps] Terraform으로 AWS 계정 간 인프라를 재현 가능하게 만들기 (0) | 2026.08.04 |
| [척척학사 | 부하 테스트 (3)] 7 TPS에서 96 TPS까지 — 병목을 제거하며 t3.micro의 한계를 밀어본 기록 (0) | 2026.08.04 |