도커 스웜, 매니저 노드 수를 홀수로 맞춰야 하는 이유
Manager·Worker 노드 구조, Raft 합의, 롤링 업데이트, Routing Mesh까지 Docker Swarm 운영을 실무 관점에서 정리한다
2026-08-12 · 최초 발행 2026-01-12
Docker CLI에 이미 익숙한 팀이 별도의 오케스트레이터를 새로 배우지 않고 클러스터를 굴리고 싶을 때 나오는 선택지가 Docker Swarm이다. Docker 1.12부터 Swarm Mode로 통합된 이 기능은 docker swarm init 한 줄로 여러 Docker 호스트를 하나의 가상 호스트처럼 묶는다. 원하는 상태(desired state)를 선언하면 나머지는 Swarm이 알아서 맞춘다는 선언적 서비스 모델이 핵심이다.
Swarm, Node, Service, Task로 구성된 모델
Swarm은 Docker 노드들의 클러스터이고 단일 가상 Docker 호스트처럼 동작한다. Node는 이 Swarm에 참여하는 개별 Docker 인스턴스로 Manager 또는 Worker 역할을 맡는다. Service는 실행할 컨테이너의 정의이자 원하는 상태의 명세이고, Task는 그 서비스의 개별 컨테이너 인스턴스로 스케줄링의 최소 단위다. 이 네 층위가 "web 서비스를 replicas 3으로 띄워라"라는 선언 하나가 실제로 Worker 노드 세 곳에 Task 세 개로 흩뿌려지는 과정을 설명한다.
Manager는 상태를 관리하고 Worker는 실행만 한다
Manager Node는 클러스터 상태 관리, 서비스 스케줄링, Swarm API 제공을 담당하며 Raft 합의 알고리즘으로 동작한다. Worker Node는 Manager로부터 작업을 받아 Task를 실행하고 상태를 보고할 뿐 Manager 역할은 수행할 수 없다.
Raft가 하는 일은 분산 시스템에서 여러 Manager 간 상태를 동기화하고 장애를 허용하는 것이다. Leader를 선출하고 과반수 합의로 결정을 내리는 구조라, N개의 Manager 노드가 있으면 (N-1)/2개까지 장애를 견딘다. 1개는 장애 허용이 0이라 개발용으로만 쓰고, 3개는 1개까지 장애를 허용해 프로덕션 최소 구성이며, 5개는 2개, 7개는 3개까지 견뎌 대규모 환경에 쓰인다. 여기서 Manager를 짝수로 늘리는 게 왜 의미가 없는지가 드러난다—과반수 계산 방식상 2개는 1개보다 나을 게 없고(둘 다 장애 허용 0), 4개는 3개와 장애 허용 수가 똑같다(둘 다 1개). Manager 수는 항상 홀수로 맞추는 이유다.
클러스터 구성하기
docker swarm init으로 첫 Manager를 세우면 Worker Token과 Manager Token 두 종류가 생성된다.
docker swarm init --advertise-addr <MANAGER-IP>
Worker는 이 토큰으로 참여한다.
docker swarm join --token <TOKEN> <MANAGER-IP>:2377
추가 Manager도 같은 방식으로 Manager Token을 받아 참여한다.
docker swarm join-token manager
docker swarm join --token <MANAGER-TOKEN> <MANAGER-IP>:2377
이후 docker node ls로 노드 목록을, docker node promote/demote로 Worker와 Manager 역할을 서로 전환하고, docker node rm으로 노드를 제거한다.
서비스는 replicas 숫자 하나로 관리한다
기본 생성은 간단하다.
docker service create --name web --replicas 3 -p 80:80 nginx
실무에서는 --env, --mount, --constraint, --update-parallelism, --update-delay 같은 옵션을 더해 배치 조건과 업데이트 방식까지 함께 정의하는 경우가 많다.
docker service create \
--name web \
--replicas 3 \
--publish 80:80 \
--env NODE_ENV=production \
--mount type=volume,source=web-data,target=/data \
--constraint 'node.role==worker' \
--update-parallelism 2 \
--update-delay 10s \
nginx:latest
docker service scale web=5로 레플리카 수를 조정하면 Scheduler가 현재 상태(3개)와 목표 상태(5개)의 차이만큼 Task를 추가로 만들어 Worker 노드에 배치한다.
# 레플리카 수 조정
docker service scale web=5
# 여러 서비스 동시 스케일링
docker service scale web=5 api=3 db=1
docker service ls/ps/inspect/logs/update/rm이 일상적인 관리 명령이다.
롤링 업데이트 옵션으로 위험을 조절한다
무중단으로 컨테이너를 순차 교체하는 롤링 업데이트는 update-parallelism(동시 업데이트 Task 수, 기본값 1), update-delay(업데이트 간 대기 시간, 기본값 0s), update-failure-action(실패 시 동작, 기본값 pause), update-order(업데이트 순서, 기본값 stop-first) 네 옵션으로 위험 수준을 조절한다. docker service update --image nginx:1.25 web으로 이미지를 바꾸고, 문제가 생기면 docker service rollback web으로 되돌린다.
# 이미지 업데이트
docker service update --image nginx:1.25 web
# 롤백
docker service rollback web
update-delay를 0으로 두면 순차 교체가 사실상 동시에 일어나는 것과 다를 바 없어지고, update-parallelism을 replicas 수만큼 크게 잡으면 롤링 업데이트가 아니라 일괄 교체가 된다는 점에서, 이 옵션들은 "얼마나 조심스럽게 배포할 것인가"를 그대로 숫자로 표현한다.
Overlay 네트워크와 Routing Mesh
Overlay 네트워크는 다중 호스트 간 통신을 지원하고 자동 서비스 디스커버리와 내장 DNS, 암호화를 제공한다.
docker network create --driver overlay --attachable my-network
Ingress 네트워크는 외부 트래픽을 받아 자동 로드 밸런싱을 하는데, 그 실제 동작 방식이 Routing Mesh다—퍼블리시된 포트를 모든 노드가 수신하도록 만들어, 어느 노드로 요청이 들어오든 실행 중인 Task로 라우팅해준다.
Stack은 Compose의 클러스터 버전이다
Docker Stack은 Docker Compose 파일 형식을 그대로 써서 다중 서비스·네트워크·볼륨을 클러스터 단위로 배포한다. docker-stack.yml에는 Compose와 달리 deploy 섹션(replicas, update_config, restart_policy, placement constraints)이 추가로 들어가는데, 이게 바로 롤링 업데이트 설정과 노드 배치 제약을 선언하는 자리다.
version: "3.8"
services:
web:
image: nginx:latest
deploy:
replicas: 3
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
ports:
- "80:80"
networks:
- webnet
api:
image: myapi:latest
deploy:
replicas: 2
networks:
- webnet
- backend
db:
image: postgres:14
deploy:
placement:
constraints:
- node.role == manager
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
networks:
webnet:
backend:
volumes:
db-data:
docker stack deploy -c docker-stack.yml myapp으로 배포하고 docker stack rm myapp으로 제거한다.
# 스택 배포
docker stack deploy -c docker-stack.yml myapp
# 스택 제거
docker stack rm myapp
Kubernetes와 나누는 경계선
두 도구 모두 컨테이너 오케스트레이션이지만 설치 복잡도, 학습 곡선, 기능 범위에서 확연히 갈린다. Swarm은 설치가 쉽고 학습 곡선이 완만하며 Docker와 네이티브로 통합되지만 기능은 기본적이고 자동 스케일링도 수동이다. Kubernetes는 설치가 복잡하고 학습 곡선이 가파르지만 포괄적인 기능과 훨씬 큰 커뮤니티·에코시스템, HPA 기반 자동 스케일링을 갖췄다. 소규모 팀이 Docker 기반 환경에서 빠르게 시작해야 하고 오케스트레이션 요구가 단순하면 Swarm이, 대규모 프로덕션에 복잡한 요구사항과 풍부한 에코시스템이 필요하면 Kubernetes가 맞는 선택이다.