너도 할 수 있다! 배포를 위한 AWS ECS 인프라 구축🔥

sujin·2024년 3월 10일
2

AWS

목록 보기
1/1
post-thumbnail

백만년 만에 벨로그 🙊

개요

프론트 개발을 시작한지도 2년차에 들어서면서 회사에서 하는 일이 점점 익숙해져 갈 때쯤 새로운 업무가 주어졌다! 그동안은 항상 말로만 들어서 나와는 상관없다고 느꼈던 AWS ... 드디어 그녀석과 제대로 마주할 일이 생겼다.😨💦
항상 수동 배포로만 진행하던 프로젝트가 있었는데 미루고 미뤘던 그 녀석의 자동배포를 내가 맡게된 것!

자동배포를 위한 AWS ECS 인프라 구축 이라고만 하면 너무 거창해서 내가 할 수 있을까? 싶지만 하나하나 뜯어보면서 하니깐 어느새 목적지에 도달해 있는 나를 발견할 수 있었다ㅎㅎ

처음엔 AWS 홈페이지 자체가 뭔가 어색하고 어디를 어떻게 들어가서 뭐를 누르라는 거지...? 싶었지만 계속 보다보니 이또한 익숙해졌다ㅎㅎ 이 블로그는 나와 같이 AWS를 처음 접하는 사람들을 위해 하나하나 최대한 이해가 쉽게 갈 수 있도록 상세하게 적어봤다. 부디 누군가에게 도움이 될 수 있길 바라면서 꽤나 긴글을 시작해본다😉



본격적인 구현 과정을 설명하기 전에 먼저 내가 구현한 자동배포 프로세스는 다음과 같다.

1. Dockerfile

  • 컨테이너를 구성할 때 필요한 특정 명령어 집합들을 실행시켜 도커 이미지를 생성하는 역할을 한다.
  • 생성한 프로젝트 루트에 위치한다.

1-1) Dockerfile 생성

FROM node:16              기본 이미지로 Node.js 16을 사용

COPY package*.json ./     프로젝트 디렉토리에 있는 package.json 및 package-lock.json 파일을 도커 이미지 내부의 /app 디렉토리로 복사
RUN npm install           의존성 패키지를 설치하기 위해 npm을 실행
COPY . .                  프로젝트 디렉토리의 모든 파일을 도커 이미지 내부의 /app 디렉토리로 복사

RUN npm run build         프로젝트의 빌드 스크립트를 실행

EXPOSE 3000               컨테이너가 사용하는 포트를 외부에 노출합니다. 여기서는 애플리케이션이 3000번 포트에서 실행되고 있다고 가정하고 노출

CMD ["npm", "start"]      컨테이너가 시작될 때 실행되는 명령어를 정의합니다. 여기서는 npm start 명령을 실행하여 애플리케이션을 시작

1-2) Docker image build

docker build -t your_image_name .
docker images
  • Dockerfile이 있는 디렉토리에서 이미지가 빌드되며, 해당 디렉토리 내에 있는 소스 코드 및 파일이 이미지에 포함된다.
  • . 은 현재 디렉토리에서 빌드 하겠다는 것을 의미한다.

1-3) Docker image push

  • Docker image를 push하기 위해서는 ECR repository 생성 이 먼저 선행 되어야 한다.
  • image를 push하기 위한 명령어는 ECR repository에서 푸시 명령 보기를 하면 확인 할 수 있다.

🤔 배포 할 때마다 매번 이렇게 수동으로 docker image를 push 해줘야 하나?
➡️ 이미지 빌드 및 푸시를 자동화하기 위해서 CI/CD (GitHub Action) 파이프라인을 구축하여 자동으로 빌드 및 푸시 되어 배포 프로세스가 실행될 수 있도록 한다.

배포 프로세스를 정리하자면,
1. 코드 변경 : 코드가 변경되면 CI/CD (GitHub Action)이 실행된다.
2. 빌드 : CI서버에서 Docker 이미지를 빌드한다.
3. 이미지 푸시: 빌드된 이미지를 Docker 레지스트리 (ASW ECR)에 푸시한다.
4. 배포 : ECS 를 통해 새로운 이미지를 배포한다.



2. ECR Repository 생성

  • Docker Image를 보관하는 역할을 한다.
  • GitHub Action으로 생성한 Docker Image를 이곳에 업로드한다.

