서버/홈서버

[홈서버구축하기 6] Docker 및 Docker Swarm 설정하기

for2gles 2024. 1. 6. 20:38
반응형

홈서버 구축하기 시리즈


 

홈서버에서 서비스 운영을 위해서 나는 Docker 그리고 Docker Swarm 사용했다.
이번글에는 그 이유와, 사용법을 서술 해 보았다.

도커(Docker)를 사용 한 이유

도커를 사용하면 말도 못 할 정도의 많은 장점들이 있다.

  1. 처음으로 홈서버를 구축해보다 보니, 운영체제 재설치들이 잦았다.
    항상 동일한 환경을 구성하기 가장 좋은 방법은 도커를 사용하는 것 이었다.
  2. 배포하려는 프로그램 별로 구축 환경이 다를 수 있었다.
    예를들어 어떤 프로그램은 Node.js 20버전에서 돌아갈 수도 있고 어떤 프로그램은 Node.js 16버전에서 돌아갈 수도 있다.
  3. 이미 빌드되어있는 이미지를 활용해서 배포하는것은 너무 쉽고도 쉬웠다.
    도커 컴포즈만 있으면 동일한 시스템을 너무나도 쉽게 구축할 수 있었다.
  4. 컨테이너라는 가상 공간에서 프로그램이 작동하며 독립된 형태의 리눅스 환경을 갖는다는 아주 훌륭한 장점이 있다.
    이는 다른 프로그램과 엉키는 불상사를 사전에 방지할 수 있다.
  5. 독립된 내부 리눅스 환경과 필요한 경우 스토리지를 선택적으로 공유할 수 있음을 통해 데이터를 주입해줄 수 있다.

등등 정말 수많은 도커의 이점들이 있다.

여기에 한가지 친구를 더 활용하게 된다면 아주 환상적인 경험을 할 수 있다.

도커 스웜(Docker Swarm)을 사용 한 이유

Docker Swarm은 Kubernates 와 같이 오케스트레이션 툴이다.
모두가 흔히 알고 있는 쿠버네티스가 아닌 Docker Swarm을 사용 한 이유는, 일단 현 회사에서 Docker Swarm을 사용하고있다.
그래서 내가 구축하던 중 궁금한 점이 생긴다면 얼마든지 데브옵스 동료에게 물어볼 수 있었다.

그리고, 처음 홈서버를 구축 할 당시에는 도커의 커맨드도 잘 몰랐던 도린이(?)였다. 그런데 여기에서 도커를 제대로 이해하지도 못했는데 쿠버네티스까지 시도하는 것은 큰 난관이었다.

마지막으로, 내 서비스를 운영하는데에는 도커스웜이면 사실 충분하다는 확신이 있었다.
왜냐하면 이미 회사 서비스들도 도커 스웜으로 충분히 잘 운영되고 있기 때문이다.
물론 나중에는 쿠버네티스를 도전해 볼 것이다. 하지만 처음에는 도커 스웜을 통해 구축을 해 보게 되었다.

도커스웜을 사용하게되면 도커에는 없는 여러가지 이점이 생긴다.

  • Replica 서버를 운영할 수 있다. 클러스터로 작동하는 모양새인데, 하나의 포트에 여러개의 서버를 동시에 작동시키고, 그중 한개씩 배포를 진행함으로서 무중단 배포를 가능하게 해준다.
  • 여러개의 서버를 한번에 운영할 수 있게 된다. 1번서버에서 2번서버에 도커를 실행시켜 줄 수 있다. (이에서 오는 또다른 문제가 있기는 하다)
  • 알아서 여러 서버 중에서 알맞는 서버에 컨테이너들을 배치해준다.(똑똑하지는 않다.)

뭐 이런 장점들이 있었던 것 같다.

Docker 를 설치하기

