티스토리 뷰

DevOps/Docker

[Docker] Docker Swarm Service

뱃싸공 2023. 1. 11. 14:28
스웜 모드 서비스 개념

 

Docker Swarm 모드를 사용하지 않고, 사용하는 도커 명령어의 제어 단위는 컨테이너이다. 예를 들어 docker run 명령어는 컨테이너를 생성하고, docker rm 명령어는 컨테이너를 삭제한다. 그러나 스웜 모드에서 제어하는 단위는 컨테이너가 아닌 '서비스(Service)'이다.

서비스는 같은 이미지에서 생성된 컨테이너의 집합이며, 서비스를 제어하면 해당 서비스 내의 컨테이너에 같은 명령이 수행된다. 서비스 내에 컨테이너는 1개 이상 존재할 수 있으며, 컨테이너들은 각 워커 노드 혹은 매니저 노드에 할당된다. 이렇게 서비스 내의 컨테이너를 '태스크(Task)'라고 부르기도 한다.

예를들어, ubuntu 이미지로 서비스를 생성하고 컨테이너의 수를 3개로 설정했다고 가정해 보자.
스웜 스케줄러는 서비스의 정의에 따라 컨테이너를 할당할 적합한 노드를 선정하고, 해당 노드에 컨테이너를 분산해서 할당한다. 위의 그림은 각 노드에 컨테이너가 하나씩 할당된 경우를 보여주지만, 반드시 각 노드에 하나씩 할당되지 않을 수도 있다. 이처럼 함께 생성된 컨테이너를 '레플리카(replica)'라고 하며, 서비스에 설정된 레플리카의 수만큼의 컨테이너가 스웜 클러스터 내에 존재해야 한다. 

스웜은 서비스의 컨테이너들에 대한 상태를 계속 확인하고 있다가 서비스 내에 정의된 레플리카의 수만큼 컨테이너가 스웜 클러스터에 존재하지 않으면 새로운 컨테이너 레플리카를 생성한다.

그림으로 쉽게 보면, 위와 같이 컨테이너가 할당된 노드가 다운되었을 때 매니저는 사용 가능한 다른 노드에 같은 컨테이너를 생성한다. 또한 서버가 다운되지 않더라도 서비스 내의 컨테이너 중 일부가 작동을 멈춰 정지한 상태로 있다면 이 또한 레플리카의 수를 충족하지 못하는 것으로 판단해 스웜 매니저는 새로운 컨테이너를 클러스터에 새롭게 생성한다.

서비스 생성

 

서비스를 제어하는 도커 명령어는 전부 매니저 노드에서만 사용할 수 있다. 따라서 아래의 예제는 모두 매니저 노드에서 입력한다는 전제하에 진행할 것이다.

서비스를 사용하기 위한 명령어는 docker service로 시작하고, 서비스를 생성하려면 docker service create 명령어를 사용한다. 아래의 명령어는 ubuntu 이미지로 서비스 내의 컨테이너를 생성하며, 컨테이너가 시작할 때 실행할 'hello world'를 출력하는 셸 명령어를 설정하는 명령어이다.

docker service create \
ubuntu \
/bin/sh -c "while true; do echo hello world; sleep 1; done"

위의 명령어를 통해 서비스를 생성했다면 서비스의 목록을 확인해 방금 생성한 서비스가 정상적으로 구동되고 있는지를 확인해 보자. 스웜 클러스터 내의 서비스 목록은 docker service ls 명령어로 확인할 수 있다.

docker run 명령어를 사용했을 때처럼 서비스의 이름을 따로 정의하지 않았기 때문에 서비스의 이름이 sad_williamson와 같이 무작위로 설정된 것을 볼 수 있다. 서비스의 자세한 정보를 확인하려면 docker service ps [서비스 이름]과 같이 입력하면 된다.

docker service ps [service name]

이 명령어를 통해 서비스 내의 컨테이너의 목록, 상태, 컨테이너가 할당된 노드의 위치 등의 정보를 알 수 있다. 

생성된 서비스를 삭제하려면 docker service rm 명령어를 입력하면 된다. 

Nginx 웹 서버 서비스 생성하기

