도커 스웜 모드를 사용하면 클러스트 환경에서 서비스를 관리할 수 있다. 여기서 서비스는 일종의 네트워크에서 찾고 사용할 수 있는 기능으로 컨테이너로 구성되어 있다. 서비스를 사용하면 실제 운영 중에 필요한 컨테이너 헬스체크, 고가용성을 위한 이중화, 롤링 업그레이드 등을 손쉽게 할 수 있다.

이 글에서는 도커 스웜 클러스터를 구축하고 아주 간단한 서비스를 클러스터에서 실행해보겠다.

서비스 테스트를 위한 간단한 이미지

여기서 사용할 이미지는 호스트 이름을 리턴하는 간단한 노드 웹이다. 코드는 다음과 같다.

const http = require('http');

const server = http.createServer().listen(5000);

server.on('request', (req, res) => {
    console.log('request arrived.');
    res.write("Hello: " + process.env.HOSTNAME);
    res.end();
});

server.on('connection', (socket) => {
    console.log("Connected");
});

이 코드를 실행하는 이미지를 도커 허브에 madvirus/simplenode:0.1로 등록해 놨다. 다음은 이미지를 생성할 때 사용한 Dockerfile이다.

FROM node:8.16-alpine
RUN apk add --no-cache tini curl

WORKDIR /app

COPY app.js .

ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "app.js"]

도커 스웜 클러스터 생성

도커 스웜 클러스터를 생성하기 위해 다음의 IP를 가진 세 장비를 준비했다. 괄호 안에 표시한 문자열은 호스트 이름이다.

  • 매니저 : 192.168.1.101(docker-node1)
  • 워커: 192.168.1.102(docker-node2), 192.168.1.103(docker-node3)

101 서버에는 스웜 클러스터의 매니저를 설치하고 나머지 102, 103 서버에는 워커를 설치한다.

먼저 101 서버에서 docker swarm init 명령어로 도커 스웜을 초기화하자. 이때 --advertise-addr 옵션으로 스웜 클러스터에 참여할 IP를 지정한다.

$ docker swarm init --advertise-addr=192.168.1.101
Swarm initialized: current node (t8uoehrwcnzdf4q0poh6thlt4) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-4pldr32x98ytmo60lso4jkhj2mg2zrdqxo33b2n8f50oz01pwp-8y4jflppx6eelxs7cn6fgfmd2 192.168.1.101:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

docker swram init 명령어는 docker swarm join 명령어를 출력한다. 이 명령을 사용해서 스웜에 워커를 추가할 수 있다. docker swarm join-token worker 명령어를 사용해서 참여 명령어를 조회할 수 있다.

102 서버와 103 서버에서 docker swram join 명령어를 실행하자.

$ docker swarm join --token SWMTKN-1-4pldr32x98ytmo60lso4jkhj2mg2zrdqxo33b2n8f50oz01pwp-8y4jflppx6eelxs7cn6fgfmd2 192.168.1.101:2377
This node joined a swarm as a worker.

스웜 매니저 장비(101 서버)에서 docker node ls 명령어를 실행해보자. 노드 목록을 볼 수 있다. 노드는 스웜에 참여한 도커 인스턴스로 보통 한 호스트에 한 노드를 설치한다.

vagrant@docker-node1:~$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
t8uoehrwcnzdf4q0poh6thlt4 *   docker-node1        Ready               Active              Leader              19.03.2
rmsb5mnofkv8czjgjzpcce1gy     docker-node2        Ready               Active                                  19.03.2
01bul21qtizrxnawg56zngs4v     docker-node3        Ready               Active                                  19.03.2

docker-node1 호스트는 MANAGER STATUS 값이 Leader이다. 도커 스웜은 한 개 이상의 매니저를 가질 수 있는데 이 중에서 리더가 클러스터를 관리한다.

서비스 테스트하기

스웜 클러스터를 만들었으니 이제 클러스터에서 서비스를 실행해보자. docker service create 명령어를 사용해서 서비스를 생성한다.

$ docker service create \
--name simple \
--publish published=8000,target=5000 \
--replicas 2 \
madvirus/simplenode:0.1

ojslsjah1obmlpdyargxp6fg9
overall progress: 2 out of 2 tasks
1/2: running   [==================================================>]
2/2: running   [==================================================>]
verify: Service converged

위 명령어는 madvirus/simplenode:0.1 이미지를 이용해서 이름이 simple인 서비스를 생성한다. --replicas 옵션은 생성할 컨테이너의 개수를 지정한다. 여기서는 2를 주었으므로 클러스터 내에 두 개의 컨테이너를 생성한다. --publish 옵션을 사용해서 외부에서 8000번 포트로 연결하면 컨테이너의 5000번 포트로 연결한다.

서비스를 만들었으니 http://192.168.1.101:8000, http://192.168.1.102:8000, http://192.168.1.103:8000에 각각 연결해보자. 아래 그림처럼 호스트 이름을 응답으로 출력할 것이다(simplenode:0.1이 실행하는 app.js는 호스트 이름을 출력하는 간단한 웹 어플리케이션이다).

스웜 ingress 네트워크

docker service ls 명령어를 실행하면 실행 중인 서비스 목록을 보여준다.

$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                     PORTS
ojslsjah1obm        simple              replicated          2/2                 madvirus/simplenode:0.1   *:8000->5000/tcp

REPLICAS 값이 2/2인데 이는 현재 2개가 실행중이고(앞의 2) 설정한 복제수는 2(뒤의 2)개라는 것을 보여준다. 포트 연결은 서비스 단위에서 처리된다. 서비스 수준에서 8000 포트로 오는 요청을 컨테이너의 5000 포트로 연결한다.

8000 포트를 사용하면 어떤 노드에 요청하더라도 서비스의 컨테이너에 연결된다. 예를 들어 simple 서비스의 컨테이너가 docker-node1과 docker-node2에 각각 하나씩 떠 있고 docker-node3에 요청을 보내도 도커 스웜 네트워크가 알맞게 컨테이너에 전달한다. 이를 처리하는 것이 ingress 네트워크이다.

docker network ls 명령어를 실행해보자. 이름이 ingress인 네트워크가 생성된 것을 볼 수 있다.

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
d1a366c95b3a        bridge              bridge              local
da6c7575bf20        docker_gwbridge     bridge              local
b30ace236245        host                host                local
c8c1e9h5214o        ingress             overlay             swarm
918b235ab093        none                null                local

ingress 네트워크는 오버레이(overlay) 드라이버를 사용하고 스웜(swarm) 범위를 갖는다. 오버레이 네트워크는 서로 다른 도커 호스트에서 실행되는 컨테이너 간 통신을 위한 논리적인 네트워크 그룹으로서 ingress 네트워크는 특수한 오버레이 네트워크이다. ingress 네트워크는 스웜 노드로 오는 모든 요청을 알맞게 서비스로 라우팅한다.

오버레이 네트워크와 서비스에 대한 내용은 뒤에서 다시 살펴본다.

관련 글

+ Recent posts