[AWS] ECS 서비스란?

[AWS] ECS 서비스란?

안녕하세요? 정리하는 개발자 워니즈 입니다. 이번시간에는 아마존에서 제공하는 서비스중 하나인 ECS에 대해서 정리를 해보려고 합니다. 기존에 EC2 인스턴스 내에서 도커를 설치하고 컨테이너를 생성해보는것을 해봤는데요. 기존에 SWARM이라던지, 쿠버네티스와 같은 서비스는 없을까 하고 알아보던중에 아마존에서 제공해주는 서비스가 있다는 것을 알게 되었습니다. ECS 는 elastic container service의 약자로 클러스터를 구성해주고 컨테이너를 생성해주고 관리해주는 역할을 합니다.

1. 클러스터의 개념

ECS의 가장 기본적인 단위는 클러스터입니다. 클러스터는 도커 컨테이너를 실행할 수 있는 가상의 공간입니다. 클러스터를 잘 구분해주는 것이 중요한데, 보통 프로젝트 단위나 업무(service) 단위로 구분지어 생성합니다.

2. Task Definition

ECS 에서 컨테이너를 실행하는 최소 단위를 태스크 라고 합니다. 태스크는 하나 이상의 컨테이너로 구성이 됩니다. 여러 컨테이너의 조합으로 하나의 태스크를 생성 할 수 있스니다. 태스크를 실행하려면 태스크 디피니션이 필요합니다. 네트워크 모드, 태스크 역할, 도커 이미지, 실행 명령어, CPU 제한, 메모리 제한 등 다수의 설정이 필요합니다. 컨테이너를 오케스트레이션을 사용하는 가장큰 이유중 하나는 컨테이너의 생명주기를 스스로 관리하게끔 하는 것입니다. 이러한 설정들의 정의를 미리 작성해두어, 나중에 이 정의를 기반으로 태스크를 실행합니다.

3. 서비스

태스크를 실행하는 방식은 다음 두가지 입니다.

  • 태스크 디피니션을 통한 태스크 실행
  • 서비스 정의

서비스는 하나의 태스크 디피니션(리비전)과 연결됩니다. 서비스 타입은 다시 다음 두가지 방식으로 나뉘어 집니다.

  • 데몬타입
  • 리플리카 타입

데몬타입 같은 경우는 각 인스턴스 별로 1개의 컨테이너가 생성이 되고, 리플리카 같은 경우는 태스크의 개수를 지정하여 클러스터에서 이 개수만큼 태스크가 실행되도록 자동적으로 관리를 해줍니다.

서비스는 ECS 클러스터 내에서 작업을 스케쥴링 해주는 역할을 합니다. EC2와 같은 컴퓨팅 자원을 직접 사용해서 프로세스를 배치하는 경우 서버 운영자가 직접 어떤 인스턴스에 어떤 프로세스를 언제 배치할지 결정해야합니다. 오케스트레이션에서는 이러한 관리를 담당하는 스케줄러가 존재합니다. ECS에서는 서비스가 이러한 스케줄링을 담당하고 있습니다. ECS 서비스는 각 인스턴스들에 설치된 ecs-client에서 수집된 정보를 기반으로 어디에 어떤 태스크를 언제 실행할지 결정합니다. 따라서 리플리카 타입 서비스의 경우, 다수의 컨테이너 인스턴스가 있을 때 언제 어디에서 태스크가 실행될지 알 수 없습니다. 서비스가 직접 태스크 배치 스케줄링을 수행합니다.*

4. ECR(Elastic Container Registry)

AWS ECS에서는 엘라스틱 컨테이너 레지스트리ECR, Elastic Container Registry라는 프라이빗 도커 레지스트리 서비스를 제공하고 있습니다. 도커 레지스트리는 도커 이미지를 저장 및 관리하는 서비스입니다. 일반적으로 도커에서 공식적으로 제공하는 도커 허브Docker Hub가 많이 이용됩니다. 이미지를 비공개적로 푸시하거나 풀하는 경우에는 도커 허브의 유료 플랜을 이용하거나 직접 도커 레지스트리 서비스를 운용해야합니다. ECR을 사용해서 프라이빗 도커 레지스트리를 대체할 수 있으며, IAM과 조합함으로서 세세한 권한 관리가 가능합니다.

5. 실습 예제

필자의 프로젝트에서는 아직 Container를 운영하고 있지는 않습니다. 하지만, ECR을 한번 고려해보기 위해서 실습예제를 수행해보도록 하겠습니다.

5-1. 클러스터 생성

아마존의 ECR 메뉴로 들어가게 되면, 클러스터를 생성할 수 있는 메뉴가 있습니다. 거기서 EC2+네트워킹을 선택하여 필요한 모든 resource들을 생성해줍니다. 필자 같은 경우는 아래와 같이 생성했습니다.

  • 클러스터 인스턴스 2대
  • VPC / Subnet
  • Security Group
  • IAM

IAM 같은 경우는 아래의 내용때문에 필요합니다. > Amazon ECS 컨테이너 에이전트는 사용자를 대신하여 Amazon ECS API 작업을 호출하므로 에이전트가 사용자에게 속한다는 것을 서비스가 알기 위해서는 에이전트를 실행하는 컨테이너 인스턴스에 ecsInstanceRole IAM 정책과 역할이 필요합니다. ecsInstanceRole이 아직 없는 경우, AWS가 생성할 수 있습니다.

5-2. ECR 생성

