ECS Cluster 생성

Cluster란?
ECS 클러스터는 Docker Container를 실행할 수 있는 논리적인 공간이다.
ECR에 등록한 Docker Image를 가지고 컨테이너를 구성하려면 이 클러스터를 생성 및 사용해야 한다.

클러스터 이름을 sample-cluster로 짓고, 나머지 설정은 그대로 둔 후 생성한다.

인프라 탭에서 주로 Fargate와 EC2 인스턴스 둘을 사용한다.
간략하게 두 인프라의 차이점을 살펴보면 아래와 같다.


EC2인스턴스
EC2는 AWS에 대표적인 서비스 중 하나이다. 주로 서버로 사용하며, 비용을 지불하고 가상의 서버를 대여 받을 수 있다.

ECS 서비스를 구축할 때 EC2 인스턴스를 인프라로 선택하면 서비스에 속한 EC2 인스턴스 서버와 클러스터를 직접 관리해주어야 한다.

Fargate
EC2 인스턴스와 다르게 서버 인스턴스를 관리할 필요가 없는 컨테이너 서비스이며 사용량에 따라 요금이 부과되는 종량제 형식으로 제공된다.
(서버리스란 서버가 없다는 것이 아니다. 서버가 필요한 순간이 왔을 때 잠시 서버를 깨워 기능을 수행하고 다시 잠든다. 이렇게 종량제 서비스가 되는 것이다.)

EC2 인스턴스와 Fargate는 상황에 맞게 잘 고려해서 선택하면 될 것 같다.


Task 정의 생성

다시 본론으로 돌아와서 클러스터를 생성했다면, 이제 Task 정의를 생성한다.

클러스터를 생성할 때 인프라를 Fargate로 생성했으니 시작 유형을 AWS Fargate로 설정한다.
태스크 크기는 CPU : 0.25vCPU, 메모리 : 0.5GB 으로 설정한다. (캡처와 다르니 참고)

컨테이너 이름은 sample로 지었다.
이미지 URI는 지난번 ECR에 등록된 이미지 URI를 복사해서 사용한다.
여기서 주의할 점이 있는데, 레포지토리 URI가 아닌 이미지 URI를 복사해야한다.
(그래야 sample:${version}까지 복사된다.)


다음, 포트 매핑에서는 컨테이너 포트를 7000으로 설정한다.
Docker File에서 Port를 7000으로 설정했기 때문에 여기서도 맞춰준다.

이후에는 기본 값으로 두고 작업을 생성한다.


서비스 생성

앞서 클러스터와 Task를 정의 한 것은 바로 서비스를 생성하기 위함이다.
이제 대망의 서비스를 올려보자!

생성한 ECS 클러스터를 클릭하면 서비스 생성이 가능하다.


컴퓨팅 옵션 : 시작 유형
시작 유형 : Fargate
플랫폼 버전 : LATEST



태스크 : 2 (Fargate 인스턴스가 2개 생성된다.)



네트워킹은 별도로 건들지 않았다.
로드밸런서 및 대상 그룹은 서비스를 생성하며 함께 생성해준다.


서비스가 정상적으로 생성되고 활성화가 되었다.

이제서야 비로소 개인 프로젝트가 모든 서버 인스턴스에 Docker를 통한 동일한 서비스 환경을 구축한 것이다.

아래 로드밸런서 DNS 이름의 주소를 가지고 웹에서 나의 프로젝트를 확인할 수 있다.

결과 화면


마무리하며

포스팅을 하면서 서버와 네트워크에 대해 점점 친숙해지는 기분이다.
사실 여기까지의 과정에서 우여곡절이 많았지만 시간이 걸려도 해내면 그만이다.

다음 포스팅에서는 Git을 통한 ECS 서비스 자동 생성을 구현해볼 예정이다.

글을 읽으시는 모든 분들께 알량한 나의 지식이 도움이 되었으면 한다.

AWS - ECR 레포지토리 생성

ECR 레포지토리를 생성해준다.

우선은 연습용으로 사용할 것이기 때문에 프라이빗으로 생성하고, 레포지토리 이름은 "sample"로 지정했다.

docker file 작성

(docker를 미리 설치해주세요 ^^)
이제 ECR 레포지토리를 생성했으니, 해당 레포에 도커 이미지를 등록하기 위해 dockerfile을 만들어준다.
(도커파일 만드는 방법)
(본인의 프로젝트에 맞게 작성하면 된다.)
이번 Next sample 프로젝트를 docker image로 만들기 위해 아래와 같이 작성한다.

