[AWS] ECS란?

01. Micro Service Architecture 와 Container

01-01. Micro Service Architecture

[이미지 출처]  https://revdebug.com/blog/microservices-vs-monolithic-architecture/

ECS를 알아보기 전에 ECS의 사용 배경이 되는 마이크로 서비스 아키텍처와 컨테이너에 대해 알아보겠습니다.

마이크로 서비스 아키텍처는 전통적인 방식이었던 하나의 거대한 아키텍처인 ‘Monolithic’ 아키텍처를 도메인, 기능 등에 따라 쪼개어 모듈화, 캡슐화를 시킨 아키텍처입니다.

마이크로 아키텍처의 장점은 각 서비스에 대한 독립성을 가지고 기획, 개발 운영을 가능하게 합니다. 따라서 다른 서비스에 대한 의존성 없이 빠르게 개발할 수 있습니다. 또한 병목의 위험성을 감소시킵니다.

01-02. Container

[이미지 출처] https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/

위에서 설명한 마이크로 서비스 아키텍처를 실현하기 위해서는 벤더에 종속적이지 않으며, 개발자가 손쉽게 운영 및 접근할 수 있는 기술이 필요합니다. 이러한 인프라 관리 기술의 중심이 되는 기술이 컨테이너입니다.

위의 사진을 참고해 가상 머신과 컨테이너를 비교해 보면, 가상머신은 호스트 운영체제 위에 Hypervisor라고 하는 가상화 소프트웨어를 이용하여 여러 개의 게스트 운영체제(Ubuntu, CentOS 등)를 구동하는 방식을 가지고 있습니다. 이때 쓰이는 hypervisor는 가상 머신을 생성하고 실행하는 역할, 가상화된 하드웨어와 각 가상 머신을 모니터링하는 중간 관리자 역할을 합니다

반면에 컨테이너는 물리적인 공간의 격리가 아닌 프로세스 격리를 통해서 이미지를 실행하고 서비스할 수 있는 컨테이너 기술입니다. 컨테이너 엔진은 호스트 운영체제의 커널을 공유하고 그 위에서 실행파일(Bins) 및 라이브러리, 기타 구성 파일 등을 이미지로 빌드 하여 패키지로 배포합니다.

이런 컨테이너를 관리하고 동작시키는 여러 기술 중에 Docker에 대해 알아보겠습니다.


02. Docker

[이미지 출처] https://www.docker.com/company/newsroom/media-resources/

Docker는 어플리케이션 프로세스를 독립적으로 실행시킬 수 있는 리눅스 컨테이너 환경입니다. 

기존의 가상머신 환경과 도커 환경을 비교해 보면 도커 환경에서 Docker Engine이 Hypervisor 와 Guest Os 가 필요 없게 만들어주어 더 가볍고 빠른 서비스가 가능하게 합니다.

[이미지 출처] https://devanshdhrafani.github.io/blog/2021/04/15/dockerros2.html

Dockerfile은 컨테이너에 설치해야하는 패키지, 소스코드, 명령어, 환경변수설정 등을 기록한 스크립트 파일입니다.
이렇게 만든 Dockerfile을 build 하면 도커 이미지가 됩니다. 
도커 이미지를 Run 하면 이미지가 실행되어 하나의 애플리케이션으로 서비스를 하는 컨테이너가 생성됩니다. 

[이미지 출처] https://www.itzgeek.com/how-tos/linux/working-with-docker-images-building-docker-images.html

도커파일을 통해 생성된 도커이미지는 push 명령어를 통해 Docker Registry 보관할 수 있으며, pull 명령어를 통해 Registry 저장된 도커 이미지를 로컬 도커 컨테이너에 가지고 올수 있습니다. 

이런 기능을 하는 AWS 서비스 중에는 ECR이 있습니다.


03. ECS

03-01. ECS란?

ECS 란 컨테이너의 생성과 종료, 자동 배치 및 복제, 로드 밸런싱, 클러스터링, 장애 복구, 스케줄링 등의 역할을 수행해 주는 오케스트레이선 도구입니다.

[이미지 출처] https://aws.amazon.com/ko/ecs/

ECS의 워크 플로우를 살펴보면 위의 사진과 같습니다.

Container registry에 저장된 도커 이미지를 가져옵니다. 그 후 ECS에서 이미지를 실행하여 컨테이너를 생성하는데 그때, 리소스와 Compute Option을 설정합니다. 이는 도커 이미지를 run 할 때 명령어로 옵션을 설정하는 것과 같습니다.

ECS는 이렇게 실행한 컨테이너들과 그 집합인 클러스터를 관리하는 역할을 합니다.

이때 사용하는 컨테이너 저장소는 Docker hub를 써도 연결이 가능하지만 Amazon ECR은 AWS IAM 인증을 통해 이미지 push/pull에 대한 권한 관리가 가능하여 보안상 좋고, S3에 저장되기 때문에 고가용성 유지되며 다른 AWS 서비스들과 편리하게 연결 가능하다는 장점이 있습니다.

