728x90
반응형
SMALL

참고자료

 

커리어 성장을 위한 최고의 실무교육 아카데미 | 패스트캠퍼스

성인 교육 서비스 기업, 패스트캠퍼스는 개인과 조직의 실질적인 '업(業)'의 성장을 돕고자 모든 종류의 교육 콘텐츠 서비스를 제공하는 대한민국 No. 1 교육 서비스 회사입니다.

fastcampus.co.kr

 

저번에는 Docker를 사용하지 않고 그냥 EC2에 서비스를 올려서 실행하는것까지 물론 DB도 있고 CloudFront도 있고 Route 53, VPC, Subnet, S3도 있고 이것저것 다 있었지만 Docker를 사용하지는 않았다. 이번에는 Docker와 연동해보자.

 

그래서 최종적으로 만들고자 하는 구조는 다음과 같다.

 

이전과 다른 부분은 ECSCluster, ECR 같은 개념이 새로이 도입됐다. 이것들이 뭔지 알아보자.

 

ECS란

 

Elastic Container Service의 약자로 컨테이너를 오케스트레이션 해주는 서비스이다. ECS를 사용하면 클러스터 구성이 가능하고 클러스터에서 컨테이너를 실행, 중지, 배포, 모니터링 등을 관리할 수 있다.

 

ECS Cluster에는 ECS Container instance(EC2라고 생각하면 된다)가 있는데 EC2 내부에 ECS Container Agent가 설치된 상태로 생성이 되고 이 EC2는 내부적으로 Auto Scaling Group으로 구성되어 있다. 저 Container instance안에 컨테이너들은 Task로 실행이 되고 Task Definition이라는 설정값에 의해 배포가 된다. 이 Task들은 서비스에 의해 생성이 되고 서비스는 ELB와 연동해서 외부에서 접근이 가능하도록 할 수 있다. 직접 만들어보면 이해가 빨리 된다. 이후에 직접 만들어보자.

 

 

ECS Cluster는 두 가지 형태로 구성이 가능하다.

  • Fargate Type: 인스턴스가 없는 서버리스 형태의 서비스. 실제 컨테이너에서 사용한 CPU와 메모리 사용량에 의해서만 과금이 된다. 
  • EC2 Type: 위 Container instance로 구성한 그림이 EC2 Type.

이 두개 중 하나를 선택하는 기준은 가격을 중심으로 두고 보면 되는데, Fargate Type이 기본 가격이 더 비싸지만 네트워크 트래픽이 일정하지 않고 들쭉날쭉한 서비스를 배포하고자 하는거라면 Fargate Type이 더 유리할 수 있다.

 

 

ECR이란

Elastic Container Registry의 약자로 쉽게 생각하면 Docker Hub(Registry)라고 생각하면 된다. Docker Image를 저장하고 관리하는 서비스이다. AWS IAM으로 리소스 기반 권한을 컨트롤할 수 있다는 장점이 있다. 외부에서 접근할 수 없는 프라이빗 레포지토리를 만들 수 있고 따라서 IAM 권한이 있는 지정된 사용자 또는 EC2 인스턴스가 컨테이너 레포지토리에 접근할 수 있도록 설정할 수 있다. AWS CLI를 사용해서 Docker Image의 Push, Pull, Tag와 같은 작업이 가능하다.

 

 

자자, 여기까지가 새로운 개념에 대한 설명이고 바로 저 아키텍쳐를 직접 구성해보자.

ECR 레포지토리 만들기

AWS Console에서 'ECR'을 검색한다. 화면과 같이 Elastic Container Registry를 클릭한다.

 

'Create repository'를 클릭해서 레포지토리를 하나 만들자.

Visibility는 프라이빗, Repository name은 적절하게 작성하고 그 외 모두 기본값으로 적용해서 만든다.

 

같은 방식으로 백엔드용 레포지토리를 하나 더 만들자. 그렇게 두 개를 만들면 다음과 같이 리스트에 두 개가 잘 보인다.

 

 

이제 이 레포지토리에 각각의 도커 이미지를 추가해보자. 

 

