ECS 를 여행하는 히치하이커를 위한 안내서 2.

ISAAC LEE·2023년 4월 30일
0

안녕하세요 오늘은 AWS ECR 을 만들어서 Repository 에 도커 이미지를 배포하고 로드밸런서 -> 타겟 그룹 -> EC2 로 트래픽이 들어오는 형태의 애플리케이션을 기반으로 하는 ECS 클러스터를 만드는 부분을 해보겠습니다. 아래와 같은 준비물이 필요합니다.

  1. AWS 계정
  2. 헬스체크 기능이 존재하는 간단한 서버 애플리케이션
  3. AWS CLI v2

시작합니다!

간단한 NodeJS Express 앱과 Dockerfile 구성

const createError = require('http-errors');
const express = require('express');
const logger = require('morgan');

const http = require("http");

const app = express();

app.use(logger('dev'));

app.get("/health", (req, res, next) => {
  return res.send("hello world!");
});

app.use((req, res, next) => {
  next(createError(500));
});

const server = http.createServer(app);

server.listen(3000);
server.on('listening', () => {
  console.log("server start!");
});
FROM arm64v8/node:16-alpine

EXPOSE 3000

WORKDIR /app

COPY .package.json .
COPY .package-lock.json .
RUN npm ci --omit=dev

COPY .app.js .

CMD ["sh", "-c", "node ./app.js"]

ECR 레포지토리 만들어보기

이번에는 ECR 레포지토리를 만들어보겠습니다. AWS Console 좌측 상단에 Elastic Container Registry 를 검색 후 좌측 탭에 보시면 Repositories 로 접근하셔서 Repository 를 만들어주시면 됩니다.

IAM 정책과 사용자를 만들기

AWS CLIv2 로 ECR 이미지 업로드를 진행하기 위해서 관련 IAM 정책과 사용자를 만들어줍니다. IAM > 정책에서 생성 버튼을 눌러 JSON 으로 정책을 생성해주시면 됩니다. REGION, ACCOUNT_ID, REGISTRY_NAME 은 사용하실 리전, AWS ACCOUNT ID, Registry 이름에 맞게 바꿔주시면 됩니다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:BatchGetImage",
        "ecr:BatchCheckLayerAvailability",
        "ecr:CompleteLayerUpload",
        "ecr:DescribeImages",
        "ecr:DescribeRepositories",
        "ecr:GetDownloadUrlForLayer",
        "ecr:InitiateLayerUpload",
        "ecr:ListImages",
        "ecr:PutImage",
        "ecr:UploadLayerPart"
      ],
      "Resource": "arn:aws:ecr:${REGION}:${ACCOUNT_ID}:repository/{$REGISTRY_NAME}"
    },
    {
      "Effect": "Allow",
      "Action": "ecr:GetAuthorizationToken",
      "Resource": "*"
    }
  ]
}

AWS Profile 등록

IAM 사용자를 만들면서 위에서 만든 정책을 추가하고 사용자가 만들어진 후에 받을 수 있는 AccessKey, SecretKey 를 받아서 aws profile 을 등록해줍니다.

aws configure --profile ${PROFILE_NAME}

ECR에 이미지를 업로드

이제 위에서 만들었던 ECR Repository 에 AWS CLI 를 이용하여 이미지를 업로드 하겠습니다.

#Docker Image Build
docker build -t ${IMAGE_NAME} .

#Tagging Image
docker tag ${IMAGE_NAME}:latest ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/${IMAGE_NAME}

#ECR Login
aws ecr get-login-password --region ${REGION} --profile ${PROFILE_NAME} | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com

#Image Push
docker push ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/${IMAGE_NAME}

TA-DA! 이미지가 잘 업로드 된 것을 확인할 수 있습니다.

Security Group 만들기

이제 로드밸런서와 실제로 컨테이너가 구동될 EC2 서버에서 사용할 Security Group 을 만들어보겠습니다. VPC -> 보안그룹 탭에서 보안 그룹 생성을 눌러서 보안 그룹을 작성해줍니다. 먼저 로드밸런서의 보안그룹을 먼저 만들어보겠습니다. ALB 는 public subnet 에서의 http 요청을 받아야 하기 때문에 아래와 같이 설정해주겠습니다.

EC2 는 private subnet 에 존재하여 로드밸런서로부터 들어오는 요청만을 수신하면 되기 때문에 인바운드에 모든 TCP 에 로드밸런서가 가지고 있는 보안그룹을 넣어주면 됩니다.

ECS Cluster 만들기

이제 ECS Cluster 를 만들어보겠습니다. Elastic Container Service -> 클러스터 생성을 누르면 아래와 같은 화면이 보입니다. 이름의 경우 저는 {팀명}-{환경}-{제품명}-{AWS 리소스명} (ex: pension-dev-api-cluster) 이렇게 만들고 있어요. 회사마다 다른 것 같더라구요. VPC 는 사용하실 VPC 를 선택하시면 됩니다. 만약 관련 지식이 전무하시다면 public subnet 과 private subnet, 그리고 NAT 가 어떻게 엮여있는지를 알아내서 AWS VPC 상에 내가 간단하게라도 만들어볼 수 있다면 문제없을 것 같습니다

