제법 규모가 있었던 전 회사에서는 특별하게 인프라에 대해 고민을 별로 할 필요가 없었다. 많은 부분이 자동화되어 있었고, 또 적당한 툴로 잘 만들어져 있었기 때문에 개발에 온전히 집중할 수 있었다. 하지만 새롭게 온 스타트업은 (당연하게도) 그런게 없으므로, 회사에서 사용하고 있는 AWS 인프라와 배포 시스템에 대해서 직접 공부할 필요가 있었다. 그 중에서도 처음 접하는 것이 docker 였다.

Docker

예전 부터 이름은 많이 들어봤지만 이런저런 이유로 (귀찮아서) 한번도 써본적이 없었다. docker는 컨테이너 기반의 오픈소스 가상화 플랫폼 이라고 정의할 수 있다. 여기서 중요한 용어 중 하나가 컨테이너라고 생각한다.

컨테이너

docker의 컨테이너에 백엔드 프로그램, DB, 메시지 큐 등 다양한 프로그램을 컨테이너에 집어 넣어 추상화 한 다음, 이를 어디서든 배포할 수 있는 상태로 만들어 준다.

docker-container

docker는 기존의 virtual machine과는 다르게 프로세스를 격리 시키는 방법으로 가상화를 한다. docker가 동작하기 위한 cpu나 메모리만 격리해서 사용하므로, 성능적으로도 손실이 적은 방식이다.

이미지

이미지는 컨테이너의 실행에 필요한 파일 및 설정을 포함하고 있는 것 으로 별도의 상태값을 갖고 변하지 않는다. 컨테이너는 이미지를 실행하는 것이라 볼 수 있고, 추가되거나 변화가 필요한 값은 컨테이너에 저장된다. 말 그대로, 컨테이너를 실행하기 위한 모든 정보를 갖고 있기 때문에 의존성 파일을 컴파일/설치할 필요가 없다. docker를 이용한다면 이제 이미지를 다운받고 컨테이너를 생성면 된다.

Dockerfile을 시작으로 실제해보기

여기를 참고하자. 친절하게 정말 잘 써주셨다.

ECR

아마존 ECR은 docker 컨테이너 이미지를 손쉽게 저장, 관리 배포할 수 있게 도와주는 일종의 레파지토리 같은 개념이다.

AWS_ECR.png

이렇게 생성된 이미지를 푸쉬해서 관리 할 수 있다.

ECS

docker를 사용하다보면 컨테이너를 적절하게 배치하거나 관리할 도구의 필요성을 느끼게 된다. docker에서 만든 swarm도 있지만서도, 가장 유명한건 구글의 쿠버네티스가 아닐까 싶다. 이런 컨테이너 오케스트레이션 도구 중 하나가 바로 aws의 elastic container system (이하 ECS) 다.

Cluster

ecs의 가장 기본적인 단위는 클러스터다. 클러스터는 도커 컨테이너를 실행할 수 있는 가상의 공간, 일종의 논리적인 단위 수준이라고 볼 수 있다.

Task

ECS에서 컨테이너를 실행하는 최소단위를 task라고 부른다. task는 하나이상의 컨테이너로 구성할 수 있다. 같은 task내 있는 컨테이너들은 모두 같은 컨테이너 인스턴스에서 실행되는 것이 보장된다. 이러한 task를 실행하기 위한 것이 task definition 이다. task definition에는 task를 실행하기 위한 다양한 것들을 설정할 수 있다.

task-definition.png

귀찮아서 캡쳐는 안했지만, add container에는 이미지 주소, 컨테이너명, 컨테이너 사양, 환경변수 등을 정할 수 있도록 설정이 준비되어 있다. 그리고 설정 변경 / 이미지 변경이 필요할 때마다, task definition을 새롭게 만듦으로써 (create new revision) 이를 해결할 수 있다.

Service

cluster는 두가지 방식으로 task를 실행할 수 있다. 한가지는 run task definition을 통해서 일회성으로 실행하는 것이다. 이 task는 곧바로 실행되고, 더이상 관리되지 않는다. 두 번째 방법은 서비스를 정의하는 것이다. 서비스는 하나이상의 task definition과 연결된다. 서비스는 크게 리플리카 타입과 데몬타입으로 나누어져 있는데, 우리는 리플리카 타입을 사용해서 n개의 태스크가 실행되도록 관리하고 있다.

어떻게 썼나

먼저 dockerfile을 통해서 이미지를 만들고, 해당 이미지를 ecr에 업로드한다. 그리고 배포가 필요할 때마다 task definition을 새롭게 만들고, 새롭게 만들어진 이미지를 넣었다. 그리고 서비스에서 실행할 이미지를 새롭게 만들어진 k번째 task definition으로 교체하면 끝이다.

써보니까 좋았던 점

의식의 흐름대로 나열해 보았다.

  1. 배포 히스토리를 남길 수 있었다 == 롤백이 쉬웠다. 배포할 때 마다 새롭게 만들어진 이미지를 ecr에 업로드 하였기 때문에 이미지 목록을 히스토리 느낌으로 남길 수 있었다. 그리고 롤백이 필요하면 이전에 잘 동작했던 이미지로 교체해주면 된다. 사실 이 방법보다 쉬운 것은 그냥 예전에 잘 동작했던 task-definition으로 service를 교체해 주는 것이다.

  2. 스테이지 별 로 다른 변수를 task definition - container의 환경변수로 관리할 수 있다. 기존에는 프로젝트에 .development .release 이런 형식으로 소스파일안에 스테이지마다 다른 변수 값을 두어야 했다. 따라서 이 글로벌 변수에 변동이 있을 때마다 배포를 새로 하는 번거로움이 있었는데, 이 방식 대로 하면 단지 task definition을 새롭게 만들고, 환경변수를 추가해서 service에 올려주기만 하면 된다. 추가로 dockerfile 혹은 docker 빌드 과정에 환경변수를 따로따로 주입하지 않는 다면, 어떤 스테이지 든지 간에 동일한 이미지로 대처할 수 있다.

3. 드디어 docker를 써볼 수 있었다.

4. 아마존에 많은 돈을 지출할 수 있다.