프론트 소스를 도커 이미지로 만들고 ECR에 추가

 

GitHub - chyoni/aws-frontend: AWS 배포용 Frontend

AWS 배포용 Frontend. Contribute to chyoni/aws-frontend development by creating an account on GitHub.

github.com

위 소스에 미리 만들어둔 Dockerfile이 있다. 이 파일을 이미지로 빌드하고 ECR에 넣어보자. 그러기 위해 ECR이 커맨드를 다 알려준다.

원하는 레포지토리에 들어가서 오른쪽 상단 'View push commands'를 클릭

 

그러면 이렇게 OS별 순서대로 해야할 것들을 알려준다.

 

Dockerfile이 있는 경로에서 1번부터 4번까지 차례대로 실행하자. 

참고로 이 명령어들을 실행하려면 Docker, Docker Engine, AWS CLI가 설치된 상태여야 한다. 이게 귀찮다면 Cloud9 이라는 AWS에서 제공하는 IDE 서비스를 사용해도 되는데 '굳이'라는 생각이 든다.

 

이렇게 4단계를 잘 끝마쳤으면 다음과 같이 이미지가 올라가 있는 모습을 확인할 수 있다.

 

 

백엔드 소스를 도커 이미지로 만들고 ECR에 추가

 

GitHub - chyoni/aws-backend: AWS 배포용 Backend

AWS 배포용 Backend. Contribute to chyoni/aws-backend development by creating an account on GitHub.

github.com

 

여기서 우선 Jar 파일을 만들어내자. (사실 이 Jar 파일 만들어내는 과정도 자동화 할 수 있다.)

mvn clean package

 

이 상태에서 시작하자. 아까랑 동일하게 ECR에 가서 원하는 레포지토리에 푸시하는 방법을 보여주는대로 실행하면 된다.

 

마찬가지로 잘 푸시된 모습이다.

 

 

이제 백엔드와 프론트엔드 각각에 대한 이미지가 만들어졌고 AWS ECR에 올라가 있기때문에 이 이미지들을 이용해서 ECS를 이용할 수 있게 됐다. 계속 진행해보자.

 

 

필요한 보안 그룹 생성 및 수정

우선, ECS 인스턴스도 보안 그룹이 필요하고 이 인스턴스들을 묶는 클러스터와 통신하는 ALB도 보안 그룹이 필요하다. 그래서 보안그룹을 만들자. 우선 ALB에 대한 보안 그룹 먼저.

 

ALB 보안그룹의 인바운드 규칙은 80443에 대해서 모든 IP로부터 열어둔다.

 

 

이 다음은 ECS Instance 보안 그룹.

 

이름과 설명은 적절하게 입력을 하고 VPC는 이제 말하기도 귀찮다. 항상 사용하는 VPC. 그리고 인바운드 규칙을 좀 유심히 봐야한다. 얘는 ALB가 들어올 수 있게 해줘야 하는데 그 때 포트는 전체(All TCP)로 열어둔다. 그 이유는 ECS를 동적 포트 할당으로 그 때 그 때 달라지기 때문이다.

 

 

그 다음은 RDS 보안 그룹에 대한 수정이다.

이건 뭐냐면 데이터베이스를 사용하는데 이 RDS는 기존에 사용했던 것 그대로 사용을 할거다. 근데 지금 만든 ECS Instance가 접근하는 것에 대한 허용은 안 해놓은 상태니까 그 허용이 필요하다. 

 

기존에 사용하던 RDS 보안 그룹에서 인바운드 규칙 수정을 누른다.

 

MySQL로의 접근에 대한 허용을 방금 만든 ECS 보안 그룹 추가해주기.

여기까지하면 일단 필요한 보안 그룹 작업은 끝났다.

 

 

ALB 생성

이제 로드밸런서를 만들어보자.

EC2 > Load Balancing > Load Balancers

 

타입은 ALB로 정한다.

 

Basic configuration에서는 Name을 설정한다. 그 외는 기본값.

Network mapping은 항상 하던 그대로 설정한다.

 

Security groups는 앞전에 만든 ECS-ALB용으로 선택한다.

 

