Azure 컨테이너 서비스로 Node.js 앱 배포하기

Apr 25, 2016 • nodejs azure acs


사건의 발단

지난 2016년 4월 20일, Azure 컨테이너 서비스(ACS:Azure Container Service, 이하 ACS) Microsoft Azure 블로그에 공개되었다.

ACS

이 소식을 Microsoft Azure MVP인 남정현님의 글을 통해서 접했다.

그리고 패기있게 댓글을 남기게 된다.

내가왜

나도 내가 왜 그랬는지 모르겠다. 바보같은 과거의 나.

뱉어놓은 말에 책임을 느끼고 삽을 떠봤다.


필수사항

글의 내용을 진행하기 위해 Docker Engine과 Docker Compose가 필요하다. Linux 환경에서 진행하기때문에 OS도 Linux나 OSX에서 진행하길 권한다.

중요한 것은 Docker Compose 버전이다. Docker Swarm으로 ACS를 구성할 예정인데 Docker Compose 1.5 버전만 해도 생성된 컨테이너를 찾지 못해 링크하지 못하는 에러가 발생했다.

Docker Compose 1.5.1을 설치한게 작년 11월인데 글 작성일로부터 9일전에 1.7.0 버전이 나왔다.

ACS 클러스터 배포

ACS 클러스터를 배포하는 방법은 크게 3가지다. 내가 사랑하는 Azure portal을 이용하거나, Azure CLI 혹은 PowerShell을 이용하는 것이다.

각자 편한 방법으로 진행하면 된다.

글에서는 Azure portal로 진행한다. 다른 방법을 사용하고자한다면 Azure 컨네이너 서비스 클러스터 배포 글을 참고하고 SSH 터널넘어가도 좋다.

  1. Azure portal로 접속해서 ACS를 선택한다.

    acs-portal1

  2. 사용자이름(User Name), SSH 공개키(SSH public key), 리소스그룹(Resource Group) 명을 입력하고 위치(Location)을 선택한다.

    SSH 공개키를 생성하는 것은 생활코딩의 SSH Key - 비밀번호 없이 로그인 SSH Key 만들기 부분을 참고하면 된다.

    acs-portal3

  3. Orchestrator configuration은 Swarm으로 선택한다.

    Docker Compose를 활용하기 위해서 Swarm으로 선택으나 자신이 Mesos와 Marathon이 익숙하다면 DC/OS를 선택하기 바란다.

    그러나 Marathon으로 컨테이너를 배포하는 방법은 다루지 않는다.

    acs-portal4

  4. Agent count, Agent virtual machine size, Master count를 필요한만큼 입력한 뒤 DNS prefix를 입력한다.

    단순한 테스트이기 때문에 Agent count는 2로 했고 Master count는 1로 했다. Agent virtual machine size는 저렴한 Standard A1을 선택했다.

    아래 이미지와는 Agent count 숫자와 DNS prefix만 차이가 있다.

    acsp-portal5

  5. 나머지 과정을 확인하고 진행하면 15~20분 정도 배포가 진행된다.

    acs-portal8

배포가 끝나면 리소스그룹이 생성되고 그 안에 로드밸런스, 가상컴퓨터, 가상 컴퓨터 크기 집합 등 Azure의 다양한 서비스가 일괄 생성된 것을 확인할 수 있다.

acs배포완료

SSH 터널

로컬환경에서 배포된 ACS 환경을 사용하기 위해 SSH 터널을 생성하여야한다.

Windows 환경이라면 Azure 컨테이너 서비스 클러스터에 연결의 Windows에서 SSH 터널 만들기 부분을 참고하기 바란다.

SSH 터널 개념은 SSH Tunneling 글을 참고하자.

먼저 SSH 터널을 생성하려면 FQDN(Fully Qualified Domain Name)를 알아야한다.

