일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- CHECK OPTION
- 스토어드 프로시저
- 지연로딩
- 비관적락
- 다대일
- 다대다
- 낙관적락
- 힙
- exclusive lock
- 연결리스트
- FetchType
- 일대다
- execute
- querydsl
- 연관관계
- dfs
- BOJ
- 백트래킹
- SQL프로그래밍
- fetch
- 동적sql
- 스프링 폼
- JPQL
- shared lock
- 유니크제약조건
- 이진탐색
- PS
- 즉시로딩
- eager
- 데코레이터
- Today
- Total
흰 스타렉스에서 내가 내리지
t2.micro 에 SpringBoot 프로젝트를 CI/CD 배포 할 경우, 메모리 부족으로 배포에 실패하는 경우 (feat. Swap Memory (스왑 메모리)) 본문
t2.micro 에 SpringBoot 프로젝트를 CI/CD 배포 할 경우, 메모리 부족으로 배포에 실패하는 경우 (feat. Swap Memory (스왑 메모리))
주씨. 2024. 3. 24. 14:34문제 원인 파악
Github Actions 로, 도커 이미지를 빌드한 후, ECS 에 자동 배포를 하고 있다.
ECS 는 EC2 t2.micro(프리티어) 를 기반으로 동작중이다.
CD 중에 memory 부족 에러가 발생하여 배포에 실패하였다.
해결 전에는 CPU 부족이 아닌 메모리 부족이라고 에러 메시지가 떴었다
why?? - (Rolling Update)
나는 ECS 에서 "롤링 업데이트 (Rolling Update)" 라고 불리는 업데이트 전략을 사용하고 있다.
롤링 업데이트 전략은, 서비스를 업데이트할 때 ECS 가 자동으로 새 버전의 태스크 인스턴스를 시작하고, 새 인스턴스가 정상적으로 시작되고 서비스에 트래픽을 성공적으로 수용할 수 있음을 확인한 후에 기존 버전의 태스크 인스턴스를 순차적으로 종료한다.
이 방법은 서비스 중단 시간을 최소화하며, 업데이트 과정에서 발생할 수 있는 문제를 감지하고 롤백하기 용이하다. 예를 들어, 새 버전의 태스크가 예상대로 작동하지 않는 경우, ECS 는 자동으로 롤백을 수행할 수 있으며, 이는 서비스의 가용성과 안정성을 보장하는데 중요하다.
즉, 롤링 업데이트 정책을 사용할 때, 새 버전의 애플리케이션을 실행하기 위해, 기존 애플리케이션과 동시에 두 버전이 일정 시간 동안 함께 실행될 수 있다. 이 과정에서 두 애플리케이션의 메모리 사용량 합계가 EC2 't2.micro' 인스턴스의 메모리 용량을 초과하면, 메모리 부족으로 인해 새 애플리케이션의 배포가 실패하는 것이다.
++
기존 애플리케이션이 종료되었더라도, 메모리 초과로 새 버전의 애플리케이션 실행에 실패하였다.
그럼 도대체 얼마나 메모리가 부족하길래?
이는 EC2 인스턴스의 사양을 높이면 바로 해결된다.
하지만 난 돈이 없어서 프리티어를 계속 써야 한다.
t2.micro 인스턴스는 1vCPU 와, 1GiB 메모리를 제공한다.
인스턴스의 메모리가 1GiB 로 아주아주 작기 때문에, 새로운 프로젝트를 배포하던 중 메모리를 초과하였을 가능성이 크다.
Spring Boot 프로젝트가 구동되고 있는 EC2 인스턴스에 접속하여, free 명령어를 사용하여, 메모리 사용량을 살펴본다
* Mem: 시스템의 RAM 상태
- total: 시스템에 설치된 전체 메모리의 양은 972,344KB, 약 949MB
- used: 현재 사용 중인 메모리의 양은 616,440KB, 약 602MB
- free: 현재 사용되지 않고 남아 있는 메모리의 양은 67,568KB, 약 66MB
- shared: 여러 프로세스에 의해 공유되고 있는 메모리의 양은 3,092KB, 약 3MB
- buff/cache: 버퍼와 캐시에 사용되고 있는 메모리의 양은 288,336KB, 약 282MB. 이 메모리는 필요시 다른 용도로 재사용될 수 있음
- available: 애플리케이션에 사용 가능한 메모리는 207,696KB, 약 203MB. 이 값은 free 메모리뿐만 아니라 일부buff/cache 메모리도 포함하며, 시스템이 스왑 없이 사용할 수 있는 메모리 양을 나타냄.
* Swap: 스왑 공간의 사용 상태. 스왑 공간은 디스크의 일부를 메모리처럼 사용하는 것으로, RAM이 부족할 때 사용됨.
- total, used, free: 이 시스템에는 스왑 공간이 설정되어 있지 않거나 사용되지 않고 있음을 나타냄. 모든 값이 0KB.
ps 명령어를 통해, 리눅스 시스템에서 메모리 사용량이 가장 많은 상위 10개의 프로세스 정보를 출력한다.
가장 메모리를 많이 사용하는 프로세스는 역시나 Spring Boot 프로젝트로, 약 40% 의 메모리를 사용하고 있다.
그 다음은 Docker 데몬으로, 4.9% 를 사용하고 있다.
추가적인 원인
ECS 태스크 정의에서 프로세스에 대한 메모리 예약이 너무 높게 설정되어 있을 수 있다.
이는 실제 사용량보다 더 많은 메모리를 예약하게 만들어, 남은 메모리 공간을 줄일 수 있다.
해결방안
1. 메모리 예약 및 할당 조정
ECS 태스크 정의에서 메모리 예약 (memoryReservation) 과 메모리 한도 (memory) 설정을 조정하여, 애플리케이션에 필요한 최소 메모리만을 예약하도록 한다.
이를 통해 더 많은 애플리케이션을 같은 인스턴스에서 실행할 수 있게 된다.
✅ 2. Swap 메모리 사용 - 해결
Linux 시스템에는 물리 메모리가 부족할 때, 디스크 공간의 일부를 가상 메모리로 사용하는 Swap 영역을 설정할 수 있다.
t2.micro 인스턴스에서 Swap 을 설정하는 것은 임시적인 해결책이 될 수 있으나, 디스크 I/O 성능에 영향을 줄 수 있으니 주의가 필요하다.
# 스왑 파일 생성
# bs : 블록 크기, count : 블록 수
# 스왑 파일은 2GB(64MB x 32)
# 시간이 좀 걸릴 수 있다. 참을성을 가지도록
sudo dd if=/dev/zero of=/swapfile bs=64M count=32
# 스왑 파일에 대한 읽기/쓰기 권한 설정
sudo chmod 600 /swapfile
# Linux 스왑 영역 설정
sudo mkswap /swapfile
# 스왑 공간에 스왑 파일을 추가하여 스왑 파일을 즉시 사용할 수 있도록 한다.
sudo swapon /swapfile
# 프로시저가 성공적인지 확인한다.
sudo swapon -s
# /etc/fstab 파일에 스왑 파일 추가하여 부팅 시 자동으로 스왑이 활성화되도록 설정
sudo vi /etc/fstab
# 파일 끝에 다음 줄을 새로 추가하고 파일을 저장한다.
/swapfile swap swap defaults 0 0
3. 롤링 업데이트 전략 조정
롤링 업데이트 전략을 조정하여, 동시에 실행되는 최소한의 태스크 수를 유지할 수 있다.
예를 들어, 서비스를 업데이트할 때 기존 태스크를 먼저 중지하고 새 태스크를 시작하는 전략을 선택할 수 있다.
이렇게 하면 메모리 사용량이 일시적으로 증가하는 것을 방지할 수 있다.
4. 도커 이미지 최적화
애플리케이션과 Docker 이미지의 메모리 사용량을 최적화한다.
사용하지 않는 의존성을 제거하고, 애플리케이션 로직 최적화 등을 통해 메모리 사용량을 줄인다.
Swap Memory 에 대해서
스왑 메모리(swap memory)는 컴퓨터 시스템에서 물리적 RAM(주 메모리)이 부족할 때 사용하는 디스크 공간입니다.
스왑은 시스템의 가상 메모리 관리 부분의 하나로, RAM에서 사용되지 않는 데이터를 일시적으로 저장함으로써, 실제 메모리를 효율적으로 사용할 수 있게 돕습니다.
👉 스왑 메모리 사용 이유
1. 메모리 부족 해결:
시스템의 RAM이 모든 실행 중인 프로세스를 수용하기에 부족할 때, 스왑 공간은 추가적인 "가상" 메모리를 제공합니다.
이를 통해 시스템은 더 많은 프로그램을 동시에 실행할 수 있게 됩니다.
2. 시스템 안정성 향상:
RAM이 가득 찼을 때 스왑 공간이 없다면, 시스템은 메모리 할당 실패로 인해 프로그램이나 시스템 자체가 충돌할 수 있습니다.
스왑 메모리를 사용함으로써 시스템은 이러한 위험을 줄이고 안정성을 유지할 수 있습니다.
3. 효율적인 메모리 사용:
스왑 메모리는 주로 장시간 사용되지 않는 데이터나 저우선순위의 데이터를 임시 저장하는 데 사용됩니다.
이를 통해 RAM은 더 중요하고 자주 사용되는 데이터 처리에 집중할 수 있어 전체 시스템의 효율성이 향상됩니다.
👉 스왑 메모리 사용 시기
1. RAM이 모두 사용될 때:
시스템이 RAM을 모두 사용하고 추가 메모리가 필요한 경우, 스왑 공간이 이를 대신하여 사용됩니다.
2. 저우선순위 프로세스 실행 시:
시스템은 일반적으로 덜 중요한 프로세스나 장시간 사용되지 않는 데이터를 스왑 영역으로 이동시켜 RAM을 보다 중요한 작업에 할당합니다.
3. 메모리 집약적인 작업을 할 때:
대규모 데이터베이스 처리, 대용량 파일 작업, 고급 그래픽 작업 등 메모리 사용량이 많은 작업을 수행할 때 스왑 공간은 RAM을 보조하여 시스템이 해당 작업을 계속 진행할 수 있도록 합니다.
👉 스왑 메모리의 장점
1. 비용 효율:
추가 RAM을 구매하지 않고도 디스크 공간을 활용하여 메모리 용량을 늘릴 수 있어 경제적입니다.
2. 시스템 유연성:
스왑 메모리는 시스템의 메모리 관리에 더 많은 유연성을 제공하며, RAM 사용이 최적화되도록 돕습니다.
3. 작업 연속성 보장:
메모리가 부족할 때 프로그램이 강제 종료되는 것을 방지하고, 사용자가 다수의 애플리케이션을 동시에 실행할 수 있게 합니다.
👉 주의사항
- 스왑 메모리는 RAM보다 훨씬 느립니다. 디스크 기반의 스왑 공간을 과도하게 사용하게 되면 시스템의 성능이 저하될 수 있습니다.
- 스왑을 효과적으로 사용하기 위해서는 적절한 스왑 공간 크기와 시스템의 메모리 사용 패턴을 고려하는 것이 중요합니다. 스왑 공간이 너무 크거나 너무 작으면 성능 문제나 메모리 부족 문제를 야기할 수 있습니다. 일반적으로, 스왑 공간의 크기는 시스템의 RAM 크기에 따라 달라지며, 시스템의 용도와 메모리 사용량에 맞추어 조정해야 합니다.
👉 스왑 메모리 설정 및 조정
스왑 메모리의 설정과 조정은 시스템의 메모리 요구 사항과 작업 부하에 따라 다르게 접근할 수 있습니다. 스왑 공간을 추가하거나 변경할 때는 다음 절차를 따르게 됩니다:
1. 스왑 공간 확인: swapon -s 명령어를 사용하여 현재 시스템에 설정된 스왑 공간을 확인할 수 있습니다.
2. 스왑 파일 생성: 충분한 스왑 공간이 없는 경우, dd 명령어를 사용하여 스왑 파일을 생성할 수 있습니다. 예: sudo dd if=/dev/zero of=/swapfile bs=1G count=1 명령어는 1GB 크기의 스왑 파일을 생성합니다.
3. 스왑 파일 설정: 생성된 스왑 파일에 대해 mkswap 명령어를 사용하여 스왑 영역을 설정하고, swapon 명령어로 스왑 파일을 활성화합니다.
4. 영구적 스왑 설정: 스왑 설정을 시스템 재부팅 후에도 유지하기 위해, /etc/fstab 파일에 스왑 파일 경로를 추가합니다.
👉 스왑 메모리의 영향
1. 성능 저하:
스왑 메모리 사용은 물리적 RAM보다 느리기 때문에, 과도한 스왑 활동은 시스템 성능 저하를 초래할 수 있습니다. 이는 특히 디스크 I/O가 높은 작업에서 두드러집니다.
2. 시스템 안정성 개선:
스왑 메모리는 시스템의 안정성을 개선할 수 있으나, 메모리 관리 전략의 일부로서만 사용해야 합니다.
스왑 공간에 의존하는 것보다는 애플리케이션과 시스템의 메모리 사용을 최적화하는 것이 더 바람직합니다.
스왑 메모리는 리소스 제한 환경에서 시스템 안정성을 보장하고 메모리 사용량을 관리하는 데 유용한 도구입니다.
그러나 스왑 공간의 사용은 신중하게 계획하고 모니터링해야 하며, 가능한 한 성능 저하를 최소화하고 메모리 최적화를 통해 실제 RAM 사용을 극대화하는 것이 중요합니다.
⬇️⬇️⬇️ CPU, RAM, 보조 메모리, Swap Memory 에 대해서 더 자세히 정리한 글 ⬇️⬇️⬇️
https://thisisjoos.tistory.com/638
⬇️⬇️⬇️ EC2 스와핑에 대한 AWS 의 공식 포스트 ⬇️⬇️⬇️
https://repost.aws/ko/knowledge-center/ec2-memory-partition-hard-drive
'AWS' 카테고리의 다른 글
Spring boot 에 ElastiCache for Redis 사용하기 (0) | 2024.05.06 |
---|---|
Lambda 에서 외부 라이브러리 import 하기 (계층 추가) (1) | 2024.03.29 |
EC2 인스턴스에 부하 테스트 (0) | 2023.10.09 |
ec2 userdata와 cloud-init을 이용한 docker 설치, 컨테이너 실행 (0) | 2023.10.09 |
[AWS] 내 도메인을 notion 외부 링크로 리다이렉션 시키자 (1) | 2023.10.09 |