03-02. ECS 구성 및 작동 방식

ECS에서는 컨테이너를 올리는 서버, 컨테이너를 어디에 호스팅 할 건지 정할 수 있는데 서버리스 방식인 Fargate 위에 올릴 수도 있고, EC2에 올릴 수도 있습니다.

서버리스 방식인 Fargate는 아마존에서 많은 부분을 관리해 주어 유연성은 좀 떨어지지만, AWS에 많은 부분을 맡길 수 있는 AWS 매니지드 서비스이므로 운영하기에 매우 편리합니다. 따라서 AWS나 도커 운영에 대해 잘 모르는 사용자도 사용하기 편리합니다. 

EC2는 사용자가 커스터마이징 할 수 있는 부분이 많고 비용도 저렴하나 관리에 손이 많이 가기 때문에 어느 정도 컨테이너와 AWS를 다룰 수있는 사용자가 사용하여야 합니다. 

ECS의 구성에는 Task Definition, Task, Service, Cluster가 있습니다.

  • Task Definition: 컨테이너를 실행하기 위해 정의한 설정입니다.
  • Task : Task Definition에 의해 배포된 컨테이너 Set입니다.
  • Service: 클러스터에 Task를 몇 개나 배포할 것인지 결정하고 ELB와 연결하거나 Auto Scaling을 설정하는 등 Task의 LifeCycle을 관리합니다.
  • Cluster: Task가 배포되는 환경들이 논리적으로 그룹화되는 단위를 의미합니다.


04. ECS 실습

04-01. 실습 구성

  • Dockerfile을 AWS CodeCommit에 올립니다.
  • ECR을 이용해 CodeCommit에 올린 Dockerfile을 build 하여 Docker Image를 저장합니다.
  • ECS를 이용해 Docker Image를 실행시킵니다.

04-02. CodeCommit에 file 업로드

Dockerfile
nginx.conf

Dockerfile에서 참고하는 nginx 환겅설정 파일입니다.
index.html파일에 한글을 넣을 경우 꺠지는 현상을 방지하기 위한 작업입니다.

04-03. ECR Repository

ECR Repository 생성

CodeCommit에 업로드 한 Dockerfile을 ECR에 build 하기 위한 Repository를 생성하는 작업입니다.
이렇게 생성된 ECR Repository는 URI가 지정되며 이것을 통해 동작하게 됩니다.

04-04. Docker Image build & push

CodeCommit에 파일을 업로드하고 ECR Repository를 생성하였다면, CodeCommit에 있는 Dockerfile을 이용하여 ECR에 build 하는 작업을 해보겠습니다.

로컬에서 CodeCommit을 Clone 한 후 Docker 명령을 통해 Amazon ECR을 사용할 수 있도록 인증 작업을 해줍니다.
인증 성공 후 Docker Image를 빌드 해보면 Dockerfile에서 설정한 대로 build작업이 이루어지는 것을 확인할 수 있습니다.

그렇게 생성된 이미지에 태그를 지정하고 ECR에 push 합니다.

ECR Repository에 들어가 확인해 보면 지정한 Image tag로 push가 정상적으로 된 것을 확인할 수 있습니다.

04-05. 컨테이너 실행

컨테이너를 실행하기 위해서는 위에서 설명드린 ECS의 4가지의 구성 과정을 진행해야 합니다.

클러스터 생성

Docker 이미지를 읽어 올릴 Cluster를 생성합니다.
이 과정은 어떤 환경 리소스 위에 컨테이너를 올릴지 설정하는 과정으로 Cluster, VPC, 서브넷, 등의 리소스를 설정합니다.

앞서 설정한 것들은 CloudFormation Stack을 통해 생성되므로 매우 간편하고 쉽습니다.

Task Definition

작업 정의를 생성하면 Fargate, EC2, EXTERNAL(외부 온 프레미스) 중 Task를 올릴 유형을 선택할 수 있습니다.

다음으로 컨테이너 추가를 해줍니다. 이 과정은 어떤 이미지로 어떤 컨테이너를 생성할 것인지를 설정하는 단계입니다.

이미지에는 아까 ECR에 저장한 이미지 URI를 넣어주며 포트 매핑은  클러스터 만들 때 선택한 보안 그룹에 따라 호스트 포트 80, 도커 파일에서 설정한 컨테이너 포트 80을 입력해 줍니다.

Service

작업 정의가 잘 만들어졌다면 그것을 기반으로 한 서비스를 생성해 줍니다.

서비스 생성은 앞서 생성한 작업 정의를 통해 Image를 실행시켜 컨테이너를 생성해 주는 단계입니다.
여러 개의 Task가 있다면 ELB와 AutoScaling 등의 추가 작업도 할 수 있습니다.

Service 생성까지 완료하면 클러스터에 하나의 서비스가 하나의 인스턴스에서 실행 중인 것을 확인할 수 있습니다.

해당 EC2의 Public IP를 통해 접속하면 컨테이너 서비스가 잘 실행되고 있는 것과 html.index 파일에 넣었던 문구를 확인할 수 있습니다.