도커 공식홈페이지에 나와있는 방법을 따라하면 굉장히 쉽다.
https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository```

# 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/ubuntu/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/ubuntu \
  $(. /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

최신버전을 다운로드 받기 위해서 이 친구를 실행해주면 이미 도커는 설치됐다.
만약에 기존 다른 서버에 설치된 도커가 있다면 버전을 맞춰 주는것이 좋다.
불필요한 버그를 방지할 수 있다.

깨알정보 - sudo 없이 도커를 사용하도록 설정

# ubuntu에는 본인의 리눅스 유저명을 사용하면 된다.
sudo usermod -aG docker ubuntu
# 재시동 없이 바로 적용
sudo -su ubuntu

Docker Swarm 사용하기

Initialize 하기

먼저 Docker Swarm을 초기화 해 주어야한다.
초기화 하는 서버는 기본적으로 Manager 및 Leader 서버가 되기 때문에 가장 주요 서버에서 해당 커맨드를 입력 해 주면 된다.

# VPN을 구축하지 않는 경우
docker swarm init

# VPN을 구축 한 경우
docker swarm init --advertise-addr ${해당 서버 vpn 사설 ip}

VPN을 구축하는 경우 --advertise-addr 라는 옵션을 줘야한다.

Pasted image 20240104173245.png


ChatGPT는 이렇게 말하고, 가장 중요한 기능은 노드 식별이다.
도커 스웜은 여러개의 서버들이 통신하는 그룹이 될 텐데, 서로 통신할 때 사용할 IP라고 이해하면 될 것 같다.
따라서 initialize를 하고 docker info 를 입력해보면, 내 아이피가 어떤것으로 설정되어있는지를 알 수 있다.

Join 하기

다른 서버를 해당 도커스웜에 가입시켜주기위해서는 먼저 Manager 노드에서 가입을 위한 토큰을 발급받아야한다.
해당 토큰을 가입하고자 하는 서버에 입력함을 통해 도커 스웜에 한 멤버가 될 수 있다.

먼저 Manager 서버에서 아래의 커맨드를 입력해줌으로서 토큰을 발급받아준다.
매니저와 워커의 토큰이 분리되어있어 원하는 노드 유형을 입력 해 주면 된다.

# manager node를 추가하고 싶을 경우
docker swarm join-token manager

# worker node를 추가하고 싶을 경우
docker swarm join-token worker

그러면 도커 스웜에서 아래와 같이 토큰과 함께 가입할 수 있는 커맨드를 리턴해준다.

Pasted%20image%2020240106144322.png


해당 커멘드를 이제 가입하고자 하는 서버에 입력해주기만 하면 가입이 되는 것이다.

docker swarm join --token SWMTKN-1-1qfn4kn5gqrmq0x14is61n7cgihwsjaacx5r4bxa9nk6ueq1b3-4i0ymp5nox2a7ej1hpjuvkjya 141.164.60.40:2377

단, VPN을 사용하는 경우 join 할 때에도 --advertise-addr ${해당 서버 vpn 사설 ip} 옵션을 추가 해 주어야 한다.

앞서 말했다시피 advertise-addr 는 내가 통신할 아이피를 도커스웜에 안내해주는 것이다. 만약에 해당 옵션을 설정하지 않는다면, 내 아이피는 의도하지 않은 다른 사설아이피 혹은 공개아이피로 등록될 것이고, 다른 서버에서 내 서버를 호출할 수 없을것이다.

 

정상적으로 등록이 된다면, 아래와 같은 응답이 즉각적으로 Response 될 것이다.

Pasted%20image%2020240106150240.png

만약 정상적으로 등록되지 않는다면, 10~20여초 후에 아래와 같이 에러와 함께 Timeout이 노출 된다.

Pasted%20image%2020240106150402.png


이는 방화벽에 막혀 도커스웜간의 통신이 불가하여 등록이 되지 않은 것이다.

VPN이 정상적으로 구축되어있다면, --advertise-addr 옵션을 잘 주었는지, 그리고 커맨드에 적혀있는 도커스웜 매니저 IP가 정확한지 다시 한번 확인해보자.
만약에 VPN이 아닌 로컬에서 운영되는 서버간 도커스웜 연결 중에 에러가 발생한다면, 아이피를 확인해보고 또한 운영체제 방화벽을 확인 해 보자.
도커스웜 사용 포트가 방화벽에 막혀있을 수도 있다.

Manager 와 Worker 차이

Manager: 실제로 노드들을 관리하고 컨테이너를 관리 및 배치 그리고 실패한 컨테이너늘 확인 후 복구하는 하는 능동적인 노드를 의미한다. 매니저 노드 서로를 확인해가며 문제여부를 판단하기 때문에 Manager 짝수가 된다면 과반수가 불가하여 운영이 불가해진다.
공식 문서에 따르면 3개의 Manager가 설정되어있을 경우 1개 Manager의 불능상태를 허용한다고 하고, 5개의 Manager가 설정되어있을 경우 2개 Manager의 불능상태를 허용한다고 한다. 그 이상 개수의 Manager노드가 불능상태가 된다면,스웜은 현재 정상작동상태를 보존하고자 하여 수정은 불가해지고 불능상태에 빠진 매니저노드가 복구되기를 기다린다.
Worker: 매니저노드에서 컨테이너 작동명령이 떨어지면 작동시키는 말 잘듣는 착한 친구이다. 따라서 컨테이너를 마음대로 실행시킬 수는 없고, 명령만을 기다리며 현재 서비스 목록 등을 전혀 알지 못하는 수동적인 노드이다.

도커 컴포즈 파일을 활용하여 배포하기

Docker Swarm과 Docker Compose는 비슷하면서 다르기 때문에 compose.yml 파일은 공유가 가능하지만 Docker Compose에서는 작동되지만 Docker Swarm에서는 작동하지않거나 다른 몇몇 차이점이 있다.
예컨데, build, depends_on 등은 Docker Swarm에서 작동하지 않는다.

여튼 docker compose 작성법에 관한 게시글은 많은 글들이 있으므로 넘어가도록 하겠다.
매니저 노드에서 아래의 커맨드를 입력해 배포를 해줄 수 있다.

docker stack deploy ${stack 이름} -c ${compose파일}

도커스웜에는 stack이라는 카테고리와 같은 개념이 있어 여러가지 시스템을 분리하여 배포하는것이 가능하다. 물론 네트워크 설정을 통해 스택간의 통신도 가능하다.

잘 배포되었는지는 아래의 커맨드를 통해 상태를 확인할 수 있다.

docker service ls

위 커맨드는 도커스웜 모든 노드에 작동중인 서비스 항목을 보여준다.
도커스웜을 여러개 서버에서 운영중이라면, 모든 서버에서 작동하고있는 도커 서비스 항목들을 위 커맨드를 통해 확인할 수 있는 것이다.

해당 노드에서 작동하고 있는 도커 컨테이너 목록들을 확인하고자 한다면 아래의 커맨드를 사용해 확인할 수 있다.

docker ps

도커스웜에 제약조건 걸기

도커스웜은 도커 컴포즈와 다르게 서버실행에 대해 제약조건을 걸어줄 수 있다.
예를들자면, "해당 서비스는 특정 노드에서만 실행하기", "해당 서비스는 특정 Label이 설정되어있는 노드에서만 실행하기" 와 같은 것이다.

deploy:
    placement:
        constraints:
            - "node.labels.project1==run"

서비스 설정에 위 항목을 추가 하면, project1=run 이라는 label이 설정되어있는 도커 노드에서만 해당 서비스를 실행시키는 것이다.

공유 스토리지의 필요성

나는 업로드 및 파일을 다운로드 할 수 있는 자그마한 홈페이지를 운영하고있다. 그리고, 도커 스웜에는 매니저노드 1개 워커 노드를 2개 가지고 있다고 가정 해보자.
매니저 노드에서 각 워커 노드에게 Replicate 컨테이너를 1개씩 할당 해주었다.

이 때 워커노드는 volume을 어디로 연결을 해주어야하는가?

 

만약 도커를 운영 해 보지 않았다면 이게 무슨 의문인지 이해가 가지 않을 수 있다.
그렇다면 이렇게 해보자 워커 노드 두개를 A워커노드 B워커노드 라고 불러보자.

유저의 업로드 요청이 처음에는 A워커노드로 전송되었다고 해보자. 그리고 다운로드 요청이 B워커노드로 전송된다면 유저는 파일을 어떻게 다운로드를 받을 수 있을까?

 

워커 노드를 자유롭게 이용하기 위해서는, 네트워크를 통한 서버간 스토리지 공유가 필요해진다.
네트워크 스토리지 시스템, 말로만 들으면 굉장히 복잡한 것 같지만, 사실 우리가 AWS를 쓰게 된다면 우리는 이미 경험 해보았다.
EC2를 사용한다면 EBS라는 스토리지 시스템을 사용 할 것이고, 이것이 이미 네트워크 파일 시스템이다.

Pasted%20image%2020240106152456.png


EBS는 Storage Area Network(SAN)이라는 기술을 활용해 네트워크 블록 스토리지를 사용하는 것이다.
단, 우리가 쉽게 사용했던 EBS는 단일 EC2인스턴스에만 연결할 수 있는 한계가 있어 우리가 목표하는 서버간 스토리지 공유는 불가능하다.

네트워크를 통한 스토리지 공유는 어떻게 할 수 있을까? AWS에서는 EBS말고도 EFS라는 또다른 스토리지 시스템이 있다.

Pasted%20image%2020240106153411.png


이는 NFS 프로토콜을 통해 구현된 파일레벨 스토리지이다. 블록스토리지와는 다르게 파일 락 및 충돌 방지 메커니즘이 포함되어있어 블록 스토리지와는 다르게 여러개 서버에 연결이 가능하다는 것이다.

이로서 자유롭게 도커스웜 아니 오케스트레이션 툴을 사용하기 위해서는 서버간의 스토리지 공유가 필요하고, 이를 위해 NFS라는 기술을 활용한다면, 여러개의 서버에서 하나의 스토리지를 공유하여 사용할 수 있다는 것을 알게 되었다.


 

반응형