위에서 ubuntu 컨테이너를 생성해 컨테이너 내부에서 단순히 'hello world'를 출력하도록 설정했으나, 서비스의 레플리카셋을 정의하지 않았기 때문에 1개의 컨테이너만 생성되었다. 이번에는 docker service create 명령어에 --replica 옵션을 추가하고 Nginx 웹 서버 이미지를 이용해 서비스를 만들어보자.

다음 예제는 2개의 레플리카 컨테이너를 정의하고 서비스의 이름을 myweb으로 설정하며 컨테이너의 80번 포트를 각 노드의 80번 포트로 연결하는 서비스를 생성할 것이다

docker service create --name myweb \
--replicas 2 \
-p 80:80 \
nginx

. 위의 명령어를 통해 컨테이너가 정상적으로 생성되면 스웜 클러스터 내의 노드 중 하나를 선택해 80번 포트로 접근해 Nginx 웹 서버가 구동되고 있는 것을 확인할 수 있다.

nginx 컨테이너가 manager 노드와 worker1 노드에 생성된 것을 볼 수 있다. 하지만 꼭 이 두 노드의 IP 주소로 접근해야만 Nginx 웹 서버에 접근할 수 있는 것은 아니다. docker service create 명령어에서 -p 80:80 옵션을 통해 스웜 클러스터 자체에 포트를 개방했다고 생각하면 쉽게 이해할 수 있다. 즉, 스웜 클러스터 내의 어떠한 노드로 접근해도 위 서비스의 웹 서버에 접근할 수 있다. 이를 직접 확인하기 위해 다른 worker2 노드의 IP 주소로 nginx에 접근해 보자.

Nginx 컨테이너가 없는 워커 노드로 접근해도 서비스에 접근할 수 있음을 확인할 수 있다. 

그렇다면 서비스 내의 Nginx 컨테이너를 4개로 늘리면 어떻게 될까? docker service scale 명령어를 이용하면 레플리카셋의 수를 늘리거나 줄일 수 있다. 아래와 같이 입력해 컨테이너의 수를 늘린 뒤 서비스 내의 컨테이너 목록을 확인해 보자.

docker service scale myweb=4

swarm-worker2 노드에 2개의 컨테이너가 할당된 것을 볼 수 있다. 만약  각 노드의 80번 포트로 요청이 들어오면, 호스트는 위의 4개의 컨테이너 중 하나로 리다이렉트한다. 따라서 각 호스트의 어느 노드로 접근하든 4개의 컨테이너 중 1개에 접근하게 된다.

스웜 모드의 서비스 장애 복구

복제 모드로 설정된 서비스의 컨테이너가 정지하거나 특정 노드가 다운되면 스웜 매니저는 새로운 컨테이너를 생성해 자동으로 장애가 생긴 컨테이너를 복구한다. 위에서 생성한 myweb 서비스 중 컨테이너 하나를 삭제해 보자.

컨테이너를 종료한 뒤, 다시 myweb service의 상태를 확인해 보면 새로운 컨테이너가 생성되었음을 확인할 수 있다.

특정 노드가 다운 됐을 때도 위와 같은 방식으로 작동한다. 3개의 노드 중 swarm-worker1 노드의 도커 데몬 프로세스를 종료해 임의로 노드 장애 상태를 만들어보자.

service docker stop

매니저 노드에서 docker node ls 명령어를 입력하면 swarm-worker1 노드의 상태가 Down으로 바뀐 것을 확인할 수 있다. 여기서 docker service ps 명령어로 다시 서비스의 컨테이너 목록을 확인해 보면, swarm-worker1에서 구동 중이던 컨테이너가 종료됐으며, 이를 복구하기 위한 컨테이너가 swarm-manager 노드에 생성됐음을 확인할 수 있다.

여기서 다운됐던 노드를 다시 시작해 정상적인 상태로 회복해도, 장애를 복구하기 위해 다른 노드로 옮겨진 컨테이너가 해당 노드에 자동으로 할당되지는 않는다. 새로운 노드를 추가하거나, 다운됐던 노드를 다시 복구했을 때 서비스의 컨테이너 할당의 균형을 맞추기 위해서는 아래와 같은 scale 명령어를 이용해 컨테이너의 수를 줄이고, 다시 늘려야 한다.

docker service scale myweb=1
docker service scale myweb=4

 

Ref : 시작하세요! 도커/쿠버네티스

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함