본문 바로가기

Feel-Archive

[Feel-Archive] 성능 테스트(1) - 1GB 메모리에서 모니터링 구축하기

배경

Feel-Archive 프로젝트 성능 측정을 진행하기 전에 서버 자원 지표를 수집하기 위해 Prometheus 도입을 결정했다. Grafana까지 EC2에 올리면 메모리 부담이 크다고 판단해 Prometheus만 docker-compose에 추가했다. Spring Boot Actuator를 사용하였고Prometheus가 15초마다 수집하는 구조였다.

 

원인 & 문제 해결

처음에 기존에 EC2에 Spring App, MySQL, Redis가 띄워져있는 상태로 Prometheus도 추가해줬는데 터미널이 아예 먹통이 되어서 메모리나 docker stats같은것도 확인할 수 없어서 재부팅 후 Spring App에 메모리를 할당해주고 재시작했다.

 

그제서야 이제 터미널 먹통이 조금 풀리고 명령어를 실행할 수 있어서 확인해봤는데 free -h로 확인해보니, 가용 메모리가 25MB밖에 없었다. 

              total      used        free      shared     buff/cache    available
Mem:         957Mi       819Mi       76Mi       1.0Mi        60Mi        25Mi
Swap:         0B          0B          0B

 

docker stats로 도커 상태를 확인했는데 다음과 같았다. 

CONTAINER ID   NAME           CPU %     MEM USAGE / LIMIT   MEM %     NET I/O           BLOCK I/O       PIDS
84a29d196a49   feel-archive   0.15%     311.2MiB / 350MiB   88.91%    35.4kB / 28.8kB   170MB / 176kB   35
6e133272f809   feel-mysql     0.37%     201.1MiB / 350MiB   57.45%    100kB / 115kB     319MB / 18MB    44
d02cb7bc5de5   feel-redis     0.21%     5.113MiB / 50MiB    10.23%    2.14kB / 126B     51.7MB / 0B     6

 

기존 시스템은 Spring Boot 350MB, DB 350MB, Redis 50MB로 컨테이너별 mem_limit을 설정해 운영 중이었다. docker stats 지표를 확인한 결과, DB의 실제 메모리 사용량은 할당량의 57% 수준이었다. 성능 측정을 위한 Prometheus 컨테이너(최소 50MB 필요)를 실행하기 위해, 여유가 확인된 DB의 mem_limit을 350MB에서 250MB로 하향 조정했다. 이를 통해 각 컨테이너의 메모리 상한선 총합이 서버의 물리적 가용 메모리를 초과하지 않도록 제어하고, Prometheus가 안전하게 동작할 수 있는 공간을 시스템 차원에서 보장했다.

 

운영 환경의 mem_limit의 기준은 로컬 환경에서 docker stats해서 나온 값의 * 2배 정도를 줬다. 이유는 운영 환경은 트래픽이 있어 로컬보다 메모리 사용량이 높을 수 있고, OOM으로 컨테이너가 강제 종료되는 것을 방지하기 위해 여유분을 두고 2배로 설정했다.

 

prometheus를 띄우는데 성공은 했지만 가용 메모리를 확인해보니 여전히 적어서 터미널이 먹통이 되었다.

               total        used        free      shared  buff/cache   available
Mem:           957Mi       839Mi        62Mi       1.0Mi        54Mi       9.0Mi
Swap:             0B          0B          0B

컨테이너별 자원 할당량을 이미 최적화된 최소 수준으로 조정해서 더 이상 조정할 부분이 없어서 SWAP 메모리를 사용하도록 결정했다. 

Filesystem      Size  Used Avail Use% Mounted on
/dev/root       7.6G  5.8G  1.8G  77% /
tmpfs           479M     0  479M   0% /dev/shm
tmpfs           192M  1.2M  191M   1% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
/dev/xvda15     105M  6.1M   99M   6% /boot/efi
tmpfs            96M  4.0K   96M   1% /run/user/1000

 

현재 1.8GB 정도 여유분이 있어서 1GB 정도 SWAP 메모리로 설정했다.

 

프로메테우스 띄우기 전, SWAP 메모리 확인

               total        used        free      shared  buff/cache   available
Mem:           957Mi       742Mi        66Mi       0.0Ki       148Mi        61Mi
Swap:          1.0Gi        38Mi       985Mi

 

프로메테우스 띄운 후, 메모리 및 docker stats 확인

               total        used        free      shared  buff/cache   available
Mem:           957Mi       546Mi        65Mi       0.0Ki       345Mi       256Mi
Swap:          1.0Gi       334Mi       689Mi

 

CONTAINER ID   NAME              CPU %     MEM USAGE / LIMIT   MEM %     NET I/O           BLOCK I/O         PIDS
6065b04f0362   feel-mysql        0.42%     193.4MiB / 250MiB   77.35%    20.9kB / 20.1kB   87.5MB / 16.8MB   45
84a29d196a49   feel-archive      0.11%     201.7MiB / 350MiB   57.64%    1.12MB / 14MB     316MB / 313MB     37
e1914603de1b   feel-prometheus   0.02%     16.23MiB / 50MiB    32.45%    13.3MB / 2.46MB   244MB / 32.7MB    7
d02cb7bc5de5   feel-redis        0.14%     1.367MiB / 50MiB    2.73%     16.7kB / 2.75kB   37.9MB / 4.21MB   6

 

Prometheus 실행 후 OS가 당장 사용하지 않는 메모리 페이지를 Swap 영역으로 이동시키면서 물리 메모리 가용 공간을 256MB만큼 확보할 수 있었다.

느낀점

실제 운영 환경에서 t2.micro와 같은 스펙을 사용하는 경우는 드물다. 서버 스펙업으로 간단히 해결할 수 있지만, 그 전에 현재 자원에서 최적화할 수 있는 부분이 있는지 확인하는 것이 먼저라고 생각했다. docker stats, free -h같이 아주 기본적인 명령어로 실제 사용량을 측정하고 수치 기반으로 메모리를 조정하는 경험을 할 수 있었다.