Docker의 Swarm이란
최근 쿠버네티스에 대해 다루었는데 이번에는 도커 자체적으로 제공하는 오케스트레이션 툴인 "docker swarm"에 대해 다루겠다! 쿠버네티스와 무엇이 다른지도 짚어볼 생각이다.
도커에서도 쿠버네티스와 같이 여러 대의 서버 자원을 합쳐 하나의 클러스터로 만들어서 자원을 병렬로 확장할 수 있다. 도커 스웜은 도커 엔진 자체적으로 내장된 기능이다. 클러스터 관리, 자동화, 고가용성 및 확장성을 제공한다.
아래와 같이 스웜 모드 클러스터 정보를 출력해보면 기본적으로 비활성 상태인 것을 알 수 있다.
docker info | grep Swarm
Swarm : inactive # 출력
구조
도커 스웜 모드는 기본적으로 "매니저 노드"와 "워커 노드"로 구성돼 있다. 워커 노드는 실제 컨테이너가 생성되고 관리되는 서버이며, 매니저 노드는 워커 노드를 관리하기 위한 도커 서버다. 참고로, 매니저 노드에서도 컨테이너 생성이 가능하다. 매니저 노드는 워커 노드의 역할도 있는 것이다.
운영 환경에서는 매니저 노드를 다중화하는 것을 권장한다고 한다. 이는 매니저 노드의 부하를 분산할 뿐만 아니라 특정 매니저 노드가 다운됐을 때. 정상적으로 스웜 클러스터를 유지할 수 있기 때문이다! 다만 성능이 좋아지는 것은 아니다. 어디까지나 고가용성 및 장애 대비일 뿐이다.
도커 스웜 모드에서는 매니지 노드의 절반이 장애로 인해 정상동작하지 못한다면 해당 매니저 노드가 복구될 때까지 클러스터 운영을 중단한다. 그러나 홀수 개로 구성했을 때. 과반수 이상이 유지되는 쿼럼 매니저에서 운영을 계속할 수 있기 때문에 가능한 한 홀수 개로 구성하는 것이 권장된다고 한다. 물론 홀수 개로 유지하는 이유는 더 있다. 아래 공식 문서를 참고하자.
https://docs.docker.com/engine/swarm/admin_guide/
[Administer and maintain a swarm of Docker Engines
Manager administration guide
docs.docker.com](https://docs.docker.com/engine/swarm/admin_guide/)
리더 역할의 매니저 노드가 장애 등으로 다운됐을 때 새로운 리더 노드를 선출하는데 이때 리더 선출 및 고가용성 보장을 위한 Raft Consensus 알고리즘이 사용된다. 위의 공식문서에서 한 번 가볍게 읽어보길 바란다.
간단한 클러스터 구축
매니저 노드 하나만 생성하여 클러스터를 구축해보자. 다음 명령어를 사용해서 매니저 역할을 수행할 서버에 스웜 클러스터를 활성화해준다.
docker swarm init --advertise-addr <IP_주소> # 예로 192.168.10.1
Swarm initialized: current node (bvz81updecsj6wjz393c09vti) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx 172.17.0.2:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
만약 ip 주소가 2개 이상이라면(네트워크 인터페이스 카드가 2개 이상이란 것), 어느 ip 주소로 접근할지 다른 노드에 알려줄 필요가 있다. 물론 private ip, public ip 중 후자를 알려줘야 한다.
위 예제에서 보이듯이 새로운 워커 노드를 클러스터에 추가하려면 docker swarm join 같은 명령어를 실행해야 한다. --token 옵션에 사용된 토큰 값은 새로운 노드를 클러스터에 안전하게 추가하기 위한 보안키이다.
스웜 매니저는 다음과 같은 포트를 사용한다. 클러스터 구성하기 전에 반드시 해당 포트들을 각 호스트 머신에서 열어둬야 한다.
- 2377/TCP: 클러스터 관리 포트
- 7946/TCP|UDP: 노드 간 통신 포트
- 4789/UDP: 클러스터에서 사용되는 Ingress 오버레이 네트워크 트래픽 포트
매니저 노드로서 클러스터에 추가
매니저 토큰을 사용해서 호스트 머신을 클러스터에 매니저 노드로써 추가할 때는 다음과 같다. docker node ls 명령어로 상세 정보를 확인할 수 있다.
docker swarm join --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2 192.168.99.121:2377
This node joined a swarm as a manager.
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
dkp8vy1dq1kxleu9g4u78tlag * manager2 Ready Active Reachable
dvfxp4zseq4s0rih1selh0d20 manager1 Ready Active Leader
워커 노드로서 클러스터에 추가
워커 토큰을 사용하면 호스트 머신을 워커 노드로서 클러스터에 추가할 수 있다.
docker swarm join --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx 192.168.99.121:2377
This node joined a swarm as a worker.
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
7ln70fl22uw2dvjn2ft53m3q5 worker2 Ready Active
dkp8vy1dq1kxleu9g4u78tlag worker1 Ready Active Reachable
dvfxp4zseq4s0rih1selh0d20 * manager1 Ready Active Leader
Swarm 모드의 Service
스웜 모드에서 제어 단위는 컨테이너가 아니라 서비스다. 서비스는 같은 이미지에서 생성된 컨테이너의 집합이다. 다시 말해, 서비스 내에는 컨테이너가 1개 이상이며, 이러한 컨테이너들을 태스크 Task라고 칭한다. 서비스를 제어하면 서비스의 태스크에 같은 명령이 수행된다.
이런 서비스를 생성하려면 매니저 노드에서만 가능하며 docker service로 시작하는 명령어를 사용해야 한다.
docker service create --name redis redis:7.4.1
dmu1ept4cxcfe8k8lhtux3ro3
docker service create --mode global --name redis2 redis:7.4.1
a8q9dasaafudfs8q8w32udass
docker service ls
ID NAME MODE REPLICAS IMAGE
dmu1ept4cxcf redis replicated 1/1 redis:7.4.1
a8q9dasaafud redis2 global 1/1 redis:7.4.1
서비스 내 컨테이너(태스크)에서는 detached 모드(-d 옵션)로 동작할 수 있는 이미지여야 한다!
그렇지 않고 생성하려 한다면 컨테이너 내부를 차지하고 있는 프로세스가 없어서 컨테이너가 정지될 것이고, 스웜 매니저는 장애로 판단하여 계속 생성을 반복할 것이다.
도커 스웜 네트워크
도커 스웜 네트워크의 개념
도커 스웜(Docker Swarm)은 여러 개의 노드에 같은 컨테이너를 분산해서 할당하기 때문에 각 노드를 하나로 묶어줄 네트워크가 필요하다
네트워크는 그물을 뜻하는 Net와 Work의 합성어로 컴퓨터, 스마트폰, 서버 등의 디지털 장치들이 데이터를 주고 받기 위해 연결되는 시스템을 말한다
스웜 모드에서는 서비스를 외부에서 접근할 때 어느 노드로 접근하더라도 해당 서비스의 컨테이너에 접근할 수 있게 라우팅 기능이 필요하다
이러한 네트워크 기능은 스웜 모드가 지원하는 네트워크를 통해 사용할 수 있다
도커 스웜 네트워크 종류
네트워크 목록은 다음 명령으로 확인할 수 있다
docker network ls
NETWORK ID NAME DRIVER SCOPE
ff375eddfda6 bridge bridge local
09bdaeed02a3 docker_gwbridge bridge local
5cba1cb002ce host host local
dqjjhx24frzq ingress overlay swarm
8cc024d7d9e7 none null local
1. Ingress 네트워크
Ingress 네트워크는 스웜 클러스터를 생성하면 자동으로 생성되는 네트워크로서, 스웜 모드를 사용할 때만 유효하다
이 네트워크의 주요 특징은 다음과 같다
- 스웜 클러스터에 노드가 추가되면 해당 노드는 자동으로 해당 클러스터의 Ingress 네트워크에 등록된다
- 각 노드에 내장되어있는 로드 밸런서를 통해 서비스내의 컨테이너들 간에 라운드 로빈 방식으로 로드 밸런싱을 수행한다
- 노드에 실행중인 서비스가 없더라도 Ingress 네트워크에서 실행되고 있는 모든 서비스에 대한 포트를 오픈하는 routing mesh 기능을 제공한다
- Overlay 네트워크 드라이버를 사용하는 Overlay 네트워크의 일종이다
2. Overlay 네트워크
Overlay 네트워크는 여러 Docker 서버가 있는 노드 간에 네트워크 트래픽을 라우팅하는 Swarm 서비스를 위한 주요 네트워크다
주요 특징은 다음과 같다
- 서로 다른 Docker 서버가 있는 컨테이너가 마치 같은 물리적 호스트에 있던 것처럼 통신할 수 있다
- 컨테이너는 외부에 포트를 오픈하지 않아도 되고, 연결되는 다른 컨테이너와(예: 웹과 DB) 다른 노드에 있어도 같은 서버에 있는 것처럼 통신할 수 있다
3. docker_gwbridge 네트워크
docker_gwbridge 네트워크는 Ingress 네트워크를 포함한 모든 Overlay 네트워크와 함께 사용된다
- 도커 데몬(도커 호스트 혹은 노드)에 물리적으로 연결되는 가상의 네트워크다
- 외부로 나가는 통신 및 Overlay 네트워크의 트래픽 종단점(VTEP, VXLAN Tunnel End Point) 역할을 담당한다
- 스웜 클러스터를 init하거나 join할 때 자동으로 생성된다
- Overlay 네트워크를 개별 도커 데몬의 물리적 네트워크에 연결한다
도커 스웜 볼륨
볼륨의 개념 및 필요성
도커 볼륨(Volume)은 컨테이너의 파일시스템 외부에 위치하는, 데이터를 영구적으로 저장하기 위한 특별한 메커니즘이다
도커 볼륨은 컨테이너가 재시작되거나 삭제되더라도 데이터를 유지할 수 있고, 여러 컨테이너 간에 손쉽게 데이터 공유도 가능하다
도커 이미지는 여러 읽기 전용 레이어의 합으로 이루어지며, 컨테이너를 실행할 때 읽기/쓰기 레이어가 추가된다
이 읽기/쓰기 레이어는 일반적으로 일시적(휘발성)이기 때문에 컨테이너가 삭제되면 데이터도 함께 삭제된다
따라서 데이터베이스나 로그, 업로드 파일처럼 영구적으로 보관해야 할 데이터는 컨테이너가 재시작되거나 삭제되더라도 없어지지 않도록 볼륨을 사용한다
스웜 모드에서의 볼륨 타입
1. volume 타입의 볼륨
스웜 모드에서는 서비스를 생성할 때 도커 볼륨을 사용할지, 호스트와 디렉터리를 공유할지를 명확하게 명시해야 한다
volume 타입은 다음과 같이 사용한다
docker service create \
--name mysql \
--mount type=volume,source=mysql-data,target=/var/lib/mysql \
mysql:5.7
volume 타입의 특징
- source는 사용할 볼륨(도커 데몬에 해당 볼륨이 존재하면 해당 볼륨을 사용하고 없으면 새로 생성)
- target은 컨테이너 내부에 마운트될 디렉터리 위치
- source 옵션을 명시하지 않으면 임의의 16진수로 구성된 익명의 이름을 가진 볼륨을 생성한다
- 서비스의 컨테이너에서 볼륨에 공유할 컨테이너의 디렉터리에 파일이 이미 존재하면 이 파일들은 볼륨에 복사되고, 호스트에서 별도의 공간을 차지하게 된다
2. bind 타입의 볼륨
바인드 타입은 호스트와 디렉터리를 공유할 때 사용한다
docker service create \
--name nginx \
--mount type=bind,source=/root/host,target=/root/container \
nginx:latest
bind 타입의 특징
- type 옵션의 값을 bind로 설정한다
- 볼륨 타입과 달리 공유될 호스트의 디렉터리를 설정해야 하므로 source 옵션을 반드시 명시해야 한다
- 호스트의 디렉터리를 서비스 컨테이너의 지정된 디렉터리에 마운트한다
스웜 모드에서 볼륨의 한계점
스웜 모드에서 볼륨을 사용할 때 다음과 같은 한계점이 있다
- 서비스를 할당받을 수 있는 모든 노드가 볼륨 데이터를 가지고 있어야 하므로 스웜 클러스터에서 볼륨을 사용하는 것은 어렵다
- 로컬 볼륨이 존재하지 않는 노드에는 컨테이너가 할당될 수 없다
해결책 - 퍼시스턴트 스토리지 활용
일반적인 해법은 어느 노드에서도 접근 가능한 퍼시스턴트 스토리지를 사용하는 것이다
퍼시스턴트 스토리지의 특징
- 호스트와 컨테이너와 별개로 외부에 존재해 네트워크로 마운트할 수 있는 스토리지다
- 도커 자체가 제공하지 않으므로 서드파티 플러그인을 사용하거나 NFS, DFS 등을 별도로 구성해야 한다
- 스웜 매니저에 내장된 스케줄러가 컨테이너를 할당할 때 어느 노드에 할당해도 서비스에 정의된 볼륨을 사용할 수 있게 해준다
볼륨 드라이버를 사용하여 외부 스토리지(NFS, GlusterFS, Ceph, AWS EBS, Azure Disk, GCP Persistent Disk 등)를 연결할 수 있으며, 이를 통해 여러 노드에서 동일한 데이터에 접근할 수 있다
Swarm? Kubernetes?
swarm은 도커 엔진 자체에 내장돼 있지만 쿠버네티스는 별도의 설치가 필요하다. swarm이 구축 및 사용 자체는 간편하나 쿠버네티스만큼 다양하고 정교하진 않다. 당연하게도 쿠버네티스는 수천~수만 대 노드와 컨테이너를 관리할 수 있도록 설계됐기 때문이다. 따라서 쿠버네티스는 대규모 엔터프라이즈 환경에 적합하다. 도커 스웜은 그 자체로 간편해서 중소 규모의 프로젝트나 빠른 프로토타이핑에 적합하며, 대규모 환경에서는 한계가 있다.
정리하자면 이렇다.
- Docker Swarm: 소규모 프로젝트, 빠른 배포, Docker 친화적 환경, 학습 부담이 적은 팀에 적합.
- Kubernetes: 대규모 서비스, 멀티클라우드/온프레미스 혼합 환경, 고가용성 및 자동화가 중요한 엔터프라이즈 환경에 적합.
확실히 자원 사용 면에서는 auto scaling을 지원하는 쿠버네티스가 좋지만 리소스가 한정적이거나 auto scaling이 필요하지 않은 상황이라면 swarm도 충분히 좋은 선택이라고 생각한다.
뭐가 됐든 상황에 맞게 오버엔지니어링이 되지 않도록 적재적소할 수 있어야겠다.
'Docker' 카테고리의 다른 글
Docker 보안 강화하기 (0) | 2025.05.01 |
---|