Victoree's Blog

[7] Docker Swarm 본문

Infra/Docker

[7] Docker Swarm

victoree 2021. 5. 28. 15:09
728x90

Docker Swarm

도커 스웜

도커 스웜을 사용하는 이유

  • 여러 대의 서버를 클러스터로 만들어 자원을 병렬로 확장 및 관리하기
  • 적당한 성능의 서버 여러 대를 자원 풀로 만들어 사용 가능함
    • 여러 대의 서버를 하나의 자원의 풀로 만든다는 것
      • 새로운 서버나 컨테이너가 추가되었을 때, 이를 발견(Service Discovery)하는 작업
      • 어떤 서버에 컨테이너를 할당할 것인가에 대한 스케줄러와 로드밸런싱 문제
      • 클러스터 내의 서버가 다운되었을 때 고가용성을 어떻게 보장할 것인가
    • 도커 스웜과 스웜 모드 두 가지 솔루션이 존재함

스웜 클래식과 도커 클래식

  • 여러 대의 도커 서버를 하나의 클러스터로 만들어 컨테이너를 생성하는 기능을 제공
  • 컨테이너를 특정 도커 서버에 할당할 수있고, 유동적으로 서버를 확장할 수 있음
  • 분산 코디네이터
    • 여러 도커 서버를 하나의 클러스터로 구성할때의 각종 정보를 저장하고 동기화
    • 클러스터에 영입할 새로운 서버의 발견
    • 클러스터의 각종 설정 저장 및 데이터 동기화
    • etcd, zookeeper, consul등이 있음
  • 매니저
    • 클러스터 내의서버를 관리하고 제어
  • 에이전트
    • 각 서버를 제어
  • 스웜 클래식
    • 컨테이너로서의 스웜
    • 도커 1.6 이후부터 사용가능
    • 여러 대의 도커 서버를 하나의 지점에서 사용하도록 단일 접근점을 제공해줌
    • 도커 명령어(docker run / docker ps)와 도커 API로 클러스터의 서버를 제어하고 관리
  • 스웜 모드
    • 도커 버전 1.12 이후부터 사용 가능
    • 마이크로서비스 아키텍처의 컨테이너를 다루기 위한 클러스터링 기능에 초점
    • 같은 컨테이너를 동시에 여러 개를 생성해 필요에 따라 수를 조절
    • 로드 밸런싱 기능을 자체적으로 제공
    • 기본적으로 3대 이상의 카피를 안정적으로 추천함
  • 스웜 모드가 서비스 확장성과 안정성 등 여러 측면에서의 스웜 클래식보다 뛰어나기 때문에 일반적으로 스웜 모드를 더 많이 사용함
  • 스웜 클래식은 분산 코디네이터, 에이전트 등이 별도로 실행되어야 하나 스웜 모드는 클러스터링을 위한 모든 도구가 도커 엔진 자체에 내장되어 있음

도커 스웜 모드의 구조

  • 매니저 노드
    • 워커 노드를 관리하기 위한 도커 서버
    • 기본적으로 워커 노드의 역할을 포함하고 있음
    • 매니저 역할을 하는 노드와 리더 역할을 하는 노드로 구분
      • 리더 매니저는 모든 매니저 노드에 대한 데이터 동기화와 관리를 담당
      • 리더 매니저 서버의 다운의 경우, Raft Consensus 알고리즘으로 새로운 리더를 선출함
        • 리더 선출 및 고가용성 보장을 위한 알고리즘
  • 워커
    • 컨테이너가 생성되고 관리되는 도커 서버
  • 실제 운영환경에서는 매니저 노드를 다중화해야함
    • 매니저 부하를 분산하고 특정 매니저 노드가 다운되었을 때 정상적으로 스웜 클러스터를 유지할 수 있음
    • 단, 매니저 수가 증가한다고 해서 스웜 클러스터의 성능이 좋아지는 것은 아님
    • 매니저 노드의 절반 이상에 장애가 생겨 정상적으로 작동하지 못할 경우, 매니저 노드가 복구될 때까지 클러스터의 운영을 중단
      • 스웜 매니저는 홀수 개로 구성하는 것을 권장

