#bottle-note #ecs #aws
이 게시글에서 세세한 설정은 다루지 않겠습니다 저 또한 다른 분들의 매우 좋은 글을 참고했습니다.
Bottle-Note 프로젝트의 프로덕션 배포 시기가 다가오면서,
프론트엔드 팀이 API 요청을 보다 원활하게 수행할 수 있도록 개발 서버 환경 구축이 필요해졌습니다.
개발서버를 구축하며 따라 운영 서버도 고민을 할 시기였는데 선택할 수 있는 배포 옵션은 다양하지만,
이미 다른 서비스에 대한 자원을 많이 사용 중인 개인 서버를 고려할 때,
클라우드 서비스를 사용하는 것이 배포의 안정성, 편의성, 확장성 측면에서 유리합니다.
이 중에서도 AWS를 선택한 배경은 아래와 같습니다:
EC2는 가상 서버 인스턴스를 제공하며 사용자가 직접 서버 관리를 해야 합니다.
반면, ECS는 컨테이너 오케스트레이션 서비스로, AWS가 클러스터 관리를 담당하며 사용자는 컨테이너 관리에 집중할 수 있습니다.
이미지 설명: EC2와 ECS의 관리 책임 구분을 나타내는 다이어그램. EC2는 운영체제와 가상 서버를 사용자가 관리하는 반면, ECS에서는 이러한 부분이 AWS에 의해 관리됩니다.
ECS를 선택한 이유는 아래와 같습니다:
ECR은 Docker 이미지를 저장하는 서비스로, ECS 및 EKS와 통합되어 컨테이너 이미지를 효율적으로 관리할 수 있게
도와줍니다. GitHub Actions를 사용하여 아래와 같이 ECR로 이미지를 푸시하는 과정은 매우 간단합니다:
on:
push:
branches: [ "main" ] # main 브랜치에서만 진행
permissions:
contents: read # 코드를 읽기만 가능하도록 설정
# 환경변수 설정 env:
# Spring Boot Active Profile
# ACTIVE_PROFILE: ${{ github.ref == 'refs/heads/main' && '' || 'develop' }}
# AWS Region
AWS_REGION: ap-northeast-2
# 도커 컨테이너명
CONTAINER_NAME: example-container-01
# ECR 리포지토리명
ECR_REPOSITORY: develop-example-application
# ECS 클러스터명
ECS_CLUSTER: develop-example-application
# ECS 서비스명
ECS_SERVICE: develop-example-application
# ECS Task definition 파일명
ECS_TASK_DEFINITION: task-definition-develop.json
jobs:
job:
name: Build & Deploy
runs-on: ubuntu-latest
environment: production
steps:
# 체크아웃
- name: Checkout
uses: actions/checkout@v3
# JDK 설정
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
# 권한 부여
- name: Run chmod to make gradlew executable
run: chmod +x ./gradlew
# Gradle clean build
- name: Build with Gradle
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: clean build
# AWS 자격 인증 설정
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# ECR 로그인
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
# ECR에 도커 이미지 Push
- name: Push docker image to ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: latest
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
ECR에 Push에 해당하는 부분인대 github action을 안다는 전제하에 보면 매우 간단한 흐름입니다.
이렇게만 해도 ECR 활용에 문제가 없습니다.
다만 추후 관리 시 이미지 라이프사이클은 관리하도록 설정하는것이 좋습니다.
일단 ECS와 EC2중에는 ECS를 선택했습니다.
> 이유는 컨테이너만 관리하면 되기 때문에 사용자가 서버에 대한 관리 오버헤드가 없기 때문입니다.
> 또한 image registry도 매우 쉽고 편하게 사용 가능한 ECR을 채택했습니다.
> 이제 고민해야 할 부분은 ECS on EC2와 ECS on Fargate중 어떤것을 선택할지 입니다.
이 옵션에서는 데이터 제어를 ECS가 맡고, 데이터플레인은 EC2가 담당합니다.
EC2 환경에서 다수의 ECS 작업이 실행되며, 인프라 관리가 필요합니다.
이에 따른 비용이 발생하며, SSH 등을 통한 직접적인 인스턴스 접근이 가능합니다.
Fargate에서는 ECS가 데이터 제어와 데이터플레인을 모두 관리합니다.
실행 호스트에 대한 접근이 제한되어 있으며, 보안 및 규정 업데이트가 자동으로 관리됩니다.
초단위 과금이 적용되어 비용 효율이 높습니다.
실질적인 운영 비용은 fargate가 더 비싸다.
이미지 설명: Fargate 비용 예시. 4vCPU, 8GB RAM, 20GB 스토리지 구성 시 예상 비용
전체적으로 고려해보았을때 ECS on fargate를 선택하고자 하였습니다.
그 이유로는 프로젝트의 규모와 관리 용이성과
초단위 과금과 관리의 편리성이 주된 이유입니다.
개인적으로 파일럿으로 구축해보면서 편한 부분과 난해한 부분들을 모두 느꼈습니다.
특히 ecs , ecr의 비용보다 nat gateway 비용등이 더 무서워
이런 부분들의 개선방법을 고안해봐야할것 같습니다.