Cloud Wave

여러 개의 서버를 다루는 방법? Docker Compose, Docker Swarm

eunmiee 2024. 1. 8. 23:52

 

이전 포스팅에 이어서 도커 스웜과 도커 컴포즈에 대해 정리를 해보도록 하겠습니다.

 

도커와 가상화, 도커 엔진에 대해 아직 자세히 모르시는 분들은 해당 포스팅을 참고해주세요!

2024.01.08 - [Cloud Wave] - 도커는 컨테이너인가요? 도커(Docker)란?(feat. 가상화)

 

도커는 컨테이너인가요? 도커(Docker)란?(feat. 가상화)

안녕하세요! 이번주는 벌써 cloudwave 4주차가 시작되었네요.. 시간이 참 빠르게 지나가고 있답니다.. 지난주부터 저는 docker와 docker compose, k8s에 대해 간단하게 배고 있는데요! 특히 docker는 졸업작

wldmsal.tistory.com

 

 

지체없이 바로 시작할게요!!

 

도커스웜(Docker Swarm)이란?


지금부터는 여러개의 서버의 도커 엔진에 대해 알아보도록 하자

하나의 호스트 머신에서 컨테이너가 많아져 자원이 부족하게 된다면 어떻게 해야할까?

 

자원을 늘리는 방법


  1. scale up
  • 매우 좋은 새로운 서버를 구매하는 것이다.
  • 한계점 : 자원의 확정성 측면이나 비용 측면에서 좋지 않음.
    • 자원이 부족할때마다 구매하거나 낭비가 될 수 있음

 

2. scale out

  • 여러대의 서버를 클러스터로 만들어 자원을 병렬로 확장하는 것
  • 예를 들어 4GB의 서버 한 대에 도커엔진을 설치하여 실제 운영환경에 사용한다고 가정해보자.
  • 이 1대의 서버에 컨테이너가 너무 많이 생성되어 자원이 부족하다고 할 때 다시 4GB의 서버를 추가하여 자원을 늘리는 것이다. 만약 놀고 있는 자원이 많다면 다시 줄이면 된다.

그런데 클러스터가 뭐지?

 

클러스터란?


  • 각기 다른 서버들을 하나로 묶어 하나의 시스템 같이 동작하게 하는 것
    • 클라이언트에게 고가용성 서비스를 제공할 수 있음
  • 동일한 네트워크 풀을 사용하면 요청에 따라 트래픽을 분산 시킬 수 있다

하지만 여러대의 서버를 하나의 자원 풀로 만드는 것은 쉬운 일이 아니다.

  • 도입의 어려움
    • 새로운 서버나 컨테이너가 추가될 때 발견하는 작업은 어떻게?
    • 스케줄러, 로드밸런서, 고가용성 보장을 어떻게?

다행히 이러한 문제를 해결해주는 오픈소스가 있는데, 그것이 바로 도커스웜이다!

  • 도커스웜은 스웜모드를 지원 → 도커엔진 자체에 내장되어 있음

 

스웜모드란?


  • 마이크로 서비스 아키텍처의 컨테이너를 다루기 위한 클러스터링 기능에 초점
  • 필요에 따라 유동적으로 컨테이너 수를 조절
  • 컨테이너로의 연결을 분산하는 로드밸런싱 기능을 자체적으로 지원
  • scale out은 기본적으로 지원하지만, 자체적으로 인스턴스를 늘리거나 줄일 수 없기 때문에 개발자가 직접 조절해야함.

 

스웜모드의 구조


  • 스웜모드는 매니저 노드와 워커 노드로 구성 되어 있다.
  • 워커 노드는 실제로 컨테이너가 생성되고 관리되는 도커 서버
  • 매니저 노드는 워커노드를 관리하기 위한 도커 서버
    • 매니저 노드는 기본적으로 워커 노드의 역할을 포함
    • 운영환경에서 다중화하여, 부하를 분산하고 특정 매니저 노드가 다운됐을 때, 정상적인 스웜 클러스터를 유지할 수 있기 때문이다.

 

클러스터 구축


  • aws EC2 인스턴스 4개가 준비되었다고 가정해보자
  • 우선 역할을 지정해 주어야한다.
    • 매니저 역할을 할 인스턴스를 1, 워커 노드의 역할을 할 인스턴스를 2,3,4로 지정했다고 해보자
  • 이제 역할을 할당해주자!
    1. 매니저 노드 설정
      • $ docker swarm init
    2. 워커 노드 설정
      • $ docker swarm join
      • 위의 명령어를 사용하여 워커노드를 추가할 수 있음
  • 이렇게 워커 노드를 추가함으로써 하나의 클러스터 단위가 완성되었다.

물론 매니저 노드도 하나의 클러스터 단위로 볼 수 있다.

여기서 우리는 이제 서비스를 시작할 수 있다.

그런데 서비스가 뭐냐구요?

 

서비스란?


일반적인 도커 명령어의 제어단위는 컨테이너이다.

이는 도커 클라이언트가 제어하는 것은 컨테이너라는 의미이다.

도커 스웜에서의 제어단위는 서비스이다.