도커 스웜 모드 클러스터 구축

  • $ docker swarm init --advertise-addr {매니저 노드의 IP 주소}
  • $ docker swarm join
    • 새로운 워커 노드를 스웜 클러스터에 추가할 때 사용
    • --token 옵션에 사용된 토큰 값은 새로운 노드를 클러스터에 추가하기 위한 비밀키
  • $ docker node ls
    • 도커 노드 리스트 확인
  • $ docker swarm leave
    • 추가된 워커 노드를 삭제하고 싶을 때 사용
    • 매니저 노드는 해당 워커 노드의 상태를 Down으로 인지하지만, 워커 노드를 자동으로 삭제하진 않음
    • 진짜 삭제를 하고 싶다면, $ docker node rm을 수행하면 됨
    • 매니저 노드는 --force 명령을 수행해야 가능함
    • 스웜 클러스터에 매니저 노드가 하나라면, 해당 매니저 삭제 시 스웜 클러스터 자체를 사용하지 못하게 됨
  • $ docker node promote {worker HOSTNAME}
    • 워커노드를 매니저 노드로 변경
  • $ docker node demote {worker HOSTNAME}

스웜 모드 서비스

  • 도커 명령어의 제어 단위는 컨테이너
  • 스웜 모드를 제어하는 단위는 컨테이너가 아닌 서비스
  • 서비스란?
    • 같은 이미지에서 생성된 컨테이너의 집합
    • 서비스 내에는 1개 이상의 컨테이너가 존재할 수 잇음
    • 컨테이너는 각 워커 노드와 매니저 노드에 할당됨
    • 이런 컨테이너를 Task라고 부름
  • 함께 생성된 컨테이너를 레플리카(replica)라고 하며, 서비스에 설정된 레플리카 수만큼 컨테이너가 스웜 클러스터 내에 존재해야 함
  • 한 노드에 여러 컨테이너가 존재할 수 있음

서비스 생성

  • 서비스를 제어하는 도커 명령어는 전부 매니저 노드에서만 사용할 수 있음
  • 서비스 생성
    docker service create \
    ubuntu:14.04 \
    /bin/sh -c "while true; do echo hello world; sleep 1; done"
  • $ docker service ls
    • 서비스 목록 확인
  • $ docker service ps {서비스 이름}
    • 서비스 내의 컨테이너의 목록, 상태, 컨테이너가 할당된 노드의 위치
    • --filter is-task=true
      • 스웜 모드의 서비스에서 생성된 컨테이너만 출력
  • $ docker service scale {서비스 이름}={스케일링 하고 싶은 개수}
  • 스웜 모드는 라운드 로빈 방싱그로 서비스 내에 접근할 컨테이너를 결정함

서비스 모드[복제모드와 글로벌 모드]

  • 복제 모드
    • 레플리카 셋의 수를 정의해 그만큼의 같은 컨테이너를 생성하는 모드
    • 실제 서비스를 제공하기 위해 일반적으로 쓰이는 모드
  • 글로벌 모드
    • 스웜 클러스터내에서 사용할 수 있는 모든 노드에 컨테이너를 반드시 하나씩 생성
    • 글로벌 모드로 생성한 서비스는 레플리카 셋의 수를 별도로 지정하지 않음
    • 모니터링하기 위한 에이전트 컨테이너를 생성할 때 유용하게 사용가능
    • $ docker service create --mode global

서비스 복구

  • 서비스 내의 특정 노드를 다운시켰을 때, 이를 복구하기 위해 매니저 노드에서 새로 컨테이너를 생성시킴
  • 다운되었던 노드를 다시 시작해도, 다른 노드에 생성된 컨테이너를 다시 할당시켜주진 않음
    • rebalance 작업이 일어나지 않음
    • scale 명령어를 통해 컨테이너 수를 줄이고 다시 늘려야 balancing이 적용됨

서비스 롤링 업데이트

# 서비스 생성 및 롤링업데이트 설정
docker service create \
--replicas 4 \
--name {서비스명} \
--update-delay 10s \ 10초 단위로 업데이트 진행
--update-parallelism 2 \ 2개씩 업데이트를 적용
nginx:1.10

# 업데이트 도중 오류 발생 시, 롤링업데이트가 중지되나 다음 옵션으로 계속 진행되도록 적용가능
--update-failure-action continue
  • $ docker service rollback {서비스명}