FROM node:18-alpine

WORKDIR /app

COPY package.json ./

RUN npm install

#프로젝트의 모든 파일을 복사
COPY . .

RUN npm run build

#포트 7000번 사용
EXPOSE 7000

CMD ["npm", "run", "start"]

github workflow 수정

작성한 docker file을 기반으로 AWS-ECR에 docker image를 자동으로 push할 수 있도록 workflow.yml을 수정한다.

name: Staging # 워크플로 Action의 이름
on:
  push:
    branches: [main] #github main 브런치에 푸시 발생 시 실행 ( main 외 다른브런치 이용시 이름변경)
jobs:
  staging: #staging이라는 작업
    name: deploy to staging # 작업의 이름
    runs-on: ubuntu-latest # 실행될 작업환경을 말함.
    steps:
      - name: Checkout
        uses: actions/checkout@v3 #체크아웃 받기
      - name: HelloWorld
        uses: actions/hello-world-javascript-action@v1 # 헬로월드 찍어보기
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # Github Secret 이름
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # Github Secret 이름
          aws-region: ap-northeast-2 # AWS 리전 선택
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1
      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: sample # ecr 이름
          IMAGE_TAG: ${{ github.run_number }} # git 커밋넘버를 이미지 이름 구분을 위해 넣어줌
        run: |
          # Build a docker container and
          # push it to ECR so that it can
          # be deployed to ECS.
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"

name : Build, tag, and push image to Amazon ECR << 이 부분부터 추가했다.

Git Action / ECR Repository 확인

이제 작성한 docker file과 github workflow를 커밋 & 푸시하여 git action을 통한 docker image 자동 배포를 확인해볼 차례이다.

필자는 workflow의 run 부분을 잘못하여 좀 돌아왔지만 결국 성공했다.

AWS - ECR에도 정상적으로 Image가 push되었다.


마무리하며

이번 포스팅으로 ECR에 docker image를 자동 배포하는 과정을 알아보았다.
여기까지만 해도 기본적인 docker 및 AWS에 대한 지식이 필요하기 때문에 순탄치만은 않았던 것 같다.

다음 포스팅에서는 대망의 ECS 연동 및 자동배포를 다룰 예정이다. (제일 어려운 부분이 될 것 같다.)

화이팅…!!

이번에는 Git - AWS ECS 서비스를 연동해보고자 한다.
(AWS 계정이 필요하다.)


AWS - IAM 설정

AWS - IAM 페이지에서 사용자 생성을 진행한다.

그 다음 액세스 키를 발급한다.

AWS CLI 이용할 예정이기 때문에 아래와 같이 선택한다.

AccessKey를 발급 받으면

[AccessKey, SecretAccessKey]

두 개가 발급되는데, 어디다가 저장해두자.


Git repository - AccessKey 등록

이제 발급 받은 AccessKey와 SecretAccessKey를 Next 프로젝트 레포지토리에 등록해야 한다.

AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY 를 각각 등록해준다.


Next.js 프로젝트 workflow 수정

방금 추가한 Access, Secret 키를 프로젝트 내 github / workflow 파일에 추가해준다.
그래야 해당 키를 가지고 AWS와 연동할 수 있게 된다.

변경사항을 push하여 Git Action을 확인해보도록 하자.

현재는 AccessKey를 설정하는 단계에서 그쳤지만, workflow에 다른 AWS 서비스를 사용할 수 있도록 steps를 추가한다면, 해당 키가 잘 설정되어야만 오류 없이 배포가 된다.


IAM 권한 설정

이제 AWS로 프로젝트를 배포할 모든 서버에 동일한 환경을 구축하기 위해 Docker Image 생성 및 해당 Image의 Repository 역할을 하는 ECR 서비스를 사용할 예정이다.

그러나 해당 작업에 앞서 ECR과 같은 AWS 서비스를 바로 사용할 수는 없다.
우리는 앞선 과정에서 IAM 그룹 or 사용자를 생성하였고 각 서비스에 맞는 권한을 설정해주어야 한다.
필자는 그룹 단위로 권한을 부여하고, 해당 그룹에 속한 사용자들에게 동일한 권한을 부여해주는 방식으로 진행하려고 한다.

IAM 그룹에 권한 설정

그룹에 권한을 추가하려면 [사용자 그룹 - 권한 추가 - 정책 연결]
사용자별 권한을 추가하려면 [사용자 - 권한 추가 - 정책 연결]을 통해 권한을 추가할 수 있다.