이미지들을 관리하기 위해서 Repository를 구성해주어야 합니다. 아마존에서는 손쉽게 ECR로 생성이 가능합니다.

5-3. 이미지 생성

이미지 생성을 해볼 시간입니다. Dockerfile을 작성한 뒤에 이미지 빌드를 수행해서 나오는 이미지를 ECR에 push해보는 작업까지 해보겠습니다.


FROM richarvey/nginx-php-fpm:1.5.3
RUN echo '' > /var/www/html/index.php ;\
    echo '' >> /var/www/html/index.php ;\
    echo '

Nginx Demo v0.1

' >> /var/www/html/index.php ;\ echo '

Hostname:

' >> /var/www/html/index.php ;\ echo '' >> /var/www/html/index.php
$ docker build -t wonni/nginx:v0.1 .

5-4. ERC 푸시

위의 작업을 통해서 이미지가 생서잉 되면, ECR로 이미지를 push해야합니다.

로그인

(aws ecr get-login --no-include-email --region ap-northeast-1)

푸시할 이미지 준비

docker tag wonni/nginx:latest 194506033013.dkr.ecr.ap-northeast-1.amazonaws.com/first-repository:latest

푸시

docker push 194506033013.dkr.ecr.ap-northeast-1.amazonaws.com/first-repository:latest

5-5. 작업 정의

위에서 이야기했던 Task Definition을 정의할 단계입니다. 아마존 콘솔에서 진행은 하되, JSON을 통한 구성을 클릭하여 다음을 입력해줍니다.

{
  "family": "ecs_nginx_examaple",
  "networkMode": "bridge",
  "containerDefinitions": [
    {
      "name": "nginx",
      "essential": true,
      "image": "194506033013.dkr.ecr.ap-northeast-1.amazonaws.com/first-repository:latest",
      "cpu": 0,
      "memory": 128,
      "portMappings": [
        {
          "hostPort": 80,
          "containerPort": 80,
          "protocol": "tcp"
        }
      ]
    }
  ]
}

위의 작업 정의를 보면 알겠지만, 어떤 이미지를 사용하고 자원할당은 어떤식으로 하고 PORT구성은 어떻게 되어있는지에 대한 정의서 작성단계입니다.

5-6. 서비스 생성

이제 태스크 정의까지 완료 되었으니, 이를 스케쥴링 해주는 서비스를 생성해야합니다. 아마존 콘솔에서 클러스터 > 서비스 탭에서 생성 버튼을 클릭해줍니다.

그러면, 어떠한 작업 정의를 기준으로 어떻게 배포를 하는지에 대한 선택을 하는 창이 나옵니다. 최종적으로 완성된 아키텍처는 아래와 같습니다.

아직 ELB는 연결하지 않았지만, ELB를 생성하여 TargetGroup으로 클러스터링된 EC2 인스턴스를 넣어주면 됩니다.

여기서 만약에 Task definition 에서 container replica를 4개를 주면 어떻게 될까요?
현재 Container가 80포트를 점유하고 있기때문에, 2개만 생성이 되고 2개의 Container는 exited code 0로 생성되지 않습니다. 그러면 이러한 상황을 어떻게 해결할 수 있을까요?

container cluster전체를 하나의 port(80)로 바인딩하고 내부 container는 random port로 줘서 port forwarding으로 해결할 수 있습니다.

5-7. ALB 생성

필자는 ECR을 학습하면서 그림에서 ELB 생성이 나타나 있지만, 아마존에서 권고하는것은 msa 와 alb간에 port forwarding기능으로 상호작용이 좋다고 합니다. 그래서 필자는 ALB를 생성했습니다.

보이시는것처럼 리스너에 대상그룹을 추가해줬습니다. 그럼 위에서 나온 80포트로 ALB로 들어오면 80으로 대상그룹으로 보내서 Container 서비스를 할 수 있습니다.

5-8. Task Definition 수정 및 서비스 재배포

위에서 정의한 작업 정의를 업데이트 합니다. 새 개정 생성 을 클릭 한뒤에 json을 클릭하여 HOST 포트를 0으로 바꺼줍니다. 그렇게 되면, Nginx가 생성될때 임의의 포트를 생성하게 됩니다.

이제 서비스를 재생성합니다.

보시는 것처럼 위에서 수정한 작업 정의가 버전 2로 변경되어 있습니다. 이것을 지정합니다. 네트워크 탭에서는 앞서 생성한 ALB를 지정하여 ecs에서 인식하도록 합니다.

이제 생성한 서비스가 배포가 됩니다. 최종적으로 ALB내용이 포함된 서비스를 배포하고 나면, ALB에서는 동적으로 포트포워딩을 Target Group으로 지정하여 생성되게 됩니다. 따라서 아래와 같은 그림으로 서비스 하게 됩니다.

6. 마치며..

이번 글을 작성하면서, 기존에 도커 컨테이너를 학습하고 오케스트레이션에 관한 학습도 이어서 진행을 했었는데 아마존에서는 이미 서비스로 손쉽게 클러스터링을 하고 배포를 할 수 있도록 구성이 다 되어있다는 점에서 놀랐습니다. ECR + ECS를 통해서 컨테이너관리를 손쉽게 할 수 있을 뿐만 아니라, 유연성있게 서비스를 운영할 수 있을것 같다는 생각을 했습니다. 다음시간에는 EKS에 대해서 간단히 정리해보는 시간을 갖도록 하겠습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다