서비스는 같은 이미지에서 생성된 컨테이너의 집합을 의미한다.

 

  • 서비스를 제어하면 해당 서비스 내의 컨테이너에 같은 명령이 수행
  • 이때 서비스 내의 컨테이너를 Task라고 부름
  • 서비스의 정의에 따라 테스크를 할당할 적합한 노드를 선정하고, 선택된 노드에 테스크를 분산하여 할당된다.
  • 함께 생성된 테스크를 레플리카(Replica)라고 하며, 서비스에 설정된 레플리카의 수만큼 테스크가 스웜 클래스 내에 존재해야함.

 

예제를 통해 더 이해해보자

  • 현재 SpringBoot는 모든 노드에 레플리카 3개, Nginx는 모든 노드에 레플리카 2개를 설정한 상태
  • 만약, 하나의 노드에 장애가 발생한다면?
    • 스웜은 서비스의 테스크들의 상태를 계속 확인하며 서버스 내에 정의된 레플리카 개수만큼 스웜 클러스터 내에 존재하지 않으면 새로운 테스크 레플리카를 생성한다.
    • 즉, 하나의 노드가 다운되면 다른 노드에 테스크를 생성하게 된다.
    • 그러나 매니저 노드가 다운이 된다면 클러스타가 사라지게 된다.
  • 그 외에도 클러스터 관리, 서비스 관리, 네트워크 관리, 노드 관리 등 다양한 기능들을 제공한다.

 

그렇다면 우리는 “스웜모드를 왜 써야할까?”

서비스의 확장/관리를 편하게 하기 위해 사용한다고 생각할 수 있다.

 

 

 

컨테이너를 어떻게 효율적으로 생성할 수 있을까?

 

각각의 서비스가 동작하기 위해서는 컨테이너가 필요하다.

서비스에 필요한 컨테이너가 1-2개 정도라면 도커 명령어를 직접 입력하여 생성할 수 있지만, 서비스가 여러개라면 이는 어려움이 발생한다.

 

위의 예제 그림을 살펴보더라도 하나의 프로젝트 단위를 클러스터 내에 묶었고 프로젝트가 구동되기 위해서는 springboot, nginx가 필요하다. 이 컨테이너들을 기반으로 테스크가 생성되기 때문이다.

매번 명령어를 통해 서비스에 필요한 컨테이너를 생성할 수 있지만 이는 비효율적이다.

위의 경우만 해도 2번의 명령어를 입력해야 한다.

이에 대한 해답으로 도커 컴포즈를 이용하면 수월해진다.

 

 

도커 컴포즈(Docker Compose)란?


  • 여러개의 컨테이너를 하나의 서비스로 정의
  • 스웜 모드와 비슷하게 설정 파일에 정의된 서비스의 컨테이너 수를 유동적으로 조절할 수 있다.
  • 서비스 디스커버리도 자동적으로 이루어진다.
  • 컴포즈는 도커 엔진 밖에 위치한다.
    • 도커에 내장되어 있지 않고 컴포즈를 직접 설치 해야함

flow


  • 도커 컴포즈는 컨테이너의 설정이 정의된 yml 파일을 읽어 도커엔진을 통해 컨테이너를 생성
    • 즉, 도커 컴포즈를 사용하기 위해서는 yml 파일을 작성해야함
    • example.yml → 스프링부트와 엔진엑스 서비스를 정의한 파일
    version: '3.0'
    services:
    	nginx:
    		image: nginx
    		...
    	springboot:
    		image: livenow/login-service:0.0
    		...
    
  • 파일을 작성한 후, 도커 컴포즈 명령어를 입력해 컨테이너를 생성할 수 있음
    • $ docker-compose up -d

이렇게 생성된 컴포즈의 구조는 다음과 같다.

  • 도커 컴포즈는 기본적으로 docker-compose.yml에 위치한 디렉터리 이름을 프로젝트 이름으로 사용한다.
  • 즉, yml 파일이 저장된 디렉터리에 이름에 따라 프로젝트의 이름이 달라지게 될 것이다.
    • 직접 설정도 가능하다.
  • 하나의 프로젝트는 여러개의 서비스로 이루어지고, 하나의 서비스에는 여러 개의 컨테이너가 존재할 수 있다.
    • 해당 그림의 컨테이너 안에 4개가 보이는데 각 컨테이너는 번호를 붙여 서비스 내의 컨테이너를 구별한다.

 

그렇다면 “도커 컴포즈를 왜 써야할까?"

 

이는 컨테이너의 생성을 편리하게 하기 위해서라고 말할 수 있다.

 


끝마침

 

이상으로 도커에 대한 포스팅은 여기까지 입니다!

다들 유익하셨나요?

 

항상 느끼는 거지만 도커를 잘 다루는 것, 즉 실습도 중요하지만 그 전에 가장 중요한 건 이론적으로 개념을 탄탄하게 잡아야하는 것이 중요해요! 지금은 당장 도커를 잘 하는 것 같아보여도 결국 뒤로 갈수록 부족했던 개념들에 의해 무너지면서 점차 힘들어지거든요..

 

늦더라도 탄탄하게! 기본기를 다져가면서 함께 공부해요!

 

오늘도 포스팅 읽어주셔서 정말 감사합니다!!

 

 

📚 참고

[10분 테코톡] ☂️ 검프의 Docker #이론편