FQDN 확인

  1. Azure portal로 접속해서 리소스그룹을 선택한 뒤 ACS로 생성한 리소스그룹을 선택한다.

    acsFQDN1

  2. 마지막 배포를 선택한다. 그리고 배포기록에서 가장 마지막 배포를 선택한다.

    acsFQDN2 acsFQDN3

  3. 출력에서 MASTERFQDN을 확인한다(이미지에는 없지만 아래 쪽에 AGENTFQDN도 함께 확인해둔다).

    acsFQDN4

SSH 터널 생성

SSH 터널을 생성할 차례다.

아래 명령에에서 User NameFQDN(Fully Qualified Domain Name)을 자신의 ACS 환경에 맞게 대체하여 터미널에 입력하면 SSH 터널이 생성된다.

$ ssh -L 2375:localhost:2375 -N [User Name]@[FQDN] -p 2200

연결이 되었으면 터미널 창을 새로 열어서 아래 명령을 입력한다. DOCKER_HOST 환경 변수에 설정하여 배포된 ACS 환경을 자신의 로컬환경에서 Docker CLI(Command Line Interface)로 사용할 수 있게 된다.

터미널 창을 새로 여는 것은 SSH 터널이 연결된 상태에서는 프롬프트가 돌아오지 않기 때문이다.

$ export DOCKER_HOST=:2375

Node.js 앱 컨테이너 배포

이제 사용할 컨테이너가 필요하다. 여기서는 Node.js와 Express.js로 웹 어플리케이션을 만드는 과정은 생략하고 제작해둔 샘플 앱을 빌드하여 사용하도록 하겠다.

컨테이너 빌드

  • Github에서 Node.js 앱을 다운받아 압축을 해제한 후 NodejsExampleApp 폴더로 이동한다.

아래 명령을 순서대로 입력하면 된다.

$ wget https://github.com/totuworld/NodejsExampleApp/archive/0.0.1.zip
$ unzip 0.0.1.zip
$ cd NodejsExampleApp-0.0.1
  • ACS에 컨테이너를 빌드한다.
$ docker build --tag=nodeapp:0.0.1 .
  • 빌드가 완료되면 아래 명령으로 빌드된 컨테이너를 확인할 수 있다.
$ docker images

REPOSITORY      TAG         IMAGE ID        CREATED         VIRTUAL SIZE
nodeapp         0.0.1       sha256:bab5a    5 minutes ago   221.1 MB
node            4-slim      sha256:d1e5c    9 days ago      206.7 MB

컨테이너 배포

이제 빌드한 컨테이너를 ACS 환경에 배포해보자.

$ docker run --name=nodeapp -d -p 80:3000 nodeapp:0.0.1

위 명령은 nodeapp이란 이름으로 nodeapp:0.0.1 컨테이너를 배포한 것이다.

-p 옵션 뒤에 값은 호스트의 80번 포트와 컨테이너 3000번 포트를 연결한 것이다.

가장 빨리 만나는 Docker에서 Docker 명령은 자세히 익힐 수 있다.

아래 명령을 입력하면 작동하는 컨테이너를 확인할 수 있다.

$ docker ps
CONTAINER ID    IMAGE           COMMAND         CREATED         STATUS          PORTS                 NAMES
0e8c2e2712a5    nodeapp:0.0.1   "npm start"     16 minutes ago  Up 16 minutes   10.0.0.6:80->3000/tcp swarm-agent-F6767C68000002/nodeapp

앞서 확인한 AGENTFQDN 주소를 브라우저에 입력하면 아래와 같은 결과를 확인할 수 있다.

ACSAppResult

여기서 잠깐!

갑자기 왜 AGETNFQDN을 입력해서 확인하는지 궁금할 수 있다.

ACSSwarm구조