2-1) 생성 방법

  1. ECS > ECR > 리포지토리 > 리포지토리 생성
    ecr 레포지토리 생성
        

3. 태스크 정의 (Task Definition) 생성

  • 태스크 정의docker-compose 와 비슷한 역할을 한다.
    • 어떤 도커 이미지를 사용한 것인지, 포트 매핑, 인스턴스 타입, CPU 나 메모리는 얼마나 쓸 건지 등을 정해서 알려주면 주문에 맞게 컨테이너를 올려준다.

3-1) 생성 방법

1. 프로젝트에 task-definition.json파일 생성

  • 템플릿 예시 or 이미 생성 되어 있는 각 프로젝트의 task-definition.json 파일 참고
  • 설정 값 중에 executionRoleArn 값은 AWS IAM 계정이 있어야 알 수 있다.
  • executionRoleArn 확인 방법
    IAM > 엑세스 관리 > 사용자 그룹 > 해당 그룹 선택 (ecs_deploy_role) > 요약 - ARN
    ecs_deploy_role

2. 완성된 task-definition.json을 aws-cli을 사용해서 AWS 계정에 등록

  • aws-cli 설치 방법

    • json 파일을 등록하기 위해 명령어 (mac OS기준)
      aws ecs register-task-definition --cli-input-json file://[your task-definition.json name with path]
      
      // 예시
      aws ecs register-task-definition --cli-input-json file:///Users/sujin/Desktop/cicd-test/.github/task-definition.json
    • 완료 후 ECS > 태스크 정의 에 등록된 걸 확인 할 수 있다
      태스트 정의


4. 클러스터(Cluster) 생성

  • 클러스터는 task 그리고 정의한 작업을 관리해주는 service가 동작하는 곳이다

4-1) 생성 방법

  1. ECS > 클러스터 > 클러스터 생성
  2. 클러스터 이름 지어주기
  3. 인스턴스 타입으로 Fargate와 EC2 중 선택 (Fargate 선택)


5. 서비스 (Service) 생성

  • 서비스란 등록한 task를 관리하며 배포된 시스템이 정상 상태로 유지하도록 하는 역할을 하는 곳
  • ECS > 클러스터 > 내가 생성한 클러스터 (cst-cluster-test) 클릭 > 하단 서비스 생성 클릭
    서비스 생성1서비스 생성2
  • 서비스를 생성하기 위해서 네트워크에 대한 설정을 해줘야하는데 선택사항은 제외하고 다음 항목에 대해서 세팅 진행
    • 환경
    • 배포 구성
    • 네트워킹
    • 로드 밸런싱

5-1) 환경

  • 기본세팅 되어 있는 대로 진행
    환경

5-2) 배포 구성

배포구성1배포구성2

배포 옵션

무중단 배포

새로운 버전이 배포 될때가지 애플리케이션이 중단(다운타임) 되는 것을 막기 위한 방법

  1. Rolling 배포
    Rolling
  • 인스턴스를 늘리지 않고 하나씩 새로운 버전으로 늘리는 기법
  • 사용중인 인스턴스에 트래픽이 몰리는 문제가 있음
  • 버전간 호환성 문제가 생기는 순간이 있음
  1. Blue Green 배포
    Blue Green1Blue Green2
  • 구버전과 같은 환경으로 신버전을 미리 준비함
  • 로드밸랜서의 라우팅을 환번에 전환시킴
  • 구버전의 환경을 재활용하거나 롤백하기 쉬움
  • 시스템 자원이 두배로 듬

5-3) 네트워킹

네트워킹

  • vpc는 현재 공통으로 사용하고 있는 qb-vpc를 선택
  • qb-vpc에는 총 5개의 서브넷이 있는데 그중에 퍼블릭만 선택
  • 보안 그룹은 새 보안 그룹을 생성해도 되지만 특별히 추가되는 내용이 없다면 현재 사용하고 있는 보안 그룹을 선택

5-4) 로드 밸런싱

로드 밸런싱1로드 밸런싱2

  • 로드 밸러서란?
    • 둘 이상의 가용 영역에서 EC2 인스턴스, 컨테이너, IP주소 등 여러 대상에 걸쳐 수신되는 트래픽을 자동 분산한다.
    • 로드 밸러서의 유형은 Application Load Balancer 을 선택한다.
  • 대상 그룹 (target group) 이란?
    • 지정한 프로토콜과 포트 번호를 사용하여 EC2 인스턴스 같은 개별 등록된 대상으로 요청을 라우팅한다.

