서론
컨테이너 기술은 애플리케이션 배포 방식에 큰 변화를 가져왔다. DevOps 및 CI/CD 파이프라인과 연계하여 빠른 배포가 가능하게 되었으며, 주변 여러 프로젝트에서도 Docker와 같은 컨테이너 기술을 많이 이용하는 것을 볼 수 있다.
이 글에서는 AWS에서 지원하는 컨테이너 기술인 ECR과 ECS에 대해 알아볼 것이며, 그에 앞서 ECR과 ECS의 핵심 기술인 컨테이너와 컨테이너 오케스트레이션에 대해 간단하게 알아보자.
컨테이너
컨테이너는 애플리케이션과 그 실행에 필요한 모든 요소를 하나로 패키징하는 기술이다.
VM(가상 머신)과 비교해서 이식성, 확장성이 뛰어나, 현대 소프트웨어 개발 환경에서 매우 많이 이용된다.
대표적으로 Docker가 있다.
컨테이너 오케스트레이션
컨테이너 오케스트레이션은 수많은 컨테이너를 자동으로 배포, 관리, 확장하는 기술이다.
오케스트레이션은 조율이란 뜻으로, 오케스트라 지휘자가 여러 악기를 조화롭게 이끄는 모습에서 유래했다.
즉, 컨테이너 오케스트레이션은 여러 컨테이너를 조율하고 관리하여 유기적으로 동작하게 만드는 것이다.
대표적으로 Kubernetes(k8s)가 있다.
Amazon ECR
Amazon ECR(Elastic Container Registry)는 Docker Image와 같은 애플리케이션 이미지를 저장하는 AWS의 저장소이다.
주요 기능
- 높은 가용성 및 안정성
- 내부적으로 S3를 이용하므로 S3의 고가용성과 내구성을 획득한다.
- 암호화
- 내부적으로 S3를 이용하므로 S3의 암호화 또한 획득한다.
- 소프트웨어 취약성 관리
- Amazon Inspector를 통해 이미지에 포함된 소프트웨어의 보안 취약점을 파악한다.
- 이미지 수명 주기 정책 관리
- 예를 들어, 최근 5개 버전만 유지하거나 60일 지난 이미지를 자동 삭제하는 방식으로 정책을 설정할 수 있다.
Docker hub vs ECR
기능을 보면 Docker hub와 유사하다고 느낄 수 있는데, ECR은 Docker hub 보다 AWS 생태계와의 통합성에서 큰 이점을 가진다.
세부적인 차이는 다음과 같다.
- 저장소 공개 범위
- Docker hub → 기본적으로 public
- ECR → 기본적으로 private (public도 별도 서비스로 존재)
- 권한 관리
- Docker hub → 유료 플랜에서 권한 제어 제공
- ECR → IAM 기반으로 권한 제어 제공
- 요금 정책
- Docker hub → 무료 플랜과 유료 플랜으로 나뉨
- 무료 플랜은 pull 횟수 제한
- ECR → 저장 및 전송량에 따른 요금 부과
- 저장된 데이터 1GB/월당 0.10$
- 동일 리전 내 데이터 전송 무료
- 타 리전 간 데이터 전송에서 정책에 따라 요금 부과
- Docker hub → 무료 플랜과 유료 플랜으로 나뉨
Amazon ECS
Amazon ECS(Elastic Container Service)는 완전관리형 컨테이너 오케스트레이션 서비스이다. EC2 또는 Fargate에 연결하여 컨테이너를 배포할 수 있으며, 이를 운영하는 데 필요한 다양한 기능을 제공한다.
구조
ECS는 Cluster > Service > Task의 구조를 가진다.
- Cluster
- Task 또는 Service의 논리적 그룹이다.
- ex) production-cluster, test-cluster
- Task Definition & Task
- Task Definition = 설계도
- 말 그대로 Task를 어떻게 실행할 것인지 다음의 기준에 따라 정의한다.
- 어떤 이미지를 쓸 것인가?
- CPU와 메모리를 얼마나 할당할 것인가?
- 어떤 환경변수를 사용할 것인가?
- 어떤 포트를 열 것인가?
- 말 그대로 Task를 어떻게 실행할 것인지 다음의 기준에 따라 정의한다.
- Task = 설계도대로 만든 제품
- Task Definition을 실행한 인스턴스이며, ECS에서 컨테이너의 실행 단위이다.
- Task Definition = 설계도
- Service
- 지속적으로 Task를 실행, 관리하는 단위이다.
- 지정된 수의 Task를 동시에 실행하고 유지/관리한다.
- Task가 실패/중지되면 다른 Task를 시작해서 대체한다.
- Rolling 또는 Blue/Green 업데이트 또한 가능하게 한다.
- ELB와 통합해서 트래픽을 분산 가능하다.
주요 기능
- Load Balancer
- Amazon ELB와 통합해서 트래픽을 분산할 수 있다.
- 즉, ELB의 Application/Network Load Balancer를 이용할 수 있다.
- Auto Scaling
- CPU/Memory 사용률에 따라 Task가 추가되도록 설정할 수 있다.
- 모니터링
- Amazon CloudWatch와 통합할 수 있다.
- Task의 평균 또는 전체 CPU/Memory 사용률을 모니터링할 수 있다.
- Cluster/Service/Task 그룹 별 모니터링 또한 가능하다.
Elastic Beanstalk vs ECS
Elastic Beanstalk와 ECS 모두 서버 개발자에게 편리한 기능을 제공하는데, 어떤 차이가 있는지 알아보자.
- 목적
- Elastic Beanstalk → 웹 어플리케이션을 최대한 간단하게 배포 및 운영하고 싶을 때
- ECS → 컨테이너 기반 애플리케이션을 세밀하게 관리하면서 배포 및 운영하고 싶을 때
- 확장성/유연성
- Elastic Beanstalk → 세부적인 인프라 설정이 제한적
- ECS → 인프라 설정을 매우 세부적으로 조정 가능
- 그래서 어떤 때 쓸까요?
- Elastic Beanstalk → 간단한 웹 애플리케이션, 빠른 배포 필요 시
- ECS → MSA, 대규모 시스템 등에서 장기적인 운영 필요할 시
ECS vs EKS
컨테이너 오케스트레이션 서비스의 대표적인 예시로 Kubernetes(k8s)를 들 수 있다. AWS에서는 Amazon EKS(Elastic Kubernetes Service)를 통해 쿠버네티스 기반 오케스트레이션 서비스 또한 지원한다.
ECS는 AWS에서 자체 개발한 독자적인 컨테이너 오케스트레이션 서비스이지만, EKS는 표준 kubernetes 기반으로 설계된 오케스트레이션 서비스라는 차이가 있다. 때문에 EKS는 k8s의 사용법을 알아야지 활용할 수 있는 반면, ECS는 이러한 점에서 보다 자유롭다.
다만 ECS는 AWS의 기술이기 때문에 AWS에 종속적이나, EKS는 클라우드 독립적으로 운영할 수 있다는 점에 이점이 있다.
프로젝트의 배포 과정 비교
우리가 Github Actions의 workflow를 통해 서비스를 배포하는 상황을 가정해보자.
docker-compose의 경우
- Merge로 인해 Workflow 실행
- 애플리케이션 빌드 및 Docker Image로 빌드
- Docker hub에 Image 업로드
- EC2 서버에 SSH 접속
- EC2에서 Image Pull
- 내려받은 Image를 EC2에 컨테이너로 실행
ECS의 경우
참고로 Github Actions에서 'Deploy to Amazon ECS' 라는 이름으로 예시 workflow를 찾을 수 있다.
- Merge로 인해 Workflow 실행
- 애플리케이션 빌드 및 Docker Image로 빌드
- AWS에 로그인
- ECR에 Image 업로드
- ECS의 Task Definition에서 Image를 ECR에 업로드된 새로운 Image로 교체
- ECS Service 실행 → ECS가 ECR에서 새로운 Image를 EC2 또는 Fargate에 컨테이너로 실행
그래서 대체 왜 ECS를 고려하는가?
'어차피 배포되는 결과가 똑같으면 굳이 복잡하게 ECS 쓸 필요가 있는가?' 라는 의문이 들 수 있다.
docker-compose를 통한 배포는 장기적인 프로젝트 관점에서 보았을 때, 단점이 있다. docker-compose로 무중단 배포를 잘 구현했다고 하자. 만약 서비스에 오류가 생기면 docker-compose는 대처할 수 있을까? 개발자가 다시 에러를 수정하거나 다시 배포하여야 하기 때문에, 필연적으로 다운타임이 길게 생긴다. 당연하게도 서비스 이용자들은 그만큼 불편함을 오래 겪을 수밖에 없다.
또한 Load Balancing과 Auto Scaling이 불가능하다. 동일 EC2 인스턴스에 띄운 컨테이너들은 ELB를 이용하더라도 ECS 없이 컨테이너 단위 트래픽 분산이 불가능하며, CPU 사용량에 따라 컨테이너 수를 늘리고 싶다면 직접 컨테이너 수를 늘리는 명령을 실행해야 한다.
ECS를 통한 배포는 이런 점에서 자유롭다. 서비스에 오류가 생겨서 멈춘다고 하더라도, ECS는 이를 확인하고 자동으로 복구하는 기능을 갖추고 있다. 또한 ECS는 ELB와 함께 컨테이너 단위 트래픽 분산이 가능하며, CPU나 Memory 사용량에 따라 Task가 늘어나도록 하는 Auto Scaling도 지원한다.
해커톤같은 단기 프로젝트라면 docker-compose도 좋은 선택일 수 있다. 하지만 만약 장기적인 프로젝트를 계획, 또는 진행하고 있다면, 서비스의 안정성을 위해서 ECS를 통한 배포를 시도해보는 것은 어떨까?