다음은 인프라 구성입니다. EC2 를 사용할건지, Fargate 를 사용할건지 선택할 수 있습니다. Fargate 예제는 너무나도 많기 때문에 저는 EC2 기반 ASG(Auto Scaling Group) 으로 진행하겠습니다.

ECS Task 만들기

자 이제 Cluster 가 만들어졌으니 Cluster 에서 실행할 수 있는 가장 작은 단위인 Task 를 만들어보겠습니다. 태스크 정의 탭에 접근하셔서 태스크 정의 생성을 하시면 아래와 같은 화면이 보입니다. Task 의 이름도 Cluster 와 비슷한 형태로 만들어주면 됩니다.. 컨테이너의 이미지 URI 는 위에서 만든 ECR Repository 의 주소를 적어주면 됩니다. 컨테이너 포트의 경우 우리의 Express 애플리케이션은 3000번 포트를 사용하니 3000 으로 적어주시면 됩니다.

또한 아래와 같이 NodeJS 기반 서버에서 많이 사용되는 NODE_ENV 값을 컨테이너가 실행될 때 아래와 같이 주입해줄 수 있습니다.

다음 페이지에서는 실행될 컨테이너의 환경, 스토리지, 모니터링, 태그 구성을 할 수 있습니다. 우리는 EC2 ASG 를 기반으로 작동하기 때문에 EC2 인스턴스를 선택, 운영체제/아키텍처는 EC2 의 설정을 따라가면 됩니다. 태스크 크기는 실행 중인 EC2 의 CPU, Memory 를 초과하지 않는 범위에서 설정해주셔야 합니다. 아래에 보시면 모니터링 탭에서 CloudWatch 로그 설정을 할 수 있는데 이 경우 컨테이너 내부에서 출력되는 로그를 CloudWatch 에서 볼 수 있습니다.

Target Group, ALB 만들기

이제 Target Group 와 로드밸런서를 만들어보겠습니다. 이 2가지는 Service 를 만들 때 정의할 수도 있지만 저는 따로 만들어보겠습니다. Target Type 은 Instance 로 설정해주시고 위에서 Cluster 를 만들 때 사용한 VPC 를 설정해주시면 됩니다.

위에서 만든 Health Check API 의 경로를 적어주시면 됩니다. 우리의 Target Group 은 이제 해당 API 를 통해 앱의 동작 여부를 확인하고 컨테이너를 다시 시작할 건지 판단합니다.

로드밸런서는 좌측 Target Group(대상 그룹) 위에 보시면 바로 있습니다. Application Load Balancer (ALB) 선택 이름만 작성하고 넘어갑니다.
아래 탭에서는 위에서 사용했던 VPC 와 Subnet 의 가용 영역을 체크하여 집어넣습니다.
보안 그룹에는 위에서 로드밸런서 용도로 만들었던 보안그룹을 적용해줍니다.
리스너에는 http 요청을 받아들일 80번 포트를 등록하시고 위에서 만든 Target Group 으로 Forward 하도록 설정해주시면 됩니다. (보통은 http 사용을 안하고 https 를 사용하니 443 을 열고 ACM 에서 인증서를 발급받아 443 리스너를 등록하시고 80은 443 으로 리다이렉트 하도록 등록하시면 됩니다.)
이제 Target Group 에 정상적으로 로드밸런서가 붙은 것을 확인할 수 있습니다.

ECS Service 만들기

마지막으로 ECS Service 를 만들어보겠습니다. 우리는 Cluster 를 만들 때 ASG 를 이용한 용량 공급자를 선택했기 때문에 용량 공급자 전략으로 갑니다. 애플리케이션 유형은 서비스, 태스크 정의는 아까 만든 Task 를 넣어주고 서비스 이름을 작성합니다. 원하는 태스크의 경우 Cluster 내부에서 해당 Task 를 몇 개나 띄울 것인지를 설정합니다.
위에서 만든 로드밸런서와 Target Group 을 선택해주고 생성하면 됩니다.
여기까지 문제없이 됐다면 CloudWatch 에서 잘 돌고 있는 서버를 확인하실 수 있습니다.

이렇게 간단한 애플리케이션을 가지고 ECS Cluster 를 구성해보았습니다. 이 상태로 실제 서비스를 하기에는 여러모로 문제가 있지만요.. 다음 게시글에서는 ECS 배포에 대한 글을 가지고 돌아오겠습니다!

profile
안녕하세요. 개발하면서 배웠던 것을 블로그에 작성하고 있습니다. 잘못된 정보의 지적을 환영합니다.

0개의 댓글