config, secret 설정

  • 환경변수 값을 -e 옵션을 통해 세팅하는 것은 보안적으로 문제가 있음
  • 설정 파일을 호스트마다 마련해두는 것 역시 비효율적인 일
  • secret
    • 비밀번호나 SSH 키, 인증서 키와 같이 민감 데이터 전송
    • 암호화된 상태로 매니저 노드에 저장(파일을 열어보면 rawdata로 보임)
    • 컨테이너에 배포된 뒤에도 파일 시스템이 아닌 메모리에 저장(휘발성)
    • /run/secrets/ 디렉터리에 마운트됨
  • config
    • nginx나 레지스트리 설정파일과 같이 암호화할 필요가 없는 값

도커 스웜 네트워크

  • 스웜 모드는 여러 개의 도커 엔진에 같은 컨테이너를 분산해서 할당
  • 도커 데몬의 네트워크가 하나로 묶인 네트워크 풀이 필요함
  • 서비스를 외부로 노출했을 때, 어느 노드로 접근하더라도 해당 서비스 컨테이너에 접근 가능하도록 라우팅 기능이 필요함
  • 스웜 클러스터에 등록된 노드라면 전부 ingress 네트워크가 생성됨
    • ingress network
    • 스웜 노드에 접근 시 서비스 내에 컨테이너에 접근할 수 있는 라우팅 메시 구성
    • 접근을 라운드 로빈 방식으로 분산하는 로드 밸런싱을 담당

서비스 디스커버리

  • 새로 생성된 컨테이너 생성의 발견 또는 없어진 컨테이너의 감지
  • 보통 주키퍼, etcd 등의 분산 코디네이터를 외부에 두고 사용해서 해결
  • 스웜 모드는 자제척으로 서비스 지원

스웜 모드 볼륨

# 해당 볼륨이 없을 시, 생성하여 붙임
docker service create --name ubuntu \
--mount type=volume,source=myvol,target=/root \
ubuntu:14.04 \
ping docker.com

# 이미 컨테이너 내부에 파일이 존재할 때, 이 파일을 볼륨에 복사하지 않음
--volume-nocopy 추가 시, 컨테이너의 파일들이 볼륨에 복사되지 않음

# 호스트와 디렉터리를 공유할 때 사용 (source 옵션을 반드시 명시해야 함)
--mount type=bind,source=/root/host,target=/root/container \
  • 서비스를 할당받는 모든 노드가 볼륨 데이터를 가지고 있어야 하기 대문에 매우 까다로움
  • 모든 노드에 같은 데이터 볼륨을 구성하는 방법은 그다지 추천되지 않음
  • Persistent Storage를 사용하면 호스트와 컨테이너와 별개로 외부에 존재하기 때문에 네트워크로 마운트 할 수 있음

노드 관리하기

  1. Active
    ```
    docker node update \

--availability active
{워커 명}


2. Drain
- 컨테이너를 해당 노드에 할당하지 않음
- 보통 매니저 노드에 설정하는 상태이나 노드에 문제가 생겨 일시적으로 사용하지 않을 시에도 사용
- 실행중이던 컨테이너는 전부 중지되고 Active 상태의 노드에 다시 할당됨
- 이후 밸런싱을 맞추고 싶을 때 scale명령어로 조정할 수 있음
- `$ --availability drain`

3. Pause
- 실행중이던 컨테이너가 중지되지 않음
- `$ --availability pause`

#### 노드 라벨 추가
- 노드에 라벨을 추가함으로써 볼륨 유무 체크, 네트워크나 지역 및 하드웨어, 운영체제 등을 구분지어 서비스를 적용할 수 있음

docker node update
--label-add storage=ssd
{워커 명}

아래와 같이 제약조건 붙이는 것이 가능

--constraint 'node.labels.storage == ssd'

728x90

'Infra > Docker' 카테고리의 다른 글

[etc] 혼란스러운 도커 입문자에게  (2) 2021.05.28
[8] Docker Compose  (0) 2021.05.28
[6] DockerDemon  (2) 2021.05.28
[5] Dockerfile  (0) 2021.05.28
[4] Docker 이미지  (0) 2021.04.26
Comments