Listeners and routing은 HTTP:80에 적용할건 맞는데 대상 그룹을 생성하지 않았기 때문에, 대상 그룹 생성 링크를 눌러 생성하자.

 

대상 그룹 생성 화면이다. 인스턴스 타입으로 선택하고, 대상 그룹 이름을 지정한다음 HTTP:80으로 설정.

 

그 외 모든 값은 기본값으로 설정한다. VPC는 이미 내가 만든 VPC로 선택되어 있다. 

 

대상 등록 화면에서는 아무런 대상도 선택하지 않고 대상 그룹만 만든다.

 

그 다음 백엔드용 대상 그룹도 만들어야 한다.

이렇게만 변경사항을 적용하고 이 또한 대상 등록을 하지 않고 만든다.

 

이제 다시 로드밸런서를 만드는 화면으로 다시 돌아와서 다음과 같이 적용한다. 프론트엔드는 HTTP:80, 백엔드는 HTTPS:443으로 적용한다. 

 

Security policy는 다음과 같이 적용한다.

Security category는 All security policies, Policy name은 기본값, ACM의 만든 도메인을 적용.

 

그리고 로드밸런서를 최종적으로 생성한다. 최종적으로 생성하면 다음과 같이 로드밸런서 하나가 추가된다.

 

만든 로드밸런서에 들어가서 HTTP:80 규칙을 수정한다. 수정 내용은 80으로 들어오면 443으로 리다이렉션한다.

 

이번엔 HTTPS:443을 수정한다. 443으로 들어오면 80 대상 그룹(프론트엔드 대상 그룹)으로 전달한다.

 

그 다음, 443은 규칙 하나를 추가한다. 백엔드 도메인으로 들어왔을 때 8080 대상 그룹(백엔드 대상 그룹)으로 보내는 것을 추가.

 

이렇게 규칙을 만들면 된다. 이제 로드밸런서는 다 끝났고, Route 53에서 이 로드밸런서로 레코드를 추가와 변경하자. (기존에 만들었던 소규모 아키텍쳐에서 이미 사용했기 때문에 이 ECS용으로 변경해줘야 한다).

 

우선, "api.cwchoiit.net"에 대한 레코드를 ECS ALB로 변경한다.

 

그 다음, 레코드 하나를 다음과 같이 추가한다. "ecs.cwchoiit.net"으로 진입하면 방금 만든 로드밸런서인 ECS-ALB로 적용.

 

이 두가지 작업을 해주면 다음과 같이 ECS-ALB로 잘 적용됐는지 확인하자.

 

 

ECS 클러스터 생성

이제 클러스터를 만들어보자. 우선 처음보는 개념이기 때문에 천천히 하나씩 해보자.

AWS Console에서 Elastic Container Service 또는 ECS를 검색한다. 검색해서 나오는 서비스를 클릭

 

좌측 'Clusters'를 클릭해서 Create cluster를 선택한다.

 

1. 클러스터 이름과 설명을 작성한다.

 

2. 인프라를 구성한다. 

우선 Fargate이 아닌 EC2 Instance 유형의 클러스터를 만든다. 그리고 내부적으로 Auto Scaling Group으로 동작한다고 했던것을 기억하는가? 그래서 Auto Scaling Group을 선택하는데 기존에 있는것으로 선택하거나 따로 준비한게 없다면 새로 만드는 옵션을 선택한다.

On-demand는 과금 방식을 말하는 것이고 이미지는 Amazon Linux 2023, 인스턴스 타입은 c5.large 선택, Desired capacity최소 최대 모두 2개, 키페어는 항상 사용하던 키페어로 선택하고, EBS 볼륨 사이즈는 기본값으로 설정한다.

 

3. Network를 구성한다.

VPC는 항상 사용하던 VPC를 선택하고, 서브넷은 Private App A, C를 선택 Security group은 위에서 만든 ECS용 보안 그룹을 선택한다. 

 

4. Tag를 구성한다.

 

이 상태로 클러스터를 생성한다. 생성하고 나면 다음과 같이 클러스터가 리스트에 노출된다.

 