5-5) 트러블슈팅

서비스 환경 설정을 모두 해줬다면 서비스 배포를 진행하면 되는데, 이 과정에서 경험했던 트러블슈팅에 대해서 공유한다.

1. 오류 발생

오류발생

  • 서비스 배포가 실패했다는 오류가 발생, "Error occurred during operation 'ECS Deployment Circuit Breaker was triggered”.
  • 해당 오류를 cloudFormation에서도 살펴봤지만 정확한 실패 원인이 무엇인지 알 수 없었다.

2. 시도

  • 해결 방법을 찾아보던 중에 AWS CloudWatch 에서 자세한 로그를 살펴 볼수 있다고 해서 진행했다.
  • AWS CloudWatch > 로그 > 로그 그룹 > 로그 그룹 생성
  • 생성한 로그 그룹을 작업정의에 추가 해줘야함
    시도
  • containerDefinitions 안에 logConfiguration 에 CloudWatch에 생성한 로그 그룹을 등록 해 준다. (새롭게 수정한 작업정의는 aws에 업데이트 해줘야함)
    aws ecs register-task-definition --cli-input-json file://your-updated-task-definition.json --region your-region

3. 원인

원인

  • 로그 그룹을 등록한 후 살펴본 결과 exec /usr/local/bin/docker-entrypoint.sh: exec format error 이런 오류가 볼 수 있었다.
  • 해당 오류는 AWS의 아키텍처와 도커(컨테이너 이미지)의 아키텍처가 달라서 발생하는 오류임을 알 수 있었다.
    • aws : X86_64
    • docker : arm64
        uname -m

4. 해결 방법

  • AWS의 아키텍처는 Fargate를 사용하는 경우 작업정의에서 설정해줄 수 있다. 따라서 AWS의 아키텍처와 도커의 아키텍처를 동일하게 설정해준다. (수정 후 aws 작업 정의 업데이트 해줘야함)
  • X86_64arm64
    해결 방법


6. Route 53

  • AWS Router53 이란 DNS 웹 서비스로 도메인 등록, DNS 라우팅, 상태 확인을 조합하여 실행 할 수 있다.
  • 생성한 서비스 배포까지 완료되었다면 마지막으로 Route 53과 로드 밸랜서를 연결하여 도메인을 생성한다.

6-1) 생성 방법

1. Route 53 > 호스팅 영역 > 도메인 이름 선택 > 레코드 생성

레코드생성1레코드생성2

2. 레코드 이름을 설정 해주고 트래픽 라우팅 대상에 위에서 생성했던 로드 밸런서를 연결해준다.

레코드생성3레코드생성4

6-2) HTTPS 설정

  • HTTP로 연결된 url로 접속하면 경고 문구가 뜨기 때문에 HTTPS로 변경해주는 작업을 진행해야한다.
  • 로드 밸런서를 사용하여 HTTP요청을 HTTPS로 리디렉션 시켜준다.

1. 연결된 로드밸런서 선택

  • EC2 > 로드밸런싱 > 로드밸런서 > 로드밸런서 선택

2. 리스너 추가

리스너 추가

3. 기존 리스너(HTTP:80) 편집

  • 위에서 추가한 리스너로 리디렉션
    기존 리스너(HTTP:80) 편집

4. 완료✨

완료



이렇게 AWS ECS 배포 환경 구축이 마무리됐다!🙊 자동배포 프로세스까지 연결하려면 CICD 파이프라인까지 구성해야한다. 그 부분에 대해서도 추후에 정리해서 올려야겠다ㅎㅎ
처음엔 막연했는데 막상 해보고 나니 별거 아닌거처럼(?) 느껴지도 한다. 그래도 AWS랑 조금은 친해진거 같아서 의미가 있었고 앞으로도 AWS와 더 친해질 수 있도록 인프라 쪽에도 지속적으로 관심을 가져야겠다~!!

profile
개발댕발

1개의 댓글

comment-user-thumbnail
2024년 3월 13일

잘보고 가요~ ^^

답글 달기