1. 사전 준비물
Docker Swarm으로 클러스터를 운영하기 위해서 다음과 같은 요소들이 필요합니다.
2개 이상의 PC
Docker Swarm은 기본 Docker 시스템과 달리, 멀티 노드로 확장하는 클러스터 운영 프레임워크입니다. 따라서 호스트 머신 하나로는 구축이 의미가 없으며, 둘 이상의 PC를 배치하고 통신을 열어주던지, 또는 다수의 PC를 운영할 여력이 안 된다면 가상머신을 이용하는게 좋습니다.
가상머신으로 클러스터를 구성하고자 한다면 Vmware/VirtualBox*로 비어 있는 상태의 Linux를 미리 준비해두면 됩니다. 좀 더 간결한 가상머신 구축을 원한다면 *Docker Machine(지금은 더 이상 패치가 없다고 하네요 😪)을 활용하는 방법도 있으니, 이와 관련해서는 바로 다음 포스트에서 다루도록 하겠습니다.
본 실습에서는 3개의 VPC를 설치하였고 이들을 각각 1개의 Master 노드와 2개의 Worker 노드로 운영하고자 합니다. OS 이미지는 Debian 12 버전을 사용했습니다.
노드간 네트워킹 활성화
클러스터를 구축하려면 당연히 노드끼리 원활하게 통신이 되어야겠죠. 클러스터의 대표 IP 주소가 있어야하고, 여기저기 배치된 노드들은 해당 주소로 접근하여 클러스터에 join할 수 있습니다.
본 포스트처럼 VirtualBox 환경에서 작업을 한다면, 아래와 같이 VPC들을 같은 NAT Network로 묶어 통신이 가능토록 합니다.
파일 → 도구 → 네트워크 관리자
NAT 네트워크 → 상단의 *만들기* 클릭
생성된 NAT 네트워크의 대역은 10.0.2.0/24
입니다. 이 주소를 확인한 뒤, 각 VPC 별로,
설정 → 네트워크 → 네트워크 어뎁터를 NAT 네트워크(NatNetwork)로 변경 → 확인
VPC를 실행하여 네트워크 설정으로 들어가 NAT 네트워크 대역(ex., 10.0.2.0/24
)에 맞춰 고정 IP를 하나씩 할당해줍시다.
그리하여 아래와 같은 실습 환경이 만들어진 상태에서 Swarm 클러스터를 구축할 것입니다.
Docker Engine
Swarm은 Docker에서 제공하는 부가 기능이기 때문에, 실습 환경에 Docker Engine이 미리 설치되어 있어야 합니다. 아래 링크를 참조하여 Windows 기반 PC에서는 Docker desktop을 다운로드 받고, Linux 계열에서는 패키지 관리자로 docker를 설치하면 됩니다.
Master 노드 뿐만 아니라 Worker도 모두 docker-engine이 필요합니다. 제 경우, VPC가 debian 계열이므로 해당 가이드라인에 따라 docker 패키지를 설치하였습니다.
# Add Docker's official GPG key:
$ sudo apt-get update
$ sudo apt-get install ca-certificates curl gnupg
$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Add the repository to Apt sources:
$ echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
별 문제 없이 설치가 진행되었는지 확인합니다.
$ docker --version
2. Swarm 생성
Swarm 클러스터가 형성되기 위해 우선 어느 한 노드가 대표로 swarm init
을 선언해야 합니다. 여기서는 앞서 생성한 3개의 VPC 중에 ‘Master’가 그 역할을 맡을 겁니다.
# Master 노드에서
# docker swarm init --advertise-addr [Master 노드의 IP]
$ sudo docker swarm init --advertise-addr 10.0.2.10
swarm init
명령어를 치면 그 아래에 친절하게도 docker swarm join ~
명령어를 Worker 노드마다 수행하라고 안내해줍니다.
# Worker 노드에서
$ sudo docker swarm join --token [Token ID] [Master 노드 IP]:2377
Swarm 클러스터에 다른 호스트를 참여시키기 위해서는 token
이라는 긴 문자열이 필요합니다. token 정보를 잊어버렸더라도 Master 노드에서 아래 명령어를 통해 재확인이 가능합니다.
# Master 노드에서
$ sudo docker swarm join-token -q worker
현재까지의 Swarm 클러스터 상태를 체크해봅니다.
$ sudo docker node ls
3. Service 생성
Service를 생성하는 명령어는 docker service create
입니다. 단일 컨테이너를 배포할 때, docker run
이라는 명령어를 사용했을 텐데요. Service의 경우에도 크게 다르지 않습니다.
테스트도 해볼 겸, 가벼운 Apline 이미지를 서비스로 올려보겠습니다.
# Master 노드에서
$ sudo docker service create alpine ping 8.8.8.8
$ sudo docker service ls
서비스가 어떤 노드에게 할당되었는지 확인하기 위해 docker service ps
명령어를 사용합니다.
# Master 노드에서
$ sudo docker service ps [서비스 명]
worker2
에서 컨테이너가 잘 동작하고 있네요.
# worker2 노드에서
$ sudo docker container ls
이번에는 서비스를 확장(Scale-Up)시켜보겠습니다. 가만히 놀고 있는 노드들에게도 일을 시키기 위해서 replica
를 늘리는 일, 즉 프로세스를 복제할건데요. 이런 경우에는 docker service update
명령어를 사용합니다.
# Master 노드에서
$ sudo docker service update [서비스 명] --replicas 3
그래서 Service와 Container의 차이는?
지금까지만 보면, 그냥 각 노드에 똑같은 컨테이너를 하나씩 배포한 정도로밖에 보이지 않습니다.
그러나, Service 동작과 Container 동작의 결정적인 차이는 컨테이너를 하나 지워봄으로써 알 수 있습니다. Master 노드에서 생성된 컨테이너를 삭제하고 서비스의 상태를 확인해보면 Replica의 개수가 2/3
로 하나가 소실된 것처럼 보이지만, 조금 기다렸다가 다시 서비스를 조회해보면 Replica의 상태가 원상복귀되었음을 확인 가능합니다.
자세히 보면, 이후에 조회해본 컨테이너는 기존에 삭제했던 컨테이너와 ID는 다르지만 동일한 기능을 수행하고 있음을 알 수 있는데요. 이렇듯 Docker 서비스는 최초 생성했을 때의 명시했던 컨테이너 구성 요소와 역할과 관련된 전체 체계를 자동으로 유지해줍니다.
반면 docker run
으로 애플리케이션을 처음부터 컨테이너로 띄운 경우에는 컨테이너가 갑작스레 중단되거나 제거되더라도 복구해주지 않습니다.