위 그림에서 보는것처럼 좌측은 ACS를 관리하기 위한 클러스터이다. 이 관리용 클러스터에 접속할 때 MASTERFQDN을 사용한다. 실제로 컨테이너가 배포되는 곳은 우측의 agent이 클러스터이므로 agent에 접근할 수 있는 주소인 AGENTFQDN을 입력해야 nodeapp이 보내는 결과값을 받을 수 있는 것이다.

Orchestration

ACS 환경에 컨테이너를 배포해봤다. 그러나 Docker를 로컬 환경에서 활용해 봤다면 너무 간단한 예제 아닌가 하며 실망할 수 있다.

그래서 준비했다! 바로 Orchestration!!!

이제 5개 컨테이너가 연결되어 하나의 서비스로 작동하도록 구성해보자.

이부분은 A sample Docker workflow with Nginx, Node.js and Redis를 참고했다. 단계별 자세한 설명을 원한다면 원문을 보자.

구성할 컨테이너 구조는 아래와 같다.

  • 1 Redis 컨테이너
  • 3 Node.js 앱 컨테이너
  • 1 Nginx 컨테이너

DockerSample

Orchestration 환경 조성

우리는 Docker Compose로 Orchestration할 것이다. 그럼 (Docker Engine이 Dockerfile이 필요하듯) docker-compose.yml 파일이 필요하다.

그래서 하나 만들어 두었다.

이전에 작업하던 폴더(NodejsExampleApp-0.0.1)를 빠져나와서 다음 명령을 순서대로 입력한다.

$ wget https://github.com/totuworld/NodejsExampleApp/archive/0.0.2.zip
$ unzip 0.0.2.zip
$ cd NodejsExampleApp-0.0.2

Docker Compose로 앱 Orchestration하기

앞서 진행한 SSH 터널과 DOCKER_HOST 환경 변수가 유지된 환경이어야 한다.

NodejsExampleApp-0.0.2 폴더에서 다음 명령을 입력한다.

$ docker-compose up -d

Creating nodejsexampleapp_redis_1
Creating nodejsexampleapp_node3_1
Creating nodejsexampleapp_node2_1
Creating nodejsexampleapp_node1_1
Creating nodejsexampleapp_nginx_1

Creating 메시지가 나온 뒤에 Node.js 앱 컨테이너를 생성하고 nginx 컨테이너를 생성하느라 시간이 좀 걸릴 수 있다.

컨테이너 생성이 끝나고 배포되면 AGENTFQDN 주소를 브라우저하자.

ACSAppResult

결과를 보면 알겠지만 업데이트된 Node.js 앱은 접속이 이뤄질 때마다 Redis에 View횟수를 누적하여 보여준다.

만약 각 컨테이너가 어떤 agent 배포되어있는지 확인하고 싶다면 앞서 말한 아래 명령을 입력하면 된다.

$ docker ps

맺음말

Docker를 로컬 환경에서만 사용하다가 클러스터된 환경을 구성하려고 많은 삽을 뜬 기억이 있다.

CoreOS, Mesos, Marathon, Consul, Docker Swarm, Docker Compose 등 Docker도 제대로 못 쓰면서 보느라고 고생 좀 했다.

그런데 ACS는 한번에 클러스터링된 환경을 구성해준다.

덕분에 학습 비용이 낮고 서비스에만 집중할 수 있다.

말로만 듣던 CaaS(Container as a Service)가 명령어 몇 개로 다가오다니 Azure 좋구나~

하지만 이 좋은 ACS에도 단점을 말하라면 참고할만한 레퍼런스가 적다는 점이다(튜토리얼 포함).

그러나 이제 일반에 공개되었다고 생각해보면 큰 단점도 아니다. 다만 시간이 필요할 뿐이다.

끝으로 이번에 ACS보다 더 배운것은 말조심이다.

고작 Docker 조금 다뤄봐놓고 ACS 다룰려니 지식이 부족하여 아주 혼났다.

그래도 맺음말인데 자뻑 컷 하나는 있어야지.

그어려운걸제가


참고자료


Buy me a latteBuy me a latte