Skip to content

인스턴스 비정상적 다운 문제

Lee kangmin edited this page Oct 17, 2024 · 2 revisions

인스턴스

인스턴스 환경

  • 컴퓨팅 : AWS EC2
  • OS : AWS Linux
  • memory : 1G
  • HDD : 10G

애플리케이션 환경

  • docker
  • spring boot
  • jdk 17

문제점👿

  • ⚠️인스턴스가 비정상적으로 다운되는 문제가 발생

가정❓

  • CPU 사용률 문제?
    • 인스턴스 모니터링을 통해 파악
image 위 로그를 보았을 때 CPU 사용량이 100% 넘지 않아도 서버가 다운되었었습니다. 따라서 CPU 사용량이 올라가서 서버가 다운되었다는 연관관계는 아닌 것으로 생각하게 되었습니다.
  • 메모리 사용량 문제?
    • 먼저 인스턴스에서 사용하는 메모리를 파악할 필요가 있었습니다.
    • 도커를 실행 한 뒤 메모리 사용량을 체크해보았습니다.
top - 02:21:54 up  1:27,  1 user,  load average: 0.00, 0.00, 0.00
Tasks: 112 total,   1 running, 111 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.7 us,  0.0 sy,  0.0 ni, 98.0 id,  1.3 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :    949.5 total,     61.7 free,    820.0 used,     67.8 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.     25.8 avail Mem

949.5 중에서 도커를 실행하니 820을 사용 중에 있었고 그림으로 표현되지 않았지만 해당 메모리 리소스 사용량이 늘어나는 것을 확인했습니다.

해결🌞

먼저 메모리 부족을 해결하기 가장 좋은 방법은 인스턴스 업그레이드, 하지만 무지성 업그레이드는 제 취향이 아니었습니다. 실제 동작하는 애플리케이션은 매우 적은 메모리로 동작하고 있었습니다. (1개 스프핑 부트 서비스 동작 시 350mb 정도) 그래서 인스턴스가 사용하는 가상메모리 공간을 늘려보기로 하였습니다.

AWS 가상메모리 할당량 늘리기

  1. dd 명령을 사용하여 루트 파일 시스템에 스왑 파일을 생성합니다. 명령에서 bs는 블록 크기이고 count는 블록 수입니다. 스왑 파일의 크기는 dd 명령의 블록 크기 옵션에 count 옵션을 곱한 값입니다. 이 값을 조정하여 원하는 스왑 파일 크기를 결정합니다.

지정한 블록 크기는 인스턴스의 사용 가능한 메모리보다 작아야 합니다. 그렇지 않으면 "memory exhausted" 오류가 발생합니다.

이 dd 명령 예제에서 스왑 파일은 4GB(128MB x 32)입니다.

sudo dd if=/dev/zero of=/swapfile bs=128M count=32
  1. 스왑 파일의 읽기 및 쓰기 권한을 업데이트합니다.
sudo chmod 600 /swapfile
  1. Linux 스왑 영역을 설정합니다.
sudo mkswap /swapfile
  1. 스왑 공간에 스왑 파일을 추가하여 스왑 파일을 즉시 사용할 수 있도록 합니다.
sudo swapon /swapfile
  1. 절차가 성공적으로 완료되었는지 확인합니다.
sudo swapon -s
  1. 부팅 시 /etc/fstab 파일을 편집하여 스왑 파일을 시작합니다. 편집기에서 파일을 엽니다.
sudo vi /etc/fstab

파일 끝에 다음 새 줄을 추가하고 파일을 저장한 다음 종료합니다.

/swapfile swap swap defaults 0 0

결과

인스턴스의 가상메모리는 증가하였지만 이미 도커가 사용하려는 메모리 영역이 부족하거나 CPU리소스를 모두 사용하려고 해서 서버가 다운되는 것 같습니다. 그래서 다른 방법으로 메모리 사용량을 줄이는 것이 좋을 것 같다는 생각에 도커 자체에서 할당하는 리소스를 제한시키는 방법을 생각했습니다.

해결2 ☀️

도커 컴포즈 파일을 수정에서 실행되는 도커 환경의 리소스를 제한한다.

networks:
  backend:
    driver: bridge

services:
  badminton-api:
    ports:
      - "8080:8080"  # API 서비스의 포트
    networks:
      - backend
    image: speech2/badminton:api
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
    # 일반 Compose 환경에서는 deploy 대신 아래 설정을 사용
    cpus: '1.0'      # 최대 1개의 CPU 사용
    mem_limit: 512M  # 최대 512MB 메모리 사용

  badminton-batch:
    ports:
      - "9090:9090"
    networks:
      - backend
    image: speech2/badminton:batch
    cpus: '0.5'       # 최대 0.5개의 CPU 사용
    mem_limit: 256M   # 최대 256MB 메모리 사용

인스턴스에서 도커를 실행하는 컴포즈 파일 세팅한 모습니다. 비교적 리소스를 적게 할당되는 애플리케이션은 메모리를 더 적게 할당해서 리소스를 제한했습니다. image 총 700MB 만 할당해서 1GB 메모리 리소스의 여유 공간을 확보하였습니다. 가상메모리 공간도 할당되어 있어서 700MB는 여유가 있을 것이라 판단됩니다.

실제 동작환경 모니터링

image 인스턴스 환경에서 리소스를 확인한 결과 949.5 중 779를 사용하는 것으로 보입니다. 즉 도커 환경에서 할당한 메모리 리소스 768를 크게 벗어나지 않은 모습입니다.

결론

인스턴스 가상메모리 + 도커 메모리 제한

스크린샷 2024-10-17 오후 5 01 48

인스턴스 서버가 지속적으로 다운이 되는 현상이 메모리 부족으로 인해 발생한 것이라 판단하였습니다. 부족한 메모리 리소스는 업그레이드를 통해 간단히 해결할 수 있는 것 처럼 보이지만 업그레이드를 해도 2GB 인 것을 확인했습니다. 2GB로 올리는 것 보다 현재 할당된 리소스 내에서 해결할 수 있는 범위에서 해결하는 것이 더 좋다고 판단하였습니다. 결국 도커가 동작하는 애플리케이션과 별개로 도커 환경 자체 리소스를 크게 할당되는 것을 방지해야 겠습니다.

또한 마냥 도커 메모리를 제한하면 애플리케이션에서 out of memory가 발생 할 수 있으므로 적절한 메모리를 할당하면 되겠습니다.