0. Intro
지금까지 Docker 사용은?
보통 Docker를 이용해 웹 프로젝트를 배포할 때, 다음과 같은 과정을 진행한다.
- Docker File을 작성하고, 이를 통해 Docker Image를 생상한다.
- Docker Image를 Docker Hub나 외부 Docker Registry에 이미지를 등록한다.
- 원하는 서버에서
docker run
이나docker-compose up
명령어를 통해 컨테이너를 실행한다.
하지만 이 방법만으로는 서비스를 안전하게 운영하기 쉽지않다.
왜냐하면 서비스를 업데이트 하는 과정에서 무중단으로 배포하지 못할 뿐더러, 사용자가 많아지게 되면 서버 과부하로 정상적인 서비스를 제공하지 못하기 때문이다.
이러한 한계를 극복하기 위해 컨테이너 오케스트레이션 도구가 필요하며, Docker Swarm은 그 해결책 중 하나이다.
1. Container Orchestration
여기서 컨테이너 오케스트레이션은 다수의 컨테이너를 자동으로 배포, 확장, 관리할 수 있도록 도와주는 기술이며 다음과 같은 역할을 한다.
1️⃣스케쥴링: 컨테이너를 실행할 최적의 노드를 자동으로 선택하여 배치한다. 이를 통해 서버 자원을 효율적으로 활용하고 가용성을 높인다.
2️⃣클러스터링: 여러 서버를 하나의 클러스터로 묶어 관리함으로써, 분산 환경에서 자원을 통합적으로 운영할 수 있다.
3️⃣로드 밸런싱: 클러스터 내 여러 노드에 배포된 컨테이너로 들어오는 트래픽을 분산하여 리소스 사용을 최적화한다.
4️⃣서비스 디스커버리: 컨테이너의 IP 주소, 포트, 서비스 이름 등을 자동으로 관리하여, 서로 다른 컨테이너나 서비스 간의 연결을 쉽게 설정할 수 있도록 지원한다.
5️⃣모니터링 및 로깅: 각 컨테이너와 노드의 상태, 성능, 로그 정보를 실시간으로 수집 및 분석한다.
이 외에도 자동 스케일링, 롤아웃/롤백, 자동 복구, 보안 및 네트워크 관리 등 다양한 기능을 포함하여, 대규모 컨테이너 환경을 안정적이고 효율적으로 운영할 수 있도록 돕는다.
대표적인 컨테이너 오케스트레이션 도구로 Docker Swarm, Kubernetes, AWS EKS 등이 있다.
2. Docker Swarm 선택 이유
쿠버네티스는 컨테이너 오케스트레이션 도구로서 컨테이너 기반 인프라 시장에서 사실상의 표준으로 자리 잡았다.
그렇다면 왜 Docker Swarm을 선택하는가?
2.1 간단한 설치와 설정
쿠버네티스 만큼은 아니더라도, 여러 대의 호스트로 구성된 중소 규모의 클러스터에서 컨테이너 기반 애플리케이션 구동을 제어하기에 충분한 기능을 갖추고 있다. 도커 엔진(Docker Engine)이 설치된 환경이라면 별도의 구축 비용 없이 스웜 모드(Swarm Mode)를 활성화하는 것만으로 시작할 수 있다.
2.2 Docker CLI 친화적
도커 컴포즈(Docker Compose)를 사용해 본 사람이라면 도커 스웜(Docker Swarm)의 스택(Stack)을 이용한 애플리케이션 운영에 곧바로 적응할 수 있다.
2.3 단일 노드 클러스터부터 다중 서버 클러스터까지
도커 데스크탑(Docker Desktop)으로도 클러스터 관리와 배포가 모두 가능한 단일 노드 클러스터를 바로 만들 수 있다.
따라서 최소한의 자원으로 컨테이너 오케스트레이션 환경을 만들어 시험해볼 수 있다는 장점이 있다.
3. Docker Swarm 구성 요소 및 용어
3.1 노드(Node)
클러스터를 구성하는 개별 도커 서버를 의미하며 매니저 노드 (Manager Node) / 워커 노드 (Worker Node)가 있다.
- 매니저 노드(Manager Node)
클러스터 관리와 컨테이너 오케스트레이션을 담당한다. 쿠버네티스의 마스터 노드(Master Node)와 같은 역할이라고 할 수 있다. 매니저 노드는 필요에 따라 워커 노드의 역할도 겸할 수 있지만, 클러스터 관리와 스케줄링 업무가 집중되므로 보통 별도의 노드로 구성하는 것이 좋다.
- 워커 노드(Worker Node)
컨테이너 기반 서비스(Service)들이 실제 구동되는 노드를 의미한다. 쿠버네티스와 다른 점이 있다면, Docker Swarm에서는 매니저 노드(Manager Node)도 기본적으로 워커 노드(Worker Node)의 역할을 같이 수행할 수 있다는 것이다. 물론 스케줄링을 임의로 막는 것도 가능하다.
3.2 서비스(Service)
도커 스웜에서의 기본적인 배포 단위로 노드에서 수행하고자 하는 작업들을 정의해놓은 것이다. 클러스터 안에서 구동시킬 컨테이너 묶음을 정의한 객체라고 할 수 있다. 하나의 서비스는 하나의 이미지를 기반으로 구동되며, 서비스 생성 시 지정한 설정에 따라, Swarm 매니저는 해당 서비스를 여러 노드에 분산시켜 배포한다.
3.3 스택(Stack)
하나 이상의 서비스(Service)로 구성된 다중 컨테이너 애플리케이션 묶음을 의미한다. 도커 컴포즈(Docker Compose)와 유사한 양식의 YAML 파일로 스택 배포를 진행한다.
3.4 태스크(Task)
클러스터를 통해 서비스를 구동시킬 때, 도커 스웜은 해당 서비스의 요구 사항에 맞춰 실제 마이크로서비스가 동작할 도커 컨테이너를 구성하여 노드에 분배하며 이것을 태스크(Task)라고 한다. 하나의 서비스는 지정된 복제본(replica) 수에 따라 여러 개의 태스크를 가질 수 있으며, 각각의 태스크에는 하나씩의 컨테이너가 포함된다.
다시 말해 서비스가 실행될 때 매니저 노드가 할당하는 단위 작업으로, 하나의 태스크는 하나의 컨테이너 인스턴스를 의미하며, 서비스의 레플리카 수 만큼 생성된다.
3.5 레플리카(Replica)
서비스 내에서 실행되는 동일한 컨테이너(태스크)의 개수를 의미하며, 애플리케이션의 부하를 분산시키고, 고가용성을 확보하기 위해 여러 복제본을 실행한다. 예를 들어, 서비스가 3개의 레플리카를 지정하면 매니저 노드는 가능한 워커 노드에 3개의 동일한 태스크를 스케줄링하여 배포한다.
3.6 네트워크(Ingress Network)
Ingress 네트워크는 swarm cluster를 생성하면 자동으로 생성되는 네트워크로 swarm 모드일 때만 유효하다. docker network ls
명령어를 통해 네트워크 목록을 확인해보면 Ingress 네트워크의 SCOPE가 swarm으로 설정되 있는 것을 볼 수 있다.
bash
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
ff375eddfda6 bridge bridge local
5cba1cb002ce host host local
dqjjhx24frzq ingress overlay swarm
Ingress 네트워크는 각 노드에 내장되어있는 로드 밸런서를 통해 서비스내의 컨테이너들 간에 라운드 로빈(round-robin) 방식으로 로드 밸런싱을 수행하며,
외부에서 특정 포트로 들어온 요청을 클러스터 내의 적절한 컨테이너(태스크)로 전달하는 라우팅 메시(Routing Mesh) 기능과 연계되어 동작한다.
3.7 포트(Port)
- 2377/tcp : 클러스터 관리에 사용되는 포트다.
- 7946/tcp, 7946/udp : 노드 간 통신에 사용된다.
- 4789/udp : 클러스터에서 사용되는 Ingress 오버레이 네트워크 트래픽에 사용된다.
4. Docker Swarm 사용법 및 주요 명령어
4.1 Swarm 모드 활성화
bash
docker swarm init
스웜 모드 활성화가 완료되면 아래와 같은 안내문이 출력되며, 이 명령어를 실행한 해당 노드는 매니저 노드로 전환된다.
bash
Swarm initialized: current node (9yubq203dgcl82o3n2bb2s31w) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-xxxxxxxxxxxxxxxxxxxx 172.31.14.44:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
다른 서버에서 클러스터에 참여하려면 매니저 노드에서 제공하는 토큰을 사용하면 된다.
4.2 노드 추가 및 관리
bash
// 워커 노드 추가:
docker swarm join --token <worker-token> <manager-ip>:2377
// 매니저 노드 추가:
docker swarm join-token manager
docker swarm join --token <manager-token> <manager-ip>:2377
bash
docker node ls // 전체 노드 보기
docker node inspect {nodeId} // 노드별로 자세한 정보
docker node rm {nodeId} // 노드 삭제 (매니저 노드경우만 가능)
4.3 서비스 생성 및 관리
- 서비스 생성
bash
docker service create \
--name=chatservice \
--replicas=3 \
--publish=8080:8080/tcp \
--constraint=node.role==manager \
--mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
--env jasypt.password=jasyptchatkeyexample \
murphytklee/chat-challenge:0.2
-name
은 서비스 이름을 지정-replicas
는 실행할 컨테이너 수를 지정-publish
옵션은 호스트와 컨테이너 포트를 매핑-constraint
는 특정 노드(예, manager 노드)에서만 실행하도록 제한할 수 있다.
- 서비스 관리
bash
// 전체 서비스 조회: (매니저 노드 경우만 가능)
docker service ls
// 서비스 제거: (매니저 노드 경우만 가능)
docker service rm
// 서비스 로그 보기: -f는 --follow로 실시간으로 계속 보겠다는 뜻 ^C로 나갈 수 있다.
docker service logs -f <service-name>
// 서비스 업데이트: 실행 중인 서비스를 새로운 이미지로 업데이트 할 수 있다. (무중단 배포를 위해 Rolling Update 방식 지원)
docker service update --image <new-image> --with-registry-auth <service-name>
// 서비스 스케일 조정: 서비스에 할당된 컨테이너 수를 늘리거나 줄일 수 있다.
docker service scale <service-name>=<number-of-replicas>
// 현재 서비스의 컨테이너들과 상세정보 확인 :
docker service ps <service-name>
//실행 중인 모든 컨테이너의 실시간 상태를 보여주며, 각 컨테이너별 CPU 사용률, 메모리 사용량 등을 확인할 수 있다.
docker stats
//그외
docker service inspect <service-name>
4.4 스택 배포
Docker Swarm에서는 docker stack deploy
명령어를 사용하여 Docker Compose와 유사한 방식으로 다중 서비스 애플리케이션을 배포할 수 있다.
bash
docker stack deploy -c docker-compose.yml <stack-name>
4.5 visualizer
Docker Swarm Visualizer는 클러스터 내의 노드, 서비스, 태스크(컨테이너) 등의 상태를 그래픽 형태로 표시하여 사용자는 각 노드에 배포된 컨테이너의 분포, 서비스 상태, 작업(Task)의 실행 상황 등을 한눈에 파악할 수 있다.
bash
docker service create \
--name=viz \
--publish=5000:8080/tcp \
--constraint=node.role==manager \
--mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
dockersamples/visualizer
컨테이너 실행 후 웹 브라우저에서 http://{호스트 IP}:{Port}으로 접속하면 시각화된 클러스터 정보를 확인할 수 있다.
Docker Swarm Visualizer는 주로 데모 및 학습 목적으로 개발되었으며, 실 운영 환경에서는 추가적인 보안 및 성능 검증이 필요하기에 주의하자.
'DevOps' 카테고리의 다른 글
[Docker] Container Network, localhost대신 host.docker.internal을 써야하는 이유(docker0, veth, eth0) (0) | 2025.02.12 |
---|