필자는 아래와 같이 추가하였다.
아래 빨간 박스를 제외한 다른 권한들은 AWS에 이미 존재하는 권한들이고
빨간 박스는 별도로 추가해주었다.

ecs-cicd-demo-role 추가 방법 (이름은 마음대로 지어주세요)
[사용자 or 사용자 그룹 - 권한 추가 - 인라인 정책 생성 - 정책편집기 JSON] 선택 후 아래 JSON 붙여넣기

{
    "Version": "2012-10-17",
    "Statement":
    [
        {
            "Effect": "Allow",
            "Action":
            [
                "iam:PassRole"
            ],
            "Resource": "arn:aws:iam::*:role/ecsTaskExecutionRole"
        }
    ]
}

그 다음 정책의 이름을 설정해주면 끝이다.

결론적으로 추가한 정책들은 아래와 같다.

//ECR에 대한 모든 권한
AmazonEC2ContainerRegistryFullAccess

//ECS에 대한 모든 권한
AmazonECS_FullAccess

//ECR Public에 대한 모든 권한
AmazonElasticContainerRegistryPublicFullAccess

//S3에 대한 모든 권한
AmazonS3FullAccess

//ECS 클러스터로 애플리케이션 배포를 관리할 때 사용되는 권한
AWSCodeDeployRoleForECS

//AWSCodeDeployRoleForECS와 동일한 목적이지만 최소한의 권한만 부여
AWSCodeDeployRoleForECSLimited

//ECR 컨테이너 빌드를 위한 EC2 프로필을 나타내는 역할
EC2InstanceProfileForImageBuilderECRContainerBuilds

//ELB에 대한 모든 권한
ElasticLoadBalancingFullAccess

//ECS에서 실행 중인 Task에 대한 IAM 역할. 컨테이너 실행 및 관련 작업을 수행 - 별도로 직접 추가 필요
ecs-cicd-demo-role

ECR 관련 workflow 추가 및 배포 확인

이제 github workflow 하단에 ECR 로그인 관련 코드를 추가해준다.

name: Staging # 워크플로 Action의 이름
on:
  push:
    branches: [main] #github main 브런치에 푸시 발생 시 실행 ( main 외 다른브런치 이용시 이름변경)
jobs:
  staging: #staging이라는 작업
    name: deploy to staging # 작업의 이름
    runs-on: ubuntu-latest # 실행될 작업환경을 말함.
    steps:
      - name: Checkout
        uses: actions/checkout@v3 #체크아웃 받기
      - name: HelloWorld
        uses: actions/hello-world-javascript-action@v1 # 헬로월드 찍어보기
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # Github Secret 이름
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # Github Secret 이름
          aws-region: ap-northeast-1 # AWS 리전 선택
        #AWS - ECR
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

추가 성공!


정리

  1. AWS의 서비스들을 사용하기 위해서는 IAM 사용자 혹은 사용자 그룹을 생성한다.
  2. IAM 사용자 혹은 사용자 그룹에 AccessKey, SecretAccessKey를 발급 받아 github repository에 등록 및 workflow에 설정한다.
  3. 필요한 AWS 서비스를 사용하기 위해 그에 맞는 권한을 설정한다.
  4. AWS ECR 관련 workflow를 설정한다.

다음 포스팅에서는 본격적으로 ECR, ECS 서비스를 사용해볼 예정이다.
처음이라면 이 모든 과정이 쉽지 않겠지만 천천히 공부하다보면 언젠가는 될 것이라 믿는다.

Next.js 샘플 프로젝트를 Git Workflow / Action을 통해 AWS ECS로 자동 배포하는 시스템을 구축해보려 한다.


자동 배포 sequence

아래와 같은 순서를 거쳐 최종적으로 AWS ECS에 프로젝트가 자동 배포되는 과정을 경험해보고자 한다.

  1. Next.js 프로젝트 생성 및 배포
  2. Git workflow 작성
  3. AWS ECS 서비스에 연동

uml diagram

선행되어야 할 학습 내용

  • Next.js 설치 및 프로젝트 생성
  • Git / Github - workflow 설정과 Git Action
  • AWS
    • Route53 - 도메인 호스팅
    • EC2 - 클라우드 인스턴스
    • Load Balancer - 인스턴스에 접근할 트래픽 분산 처리
    • ECR - Docker Image의 저장소
    • ECS - ECR에 저장된 Docker Image를 기반으로 인스턴스를 생성하는 서비스
  • Docker - 배포한 시스템이 모든 환경에서 동일할 수 있도록 컨테이너라는 청사진 역할을 하는 시스템 구축 환경 제공

+ Recent posts