제법 규모가 있었던 전 회사에서는 특별하게 인프라에 대해 고민을 별로 할 필요가 없었다. 많은 부분이 자동화되어 있었고, 또 적당한 툴로 잘 만들어져 있었기 때문에 개발에 온전히 집중할 수 있었다. 하지만 새롭게 온 스타트업은 (당연하게도) 그런게 없으므로, 회사에서 사용하고 있는 AWS 인프라와 배포 시스템에 대해서 직접 공부할 필요가 있었다. 그 중에서도 처음 접하는 것이 docker 였다.
예전 부터 이름은 많이 들어봤지만 이런저런 이유로 (귀찮아서) 한번도 써본적이 없었다. docker는 컨테이너 기반의 오픈소스 가상화 플랫폼 이라고 정의할 수 있다. 여기서 중요한 용어 중 하나가 컨테이너라고 생각한다.
docker의 컨테이너에 백엔드 프로그램, DB, 메시지 큐 등 다양한 프로그램을 컨테이너에 집어 넣어 추상화 한 다음, 이를 어디서든 배포할 수 있는 상태로 만들어 준다.
docker는 기존의 virtual machine과는 다르게 프로세스를 격리 시키는 방법으로 가상화를 한다. docker가 동작하기 위한 cpu나 메모리만 격리해서 사용하므로, 성능적으로도 손실이 적은 방식이다.
이미지는 컨테이너의 실행에 필요한 파일 및 설정을 포함하고 있는 것 으로 별도의 상태값을 갖고 변하지 않는다. 컨테이너는 이미지를 실행하는 것이라 볼 수 있고, 추가되거나 변화가 필요한 값은 컨테이너에 저장된다. 말 그대로, 컨테이너를 실행하기 위한 모든 정보를 갖고 있기 때문에 의존성 파일을 컴파일/설치할 필요가 없다. docker를 이용한다면 이제 이미지를 다운받고 컨테이너를 생성면 된다.
여기를 참고하자. 친절하게 정말 잘 써주셨다.
아마존 ECR은 docker 컨테이너 이미지를 손쉽게 저장, 관리 배포할 수 있게 도와주는 일종의 레파지토리 같은 개념이다.
이렇게 생성된 이미지를 푸쉬해서 관리 할 수 있다.
docker를 사용하다보면 컨테이너를 적절하게 배치하거나 관리할 도구의 필요성을 느끼게 된다. docker에서 만든 swarm도 있지만서도, 가장 유명한건 구글의 쿠버네티스가 아닐까 싶다. 이런 컨테이너 오케스트레이션 도구 중 하나가 바로 aws의 elastic container system (이하 ECS) 다.
ecs의 가장 기본적인 단위는 클러스터다. 클러스터는 도커 컨테이너를 실행할 수 있는 가상의 공간, 일종의 논리적인 단위 수준이라고 볼 수 있다.
ECS에서 컨테이너를 실행하는 최소단위를 task라고 부른다. task는 하나이상의 컨테이너로 구성할 수 있다. 같은 task내 있는 컨테이너들은 모두 같은 컨테이너 인스턴스에서 실행되는 것이 보장된다. 이러한 task를 실행하기 위한 것이 task definition 이다. task definition에는 task를 실행하기 위한 다양한 것들을 설정할 수 있다.
귀찮아서 캡쳐는 안했지만, add container에는 이미지 주소, 컨테이너명, 컨테이너 사양, 환경변수 등을 정할 수 있도록 설정이 준비되어 있다. 그리고 설정 변경 / 이미지 변경이 필요할 때마다, task definition을 새롭게 만듦으로써 (create new revision) 이를 해결할 수 있다.
cluster는 두가지 방식으로 task를 실행할 수 있다. 한가지는 run task definition
을 통해서 일회성으로 실행하는 것이다. 이 task는 곧바로 실행되고, 더이상 관리되지 않는다. 두 번째 방법은 서비스를 정의하는 것이다. 서비스는 하나이상의 task definition과 연결된다. 서비스는 크게 리플리카 타입과 데몬타입으로 나누어져 있는데, 우리는 리플리카 타입을 사용해서 n개의 태스크가 실행되도록 관리하고 있다.
먼저 dockerfile
을 통해서 이미지를 만들고, 해당 이미지를 ecr
에 업로드한다. 그리고 배포가 필요할 때마다 task definition
을 새롭게 만들고, 새롭게 만들어진 이미지를 넣었다. 그리고 서비스에서 실행할 이미지를 새롭게 만들어진 k번째 task definition으로 교체하면 끝이다.
의식의 흐름대로 나열해 보았다.
배포 히스토리를 남길 수 있었다 == 롤백이 쉬웠다. 배포할 때 마다 새롭게 만들어진 이미지를 ecr
에 업로드 하였기 때문에 이미지 목록을 히스토리 느낌으로 남길 수 있었다. 그리고 롤백이 필요하면 이전에 잘 동작했던 이미지로 교체해주면 된다. 사실 이 방법보다 쉬운 것은 그냥 예전에 잘 동작했던 task-definition으로 service를 교체해 주는 것이다.
스테이지 별 로 다른 변수를 task definition - container의 환경변수로 관리할 수 있다. 기존에는 프로젝트에 .development
.release
이런 형식으로 소스파일안에 스테이지마다 다른 변수 값을 두어야 했다. 따라서 이 글로벌 변수에 변동이 있을 때마다 배포를 새로 하는 번거로움이 있었는데, 이 방식 대로 하면 단지 task definition을 새롭게 만들고, 환경변수를 추가해서 service에 올려주기만 하면 된다. 추가로 dockerfile
혹은 docker 빌드 과정에 환경변수를 따로따로 주입하지 않는 다면, 어떤 스테이지 든지 간에 동일한 이미지로 대처할 수 있다.
3. 드디어 docker를 써볼 수 있었다.
4. 아마존에 많은 돈을 지출할 수 있다.