여러 기술적 이슈들이 있었지만, 잘 극복 후 소수의 유저들을 대상으로 운영 중이다.
하지만 그저께 새벽,,,문의 단톡방에 아주 놀라운 채팅이 올라왔다.
자세한 내용은 밝힐 수 없지만 모종의 경로를 통해 우리 앱을 알게 되셨고, 정말 감사하게도 협업 문의를 주셨다.
약 1000 단위의 유저가 참여하고 2주간 진행되는 이벤트라고 하셨다.
그렇다면 우리 서버는 최악의 경우에 초당 1000개의 이상의 요청을 처리할 수 있어야한다.
하지만 아래와 같은 우리 앱의 특성 상 무작정 서버의 성능을 높이기엔 비효율적이었다.
이런 고민을 하던 중, AWS에서 EC2 인스턴스의 개수를 동적으로 늘릴 수 있는 Auto Scaling을 알게 되었고 이를 위해 AMI를 만들기로 했다.
약간은 이상하지만,, 호스트 머신에서 프로젝트 파일을 통째로 압축하고 이를 EC2에서 받아 다시 압축을 풀고 도커 이미지를 만들어 실행하는 구조다.
그렇다면 AMI는 어떤 식으로 만들어야할까?
지금 돌아가고 있는 서버를 그대로 AMI로 만든다고 해도 서버에서 새로운 변경사항이 생기면 이를 반영하지 못하는 문제가 생긴다.
즉, AMI가 실행될 때 '가장 최신의' 프로젝트 파일을 가져와 도커 이미지로 만들고 실행하는 과정을 거쳐야한다.
내가 생각한 흐름은 다음과 같다.
그렇다면, 우선 서버에 aws cli를 설치한다.
다음은 쉘 스크립트를 작성한다.
echo "> remove current project file"
rm -rf /home/ubuntu/ground_flip
echo "> remove current log file"
rm -rf /home/ubuntu/logs/groundflip_log.log
echo "> get latest project file from s3"
sudo aws s3 cp s3://{bucket_name}/deploy/ground_flip.zip /home/ubuntu/ground_flip.zip
echo "> unzip project file"
unzip /home/ubuntu/ground_flip.zip -d /home/ubuntu/ground_flip
echo "> delete project zip file"
rm -rf /home/ubuntu/ground_flip.zip
이미지 생성 후 컨테이너를 띄우는 과정은 프로젝트 폴더 내에 deploy.sh에 있어 이를 재활용하기로 했다.
#!/usr/bin/env bash
APP_NAME="ground_flip"
REPOSITORY=/home/ubuntu/ground_flip
echo "> Check the currently running container"
CONTAINER_ID=$(docker ps -aqf "name=$APP_NAME")
pwd
ls
if [ -z "$CONTAINER_ID" ];
then
echo "> No such container is running."
else
echo "> Stop and remove container: $CONTAINER_ID"
docker stop "$CONTAINER_ID"
docker rm "$CONTAINER_ID"
fi
echo "> Remove previous Docker image"
docker rmi "$APP_NAME"
echo "> Build Docker image"
docker build -t "$APP_NAME" "$REPOSITORY"
echo "> Run the Docker container"
docker run -d -p 8080:8080 --env-file /home/ubuntu/ground_flip/.env -e TZ=Asia/Seoul -v /home/ubuntu/logs:/logs --name "$APP_NAME" "$APP_NAME"
이제 AMI를 만들고 시작 템플릿을 만들면 된다.
원하는 인스턴스에서 이미지 생성을 선택한다.
이제 생성된 이미지로 시작 템플릿을 만든다.
자잘한 항목들은 필요에 따라 선택하면 되지만, 아래 사진들에서 보다시피 적절한 IAM 역할을 부여해야 S3 접근, Cloudwatch로 로그 전송 등이 가능하다.
마지막으로, 사용자 데이터를 입력해 인스턴스가 생성될 때 실행할 명령어들을 기재한다.
나는 프로젝트 파일을 가져와 압축을 푸는 on_start.sh
와 도커 이미지 생성 후 컨테이너를 띄우는 deploy.sh
를 실행하게끔 했다.
해당 시작 템플릿으로 인스턴스를 생성 후 docker ps
를 입력하면 아래와 같이 컨테이너가 동작 중인 것을 볼 수 있다.