이제 이 클러스터가 사용할 서비스와 테스크를 만들어야 하는데 만들려면 테스크 정의가 필요하다. 그래서 테스크 정의를 만들어보자.

ECS > Task definitions 에서 'Create new task definition' 클릭

 

Task Definition (Frontend 용/Backend 용)

1. 우선 Task definition family는 다음과 같이 읽기 편하게 작성한다.

 

2. Infrastructure는 Launch type을 Amazon EC2 Instances, OS는 Linux, Network mode는 bridge, CPU는 할당하지 않고, Memory는 1GB, Task role은 없음에 Task execution role은 새로운 롤을 만드는 것으로 선택한다.

 

3. Container 정보를 입력한다.

컨테이너 이름을 입력하고 Image URI는 ECR에 올려놓은 이미지의 URI를 가져온다. Host port 0이 의미하는건 동적 할당이다. Container port는 80으로 할당했다. 왜냐하면 프론트니까. 그 외 나머지는 기본값으로 설정한다. 그리고 하단에 여러 옵션들이 있는데 아무것도 하지 않는다 왜냐하면 지금은 필요가 없으니까.

 

이 상태로 Task definition을 생성한다. 즉, Task definition은 결국 Docker Container를 생성하기 위한 정보들을 입력한 메타데이터라고 보면 된다. 그리고 그 정의들로 Task가 만들어지는 것.

 

같은 맥락으로 한 개의 Task definition이 더 필요하겠지? 프론트랑 백엔드니까 백엔드를 만들어줘야 한다.

백엔드는 메모리를 2GB로 설정했다.

백엔드용 이미지 URI를 붙여넣고, 컨테이너 포트는 8080이다. 나머지는 위 프론트용과 동일하다. 

 

두개가 잘 만들어졌는지 리스트에서 확인.

 

 

클러스터의 서비스 만들기

Cluster도 만들고 Task definition도 만들었다. 이제 클러스터의 서비스까지 만들어보자.

내가 만든 클러스터로 들어가면 하단에 Service 탭이 있다. 여기서 Create 클릭

 

프론트엔드의 서비스부터 생성해보자.

 

프론트엔드 서비스 만들기

생성 화면의 첫 부분인 Environment는 다음과 같이 설정한다.

- Compute options: Launch type

- Launch type: EC2

 

그 다음 Deployment configuration 설정 부분은 다음과 같다.

- Application type: Service

- Family: 이전에 만든 Frontend용 Task definition

- Service name: frontend

- Service type: Replica

- Desire tasks: 2

 

그 다음 Load balancing 설정이다.

- Load balancer type: ALB

- Load balancer: cwchoiit-ecs-alb

- Container: frontend 80:80

- Listener: 443:HTTPS

- Target group: cwchoiit-ecs-frontend-80

 

이렇게 하고 그 외 값은 기본값 세팅으로 설정해서 만든다. 그렇게 만들면 좀 기다려서 다음과 같은 서비스를 볼 수 있다.

 

그렇게 서비스가 잘 올라오면 이 서비스에 해당하는 프론트엔드 URI(ecs.cwchoiit.net)으로 들어가보자. 우리의 프론트엔드 소스가 잘 보이는 것을 확인할 수 있다. 

 

이제 백엔드 서비스를 띄워야 한다. 그래야 완성된 전체 서비스를 이용할 수 있으니까. 이제 백엔드 서비스를 클러스터에서 만들어보자.

 

백엔드 서비스 만들기

백엔드 서비스도 위 프론트엔드 서비스와 거의 동일하다. 그러니까 다른 부분만 확인해보자.

 

Task definition이 당연히 달라진다. 백엔드용 Task definition을 선택하자.

 

컨테이너는 백엔드용으로 만든 컨테이너를 사용해야 한다.

대상 그룹은 백엔드용 대상 그룹을 선택하고 그 외 나머지는 기본값으로 생성하기를 누르자.

 

 

근데 이렇게 위에서 쭉 따라오면 다음과 같은 에러를 마주할것이다.

