돌아오지 않는 메모리를 찾아서
백엔드
돌아오지 않는 메모리를 찾아서
두줄요약
Kubernetes에서 메모리 사용률이 99%까지 오르던 원인을 heap 누수로 의심했지만, JVM committed heap과 로그 파일 page cache가 핵심 원인이었습니다. JVM 옵션 조정과 FILE Appender 제거로 사용률을 크게 낮추고 안정화했습니다.
문제 상황
- Kubernetes 환경의 프로모션 계산 서비스에서 메모리 usage/limit이 99%까지 치솟지만 OOM이나 pod 재시작은 없는 상태
- 배포 후 1~2주가 지나면 메모리 사용률이 다시 limit 근처로 올라가는 고원 현상 반복
원인 분석
- 실제 heap 누수보다 JVM heap committed가 크게 유지되는 현상
- G1 +
InitialRAMPercentage=75,MaxRAMPercentage=75설정으로 committed heap이 limit 근처까지 오래 유지 - Logback FILE Appender가
/tmp/spring.log를 남기며 page cache가 증가
해결 방법
- JVM 메모리 상한을
InitialRAMPercentage=40,MaxRAMPercentage=60으로 조정 memory limit을 3G에서 3.5G로 재조정- FILE Appender 설정 제거로 pod 내부 로그 파일 저장 중단
성능/운영 포인트
- memory.usage, working_set, RSS, cache, heap committed를 함께 확인할 필요
- cgroup 실측과 Datadog 지표를 같이 봐야 heap 누수와 page cache를 구분 가능
- 장기 운영 pod에서 page cache가 메모리 사용률을 크게 끌어올릴 수 있음
적용해볼 점
- 메모리 문제를 heap 누수로 단정하지 말고 컨테이너 전체 메모리 구성을 점검
- 로그 파일 저장 방식이 pod 메모리 사용에 미치는 영향 검토
- 서비스 특성에 맞는 JVM 옵션과 리소스 상한 재점검
