ECR ECS Fargate 기반 아키텍처 마이그레이션

devyu·2024년 12월 6일
0

안녕하세요, devyu입니다.

저는 이전에 참여한 SKT 데보션영의 최종 개발 프로젝트, 올랑올랑의 인프라를 담당했습니다. 기존 ec2, rds 기반의 인프라를 ecr + ecs + fargate 기반의 서버리스 cicd 로 변경한 과정을 적어보고자 합니다.

기존 인프라 구성에 대해

먼저 기존의 인프라는 간단하게 EC2 + RDS 를 활용하여 구성되었으며, CICD의 경우 Github Actions + CodeDeploy + S3 를 통해 아래와 같은 형태로 구현하였습니다. 모니터링 역시 간단하게 구현하였습니다.
Slide 16_9 - 34.jpg

자세한 구현 방법은 아래 글을 참조해주세요.
https://velog.io/@ycoding/Spring-Boot-simple-deploy
https://velog.io/@ycoding/CICD-Github-Actions-CodeDeploy-S3
https://velog.io/@ycoding/Prometheus-Grafana

문제점

해당 아키텍처에서는 몇가지 문제가 있었습니다. 프리티어 t3 인스턴스이다보니 메모리 사용량이 매우 높아, 매일 3~4번 정도의 80% 알람이 발생하였으며,
무중단 배포가 적용되지 않아 새로운 배포 진행시에 지연이 발생하게 되고, 이로 인해 서버가 중단되는 기간이 존재했습니다.
이러한 문제를 해결하기 위해 serverless로 개선해보자! 하고 생각하게 되었습니다.

인프라 개선

이제 본격적으로 ECR ECS Fargate 를 활용하여 개선한 과정에 대해 설명하겠습니다.

깃헙 액션으로 AWS ECR에 이미지 빌드 자동화

yaml파일 만들기

깃헙 레포지토리에 액션탭에서 새로운 워크플로우를 위한 yml파일을 생성했습니다. 코드는 아래와 같습니다.

name: CI/CD using AWS ECR ECS

on:
  push:
    branches: [ "main" ]

permissions:
  contents: read

jobs:
  CI-CD:
    runs-on: ubuntu-latest
    steps:

      # JDK 설정
      - uses: actions/checkout@v3
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'

      # Gradle 캐싱
      - name: Gradle Caching
        uses: actions/cache@v3
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            ${{ runner.os }}-gradle-

      # 환경별 yml 파일 생성 - application.yml
      - name: make application.yml
        if: contains(github.ref, 'main')
        run: |
          mkdir -p ./src/main/resources
          cd ./src/main/resources
          touch ./application.yml
          echo "${{ secrets.YML }}" > ./application.yml
        shell: bash

      # 환경별 yml 파일 생성 - prod
      - name: make application-prod.yml
        if: contains(github.ref, 'main')
        run: |
          cd ./src/main/resources
          touch ./application-prod.yml
          echo "${{ secrets.YML_PROD }}" > ./application-prod.yml
        shell: bash

      # Gradle 빌드
      - name: Build with Gradle
        run: ./gradlew build -x checkstyleMain -x checkstyleTest -x editorconfigCheck -x test

      # 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: ap-northeast-2

      # Amazon ECR 로그인
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

# Docker 빌드 및 ECR에 푸시
      - name: Build, tag, and push image to Amazon ECR
        run: |
          {위의 푸시 명령 작성}

ECR 레포지토리 만들기

프리이빗 레포지토리를 생성합니다.

오른쪽 위에 보이는 푸시명령보기를 선택하고
2번부터 4번까지 차례대로 복사하여 아까 만들었던 yaml파일에 적용합니다.
이와 같이 만들어지면 액션 설정은 완료됩니다.

이후 실행해보면 잘 업로드가 되는 것을 확인할 수 있습니다. 이제 코드 푸쉬를 하게되면 자동으로 새로운 이미지가 만들어지게 됩니다. (latest 라는 태그는 고정)

ECR에 올려져 있는 이미지 ECS로 실행 하기

해당 과정을 나누어
1. 작업정의 2. 로드밸런서 3. 서비스 생성

순서로 진행해보겠습니다.

먼저 클러스터와 작업정의를 만들어줍니다. 이는 아래와 같은 절차로 진행할 수 있습니다.

ECS에서 클러스터와 작업정의 먼저 생성합니다.


역할을 다음과 같이 생성해줍니다.



ecsTaskExecutionRole 이라는 이름으로 생성하였습니다.


이름설정 -> ECR 이미지의 latest의 url을 복붙 -> 포트매핑: -> 추가

최종적으로 아래와 같이 ECS를 생성하였습니다.

컨테이너 추가

작업정의 생성
로드밸런서 생성
애플리케이션 로드밸런서 생성
로드밸런서 이름 생성
네트워크 매핑 4가지 다 체크
보안그룹 생성
선택
타겟그룹 생성
ip adress로 생성 -> 이름설정 -> 생성
-> 로드밸런서 생성
서비스 생성
생성
FARGATE선택 -> 서비스이름 설정 -> 서비스개수 과감하게 3개(수평확장을 위해)
나머지 기본값 -> 다음
' VPC 선택 -> 서브넷 전부 선택 -> 보안그룹 아까 우리가 만들었던 보안그룹 선택
애플리케이션 로드밸런서 선택
아까 만들어 놓은거 선택
다음 -> 서비스 생성
그러면 프로비저닝이 시작된다. 그리고 Running 상태로 바뀌면 대상그룹이 초기화 되며 시작됩니다.

그 다음 확인해야 할 것은 로드밸런서의 타겟그룹이 Healthy상태가 되었는지 체크해야 합니다.
(spring boot 프로젝트 내에 헬스 체크를 위한 api가 설정 되어있어야 하며 정상적으로 동작하는지 반드시 확인해야 합니다. )

건강한 상태에서는 브라우저 검색시 제대로 나오는 것을 확인할 수 있습니다. (8000번 포트를 매핑 해 놓았기 때문에 로드밸런서 주소 마지막에 :8000을 붙혀야 뜹니다)

파이프라인 구축

이제 파이프라인을 구축할 차례입니다.
Codepipeline에서 파이프라인을 생성합니다.

다음으로, 소스 스테이지를 추가하였습니다. 소스는 위에서 생성한 ECR의 최신 이미지를 가져올 수 있도록 하였습니다.

이제 빌드 프로젝트를 생성합니다.

buildspec은 다음과 같이 작성하였습니다.

배포 스테이지는 다음과 같이 설정하였습니다.

위와 같은 과정을 통해 최종적으로 파이프라인이 잘 동작하는 것을 확인할 수 있습니다

profile
티스토리와 벨로그 사이 줄타기....

0개의 댓글