무슨 에러냐면 지금 새로 만드려는 서비스의 Task Definition으로 만든 컨테이너는 포트가 동적할당으로 되어 있는데 로드밸런서 설정에서 컨테이너에 대한 대상 그룹을 우리가 직접 지정했다 백엔드용 대상 그룹으로. 지정하는것 까지는 맞는데 지정한 대상 그룹의 Health check 포트가 동적할당이 아닌 고정값으로 설정했다. 위에서 보면 Override port해서 8080으로 지정을 했단 말이지. 그래서 8080이 아니면 Health check가 불가능한데 지금 띄우는 컨테이너가 동적 포트 할당이라 서비스를 생성할 수 없다는 에러다.

 

그래서 만든 백엔드용 대상 그룹의 Health check 부분을 다음과 같이 수정한다.

 

이렇게 대상 그룹을 수정해주고 다시 서비스를 만들자. 다시 만들면 다음과 같이 정상적으로 서비스가 만들어졌다.

 

그럼, DB가 붙었기 때문에 프론트에서 데이터를 생성하면 정상 생성이 되어야 한다. 테스트해보자. 다음과 같이 Employee를 추가하고 'Save'를 누르면 리스트에 방금 생성한 Employee가 잘 노출된다.

 

 

중간 정리

이제 클러스터를 이용해서 백엔드, 프론트엔드 서비스를 같이 올릴 수 있는 상태가 됐고 그 각각의 서비스는 ECR(Elastic Container Registry)에 등록한 도커 이미지를 통해서 서비스를 빌드하고 띄울 수 있게 됐다.

 

 

CloudFront를 클러스터에 연결

이제 CloudFront를 클러스터에 연결해서 앞 단에서 CloudFront로 요청과 응답을 처리해보자.

 

CloudFront로 가서 새로 하나 만들어보자.

 

Origin 부분에서 변경할 부분은 다음밖에 없다.

- Origin domain: ECS용으로 만든 Load Balancer

 

Default cache behavior는 이 부분만 수정하면 된다.

- Viewer protocol policy: Redirect HTTP to HTTPS

- Cache policy: CachingOptimized

 

Settings 부분은 다음을 수정하자.

- CNAME: ecs.cwchoiit.net

- Custom SSL certificate: cwchoiit.net

 

이렇게 적용하고 CloudFront를 배포하자. 배포가 진행되는 동안 이제 로드밸런서가 이 CloudFront와 통신해야 하므로 로드밸런서의 리스너 규칙을 수정해보자. ECS용 로드밸런서를 찾아 들어가보면 다음과 같이 HTTP:80에 대한 규칙이 있다.

 

저 기본 규칙은 443으로 리다이렉션하는데 이를 대상 그룹 80으로 변경하자. 어차피 CloudFront가 HTTP로 들어오면 HTTPS로 변환해주고 변환해서 들어오는 이 로드밸런서 안은 HTTP만 관심 대상으로 두면 된다.

 

HTTP:80에 대한 규칙을 하나 더 추가할건데 이제 호스트 헤더가 ecs.cwchoiit.net인 경우 80 대상 그룹으로 포워딩 하는 것도 추가하자.

 

이렇게 로드밸런서의 리스너 규칙도 다 변경 및 수정이 끝났고 CloudFront 배포도 정상 처리됐음을 확인했다.

 

 

ALB로 연결되어 있던 Route 53 레코드를 CloudFront로 연결 바꾸기

Route 53으로 들어가서 우리 도메인의 레코드로 ecs.cwchoiit.net을 만들었다. 근데 이 레코드가 연결된 건 방금 만든 CloudFront가 아니라 ALB로 연결된 상태이기 때문에 CloudFront로 변경해주자.

 

Route 53 > Hosted zones > 만든 도메인 내 레코드 편집 

 

변경 후 한번 다시 ecs.cwchoiit.net으로 들어가서 우리 서비스가 정상 응답하는지 확인해보자. 아래처럼 잘 응답하고 있다. 

 

 

응답을 한것만 확인하지 말고 이게 CloudFront로 부터 Hit된 것인지 확인해보자. CloudFront가 잘 동작하고 있다.

 

728x90
반응형
LIST

+ Recent posts