Docker

도커 스웜 개념

25G 2023. 5. 31. 09:46

도커 스웜? 사용하는 이유

기본적으로 흔히 사용하는 도커는 대부분 하나의 호스트를 기준으로 합니다. docker ps 명령어는 하나의 도커 엔진에 존재하는 컨테이너의 목록을 출력하며 create, run 명령어 또한 하나의 도커엔진에 컨테이너를 생성합니다.
만약 하나의 호스트 머신에 도커엔진을 구동하다가 cpu나 메모리, 디스크 용량과 같은 자원이 부족하면 이를 어떻게 해결할까?
이럴때 해결책은 돈을 둘둘 바르면 해결됩니다. 하지만 대부분의 상황에 이와같은 해결책을 선택할 수 있는게 아닙니다. 그래서 현제 흔히 사용하는방법은 여러대의 그저 그런 적당한 사양의 서버를 클러스터로 만들어 자원을 병령로 확장하는 것입니다.
이때 서버를 클러스터링 하기 위해서는 많은 작업이 필요합니다. 서버끼리 커넥션문제 그리고 이에 따르는 자연스러운 스케줄러와 로드벨런싱 문제 등 많은 문제에 직면하게 됩니다. 이때 좀 더 편리하게 사용하는 오픈소스가 도커 스웜과 스웜모드입니다.

스웜클래식과 도커 스웜모드

스웜 클래식과 스웜 모드는 여러 대의 도커 서버를 하나의 클러스터로 만들어 컨테이너를 생성하는 여러 기능을 제공합니다.
사실 스웜을 실무에서 잘 사용하지 않는다고들 하지만 쿠버네티스를 공부하기전에 서버 클러스터에서 컨테이너 관리에 익숙해 지는연습으로 스웜 모드를 연습해보는것도 좋은방법입니다.

도커 스웜의 두가지 종류

  • 컨테이너로서의 스웜 클래식
    • 여러 서버를 단일 접근점 제공
    • 일반 도커 명령어 및 api로 서버제어
    • 분산 코디네이터/ 에이전트 별도 실행
  • 도커 버전 1.12 이후 부터사용할 수 있는 도커 스웜모드
    • 마이크로 서비스 아케택처의 컨테이너를 다루기 위한 클러스터링 기능
    • 유동적인 컨테이너 수 조절 가능
    • 컨테이너로의 연결 분산하는 로드벨런싱 지원
    • 확장성과 안정성이 스웜클래식보다 뛰어남
    • 분산 코디네이터/ 클러스터링을위한 모든 도구 내장
      위 둘의 차이는 목적에 있습니다. 스웜클래식은 여러대의 도커 서버를 하나의 지점에서 사용하도록 단일 접근점을 제공한다면 스웜모드는 마이크로서비스 아키텍처의 컨테이너를 다루기 위한 클러스터링 기능에 초점을 맞추고 있다.
      결론 스웜 클래식은 공식문서에서도 레거시 취급
      도커 스웜모드 권장

스웜 모드

스웜모드는 도커 엔진 자체에 내장돼 있다.

# docker info  | grep Swarm 
Swarm:inactive

현제 비활성화 돼 있다.
서버 클러스터링을 할 때는 반드시 각 서버의 시각을 NTP 등의 툴을 이용해 동기화 해야 합니다. 서버 간에 설정된 시각이 다를 경우 예상치 못한 오류가 발생할 수 있기 때문입니다.

도커 스웜 모드 구조

매니저 노드, 워커

워커 : 실제로 컨테이너가 생성되고 관리되는 도커 서버,
매니저 노드 : 워커 노드를 관리하기 위한 도커 서버

이러한 메커니즘으로 매니저노드는 기본적으로 워커 노드의 역할을 포함 할 수 밖에 없다.
매니저 노드는 1개 이상이 있어야 하지만 워커 노드는 없을 수도 있습니다.
매니저 부하를 분산하고 특정 매니저 노드가 다운 됐을 때 정상적으로 스웜 클러스터를 유지할 수 있기 때문입니다. 매니저수를 늘린다고 스웜클러스터의 성능이 좋아지는 것은 아닙니다.

구축 예시

먼저 docker swarm init 명령어를 입력해 매니저 역할을 할 서버에서 스월 클러스터를 시작합니 다. 一 advertise-addr에는 다른 도커 서버가 매니저 노드에 접근하기 위한 IP 주소를 입력합니다. 즉,매니저 노드의 IP 주소를 입력합니다.

docker swarm init --advertise-addr 192.168.0.100

docker swarm join \
~token SWMTKN-1-4rcs7fnogy1113i2g9yr13vtiii4gg6x6ffkl3zg29gulcpwxs-aqxcygo7upy68tati8dfyxgtu \ 
192.168.0.100:2377

매니저 노드에 2개 이상의 네트워크 인터페이스 카드가 있을 경우 어느 ip 주소로 매니저에 접근해야 할지 다른 노드에 알려줄 필요가 있습니다.

docker swarm join 명령어는 새로운 워커 노드를 스웜 클러스터에 추가할 때 사용됩니다.
그리고 운영환경에서 토큰의 노출에 보안을 신경써야하고 주기적으로 바꿔주는것이 좋습니다.

토큰 갱신

swarm join --rotate {변경할 토큰 대상}

주의사항

  • 스웜 매니저는 기본적으로 2377번 포트를 사용하며, 노드 사이의 통신에 7946/tcp, 7946/udp 포트를 스웜이 시용하는 네트워크인 ingress 오버레이 네트워크에 4789/tcp. 4789/udp 포트를 사용합니다. 스웜 클 러스터를 구성하기 전에 이러한 포트를 각 호스트 머신에서 열어둬야 합니다.

  • docker node ls 로 node 리스트 확인 가능

매니저 노드

매니저 노드는 일반적인 매니저 역할을 하는 노드와 리더 역할을 하는 노드로 나뉩니다. 리더 매니저는 모든 매니저 노드에 대한 데이터 동기화와 관리를 담당하므로 항상 작동할 수 있는 상태여야 합니다. 리더 메니저에 서버가 다운되거나 하는 장애가 생기면 매니저는 새로운 리더를 선출합니다.

워커노드 삭제

docker swarm leave

위 명령어로 스웜모드를 해제하면 노드는 워커를 down 시키는것이지 삭제하지않습니다. 따라서 docker node rm {호스트이름} 명령어로 워커를삭제해야 워커를 완벽히 삭제한 것입니다.

메니저 노드 삭제

메니저 노드 삭제는 docker swarm leave --forece 옵션 추가
메니저 노드 삭제시 클러스터 정보도 다 삭제됩니다.
스웜 클러스터에 만약 메니저 노드가 하나 있는데 이를 삭제하면 클러스터 정보가 모두 날라가니 주의 해야합니다.

워커 노드를 매니저 노드로 변경

docker node promote

매니저 노드를 워커 노드로 변경

docker node demote
demote 명령어는 매니저 노드가 한개보다 많을때 사용가능

스웜모드 서비스

서비스?

docker run, rm 과 같은 명령어는 컨테이너를 재어하는 명령어 입니다. 하지만 스웜 모드에서 제어하는 단위는 컨테이너가 아닌 서비스 입니다.

서비스는 같은 이미지에서 생성된 컨테이너의 집합, 서비스를 제어하면 서비스 내의 컨테이너에 같은 명령이 수행됩니다. 서비스 내에 컨테이너는 1개 이상 존재할 수 있고 각 컨테이너들은 각 워커 노드와 매니저 노드에 할당됩니다. 이러한 컨테이너를 Task 라고 합니다.
스웜 스케줄러는 서비스의 정의에 따라 컨테이너를 할당할 적합한 노드를선정하고, 해당 노드에 컨테이너를 분산해서 할당합니다. 함께 생성된 컨테이너를 레플리카라고 하며 서비스에 정의된 레플리카의 수만큼 컨테이너가 스웜 클러스터 내에 존재해야합니다. 스웜은 상태를 스케줄링하다가 레플리카의 수만큼 컨테이너가 없으면 새로운 컨테이너 레플리카를 생성합니다. 정지또한 레플리카를 채우지 못했으므로 스케줄러가 컨테이너를 레플리카 수만큼 생성해 줍니다.

서비스 생성

docker service로 서비스를 사용할 수 있고
서비스를 생성하려면 docker service crete 명령어를 사용,

이때 서비스 내의 컨테이너는 detached 모드로 docker run -d 옵션이 사용가능한 이미지를 사용해야합니다.

서비스 정보 확인

docker service ps {서비스이름}

서비스 정보 삭제

docker service rm {서비스 이름}

연습

docker service create --name myweb --replicas 2 -p 80:80 nginx

위 명령어로 서비스를 만들고 레플리카를 2 개로 설정후 nginx 서버를 띄웠을때 레플리카를 늘리고 싶다면
docker service scale 명령어를 사용할 수 있다.

docker service scale myweb=4

global 서비스 생성

서비스 모드는 두가지가 있습니다.

  • 위 연습 예시처럼 레플리카 수만큼 컨테이너를 복제하는 복제모드

  • galobal 모드

    • 글로벌 서비스는 스웜 클러스터 내에서 사용할 수 있는 모든 노드에 컨테이너를 반드시 하나씩 생성합니다. 따라서 글로벌 서비스는 스웜 클러스터 내에서 사용할 수 있는 모든 노드에 컨테이너를 반드시 하나씩 생성합니다. 글로벌 서비스는 스웜 클러스터를 모니터링 하기 위한 에이전트 컨테이너 등을 생성해야할때 유용합니다.

docker service create --mode global
위 명령어로 글로벌 모드를 생성할 수 있고 --mode 옵션의 값을 별도로 설정하지 않으면 기본적으로 복제모드 사용

스웜모드의 서비스 장애 복구

docker ps 같은 도커 클라이언트 명령어로도 스웜의 서비스로 생성된 컨테이너를 확인할 수 있다.

docker ps --filter is-task=true --format {{.Name}}

도커 스웜은 다운됐던 노드를 다시 시작해 정상적인 상태를 회복해도 장애를 복구하기 위해 다른 노드로 옮겨진 컨테이너가 해당 노드에 자도으로 할당되지는 않습니다. 즉 재균형 작업이 일어나지는 않아서 새로운 노드를 추가하거나 다운됐던 노드를 복구했을땐 scale 명령어를 이용해 컨테이너 수를 줄이고 다시 늘려야 합니다.

서비스 롤링 업데이트

스웜 모드는 롤링 업데이터를 자체적으로 지원합니다,

docker service update --image {변경하는 이미지:태그} {서비스명}

태그를 보고 서비스레이어에 업데이트 여부를 보거나 컨테이너 버전을 관리할 수 있다.

-- update-failure-action 옵션에 continue 인자를 주면 업데이트 도중 오류가 생기더라도 계속 롤링 업데이트를 진행하게 할 수 있다.
롤백하고 싶다면
docker service rollback {서비스이름}

서비스 컨테이너에 설정 정보 전달

기본적으로 설정파일들은 -v 옵션을 활용해서 호스트에 위치한 설정 파일이나 값을 볼륨으로써 컨테이너에 공유하여 사용했습니다.
그러나 스웜 모드와 같은 서버 클러스터에서 파일 공유를 위해 설정 파일을 호스트마다 마련해두는 것은 매우 비효율적인 일입니다.
이를 위해 스웜모드는 secret 과 config 라는 기능을 제공합니다.
secret은 비밀번호나 ssh 키, 인증서 키와 같이 보안에 민감한 데이터를 전송하기 위해서 config는 nginx나 레지스트리 설정파일과 같이 암호화할 필요가 없는 설정값들에 대해 쓰일 수 있습니다.
secret과 config는 스웜 모드에서만 사용될 수 있는 기능입니다. MySQL과 같은 일반적으로 사용하는 컨테이너들은 스웜 모드에서도 동일하게 사용할 수 있기대문에 secret, config 기능을 활용하고 싶다면 스웜모드를 사용하는것이 좋습니다.

secret

secret을 생성하려면 아래와 같이 docker secret create 명령어를 입력합니다.

docker secret create my_mysql_password -


docker secret inspect my_mysql_password

위에서 만든 my_mysql_password 를 inspect 명령어로 확인을 해 보려해도 실제 secret값은 매니저 노드간에 암호화된 상태로 저장됩니다. 이러한 secret 파일은 컨테이너에 배포된 뒤에서 파일시스템이 아닌 메모리에 저장되기 때문에 서비스컨테이너가 삭제될 경우 secret도 함께 삭제되는 휘발성을 띠게 됩니다.

  • secret을 활용한 mysql 컨테이너 생성
    ```
    root@swarm-manager:~# docker service create
    —name mysql \
  • -replicas 1
    —secret source=my_mysql_password,target=mysql_root_password \
    —secret source=my_mysql_password,target=mysql_password \
  • e MYSQL_R00T_PASSW0RD_FILE="run/secrets/mysql_root_password" \
  • e MYSQL_PASSW0RD_FILE="run/secrets/mysql_password" \
  • e MYSQL_DATABASE="wordpress"
    mysql:5.7

—secret source=my_mysql_password,target=mysql_root_password \
—secret source=my_mysql_password,target=mysql_password \

--secret옵션을 통해 컨테이너로 공유된 값은 기본적으로 컨태이너 내부의 /run/secrets/디렉터리에 마운트 됩니다. 위 예시에서는 target의 값이 각각 mysql_root_password, mysql_password로 설정됐기 때문에 /run/secrets 디렉터리에 해당 이름의 파일이 각각 존재할 것입니다.

target의 값에 절대 경로를 입력해 /run/secrets가 아닌 다른 경로에 secret 파일을 공유할 수도 있습니다.

--secret source=my_mysql_password/target=/home/mysql_root_password

이 값 전달 방식에 교려할 점은 바로 컨테이너 내부의 애플리케이션이 특정 경로의 파일값을 참조할 수 있도록 설계해야 한다는 것입니다. 위 예시에서 -e MYSQL_PASSW0RD_FILE="run/secrets/mysql_password" 를 보면 해당 옵션을 통해서 특정 경로의 파일로부터 비밀번호를 로드할 수 있게 되어 있습니다. 이처럼 애플리케이션을 개발할 때 각종 설정 변수를 파일로부터 동적으로 읽어올 수 있도록 설계해야합니다.

도커 스웜 네트워크

도커 스웜은 일반적인 도커의 네트워크 구조와 조금 다른 방법을 사용합니다. 스웜 모드는 여러개의 도커 엔진에 같은 컨테이너를 분산해서 할당하기 때문에 각 도커 데몬의 네트워크가 하나로 묶인 네트워크 풀이 필요합니다. 또한 외부로 노출시 내부적으로 컨테이너끼리 라우팅 기능도 있어야 합니다.
스웜모드가 자체적으로 사용하는 네트워크 드라이버를 사용하면 된다.

ingress 네트워크

ingress 네트워크는 스웜 클러스터를 생성하면 자동 등록되는 네트워크, 스웜모드에서만 유효,
매니저노드가 아니더라도 스웜클러스터에 등록된 노드면 전부 ingress 네트워크 생성

ingress 네트워크는 어떤 스웜 노드에 접근하더라도 서비스 내의 컨테이너에 접근할 수 있게 설정하는 라우팅 메시를 구성하고 서비스 내의 컨테이너 접근을 분산하는 로드 벨런싱을 담당합니다.
ingress 네트워크를 사용하지 않고 외부로 서비스 노출을 할 수도 있습니다.

--publish mode=host,target=80,published=8080,protocol=tcp

그러나 ingress 네트워크를 사용하지 않고 위와같이 서비스를 외부로 노출할 경우 어느 호스트에서 컨테이너가 생성될지 알 수 없어 포트 및 서비스 관리가 어렵다는 단점이 있습니다. 따라서 가급적이면 ingress 네트워크를 사용해 외부로 서비스를 노출하는 것이 좋습니다.

오버레이 네트워크

ip할당을 순차적으로 해준다.
ingress 네트워크는 오버레이 네트워크 드라이버를 사용합니다. 오버레이 네트워크는 여러개의 도커 데몬을 하나의 네트워크 풀로 만드는 네트워크 가상화 기술
도커에 오버레이 네트워크를 적용하면 여러 도커 데몬에 존재하는 컨테이너가 서로 통신할 수 있습니다.
여러개의 스웜 노드에 할당된 컨테이너는 오버레이 네트워크의 서브넷에 해당하는 ip 대역을 할당받고 이 ip를 통해 서로 통신할 수 있는 것입니다.

docker_gwbridge 네트워크

docker_gwbridge 네트워크는 외부로 나가는 통신 및 오버레이 네트워크의 트래픽 종단점 역할을 담당합니다.
docker_gwbridge 네트워크는 컨테이너 내부의 네트워크 인터페이스 카드중 eth1과 연결됩니다.

사용자 정의 오버레이 네트워크

스웜모드는 자체 키-값 저장소르르 갖고 있으므로 별도의 구성 없이 사용자 정의 오버레이 네트워크를 생성하고 사용할 수 있습니다.

  • 오버레이 생성 명령어 예시
    ```
    docker network create \
  • -subnet 10.0.9.0/24 \
  • d overlay
    myoverlay
-d : 네트워크 드라이버 설정
--subnet: 서브넷 설정

이렇게 생성된 오버레이 네트워크의 스코프가 swarm으로 설정돼 있기때문에 일반적인 docker run 명령어로는 swarm의 스코프를 갖는 네트워크를 사용할 수 없습니다.
docker run --net 명령어로 스웜 모드의 오버레이 네트워크를 사용하려면 네트워크 생성시에 --attachable 옵션을 추가해야합니다..

### 서비스 디스 커버리
같은 컨테이너를 여러개 만들어 사용할 때 쟁점이 되는 부분중 하나는 새로 생성된 컨테이생성의 발결 혹은 없어진 컨테이너의 감지입니다. 일반적으로 이 동작은 주키퍼등의 분산 코디네이터를 외부에 두고 사용해서 해결하지만 스웜 모드는 서비스 발경 기능을 자체적으로 지원합니다.
예를 들어 2개의 컨테이너 레플리카를 갖는 B 서비스가 있고, A 서비스는 이 B 서비스의 컨테이너를 사용한다고 가정하고
docker service scale 명령어로 서비스 B의 컨테이너를 3개로 늘렷습니다. 이때 서비스 A 의 컨테이너가 B의 새로운 컨테이너에 접근할 수 있을까?

![](https://velog.velcdn.com/images/fj2008/post/21c057ef-4758-401a-b296-67f546ea464d/image.png)

스웜 모드에서 B라는 이름으로 서비스 B의 컨테이너에 모두 접근할 수 있습니다. 즉, 서비스 A의 컨테이너 입장에서는 새롭게 생성된 서비스 B의 컨테이너 ip 주소를 알 필요도 없고 새롭게 생성된 사실도 알 필요가 없으며 B라는 서비스의 이름만 알면 됩니다.
스웜모드의 서비스 발견은 오버레이 네트워크를 사용하는 서비스에 대해 작동합니다.
어떻게 이런것이 가능하냐면 서비스의 호스트이름이 3개의 ip 를 가지는 것이 아니라 서비스의 VIP를 가지는 것입니다. B 서비스의 VIP는 다음 명령어로 확인할 수 있습니다. docker ps 에서 사용했던것과 유사하게 --format 의 Go 탬플릿을 사용하면 docker service inspect 의 결과중 VirtualIps 항목만 출력하도록 포맷을 지정할 수 있습니다.

docker service inspect --format {{.Endpoint.VirtuallPs}} B
[|74mgwebvciysddx3rns0pam9a 10.0.1.2 /2 4 }]

B 서비스의 VIP는 10.0.1.2 입니다. 스웜 모드가 활성화된 도커 엔진의 내장 DNS 서버는 server라는 호스트 이름을 10.0.1.2라는 IP로 변환합니다. client 서비스의 컨테이너가 B 라는 호스트 이름으로 접근하면 실제로는 10.0.1.2로 요청을 전송하게 됩니다.

### 스웜 모드 볼륨

도커 데몬 명령어 중 run 명령어에서 -v 옵션을 사용할 때 호스트와 디렉터리를 공유하는 경우와 볼륨을 사용하는 경우에 대한 구분은 딱히 없었습니다.

호스트와 디렉터리를 공유하는 경우

docker run -i -t -- name host_dir_case -v /root:/root ubuntu:14.04

도커 볼륨을 사용하는 경우

docker run -i -t -- name volume_case -v myvolume:/root ubuntu:14.04

이러한 -v 옵션과 같은 기능을 스웜모드에서도 사용할 수 있습니다. 
그러나 스웜모드의 볼륨을 사용할땐 도커 볼륨을 사용할지, 호스트 외 디렉터리를 공유할지를 좀 더 명확히 해 볼륨을 사용합니다. 서비스를 생성할 때 도커 볼륨을 사용할지 호스트와 디렉터릴를 공유할지 명시해야합니다.

#### volume 타입의 볼륨 생성
스웜 모드에서 도커 볼륨을 사용하는 서비스를 생성하려면 서비스를 생성할 때 --mount 옵션의 type 값에 volume을 지정합니다.

docker service create --name ubuntu
--mount type=volume,source=myvol,target=/root
ubuntu:14.04
ping docker.com

type=volume 으로 이를 명시하고, source는 사용할 볼륨 target은 컨테이너 내부에 마운트 될 디렉터리의 위치입니다. 이때 도커 데몬에 이미 sorece에 해당하는 이름의 볼륨이 있으면 해당 볼륨을 사용하고 없으면 새로 생성합니다.
서비스의 컨테이너에서 볼륨에 공유할 컨테이너의 디렉터리 파일이 이미 존재하면 이 파일들은 볼륨에 복사되고, 호스트에서 별도의 공간을 차지하게 됩니다. 그러나 서비스를 생성할 때 볼륨 옵션에 volume-nocopy를 추가하면 컨테이너의 파일들이 볼륨에 복사되지 않도록 설정할 수 있습니다.
#### bind 타입의 볼륨생성
바인드 타입은 호스트와 디렉터리를 공유할 때 사용됩니다. 볼륨 타입과는 달리 공유될 호스트의 디렉터리를 설정해야 하므로 source 옵션을 반드시 명시해야 합니다. 바인드 타입은 type 옵션의 값을 bind로 설정해서 사용할 수 있습니다. 다음 명령은 호스트의 /root/host 디렉터리를 서비스 컨테이너의 /root/contatiner 디렉터리에 마운트 합니다.

--mount type=bind,source=root/host,target=root/container

#### 스웜 모드에서 볼륨의 한계점
스웜 클러스터에서 볼륨을 사용하기란 상당히 까다롭다. 서비스를 할당받을 수 있는 모든 노드가 볼륨데이터를 가지고 있어야 하기때문입니다. 스웜 매니저에 내장된 스케줄러가 컨테이너를 할당할 때 어느 노드에 할당해도 서비스에 정의된 볼륨을 사용할 수 있어야 하기때문입니다.
그래서 여러 개의 도커 데몬을 관리해야 하는 스웜 모드에서는 도커 볼륨, 또는 호스트와의 볼륨 사용이 적합하지 않은 기능 일 수 있습니다.
![](https://velog.velcdn.com/images/fj2008/post/be43b6c8-be27-4361-aa39-d86d17c51894/image.png)

이를 해결하기 위한 일반적인 방법은 어느 노드에서도 접근 가능한 퍼시스턴트 스토리지를 사용하는 것입니다. 퍼시스턴트 스토리지는 호스트와 컨테이너와 별개로 외부에 존재해 네트워크로 마운트 할 수 있는 스토리지 입니다.

![](https://velog.velcdn.com/images/fj2008/post/a7d281a8-9ab5-4bbd-a972-d2ee55cbad28/image.png)

서비스 컨테이너가 각 노드에 할당될 때 퍼시스턴트 스토리지를 마운트해 사용하면 노드에 볼륨을 생성하지 않아도 되고 컨테이너가 어느 노드에 할당되든 컨테이너에 필요한 파일을 읽고 쓸 수 있습니다.
이를 구성하기 위해선 서드파티 플러그인을 사용하거나 nfs, dfs 등을 별도로 구성해야 합니다. 

### 도커 스웜 모드 노드 다루기
현재는 스웜 모드의 스케줄러를 사용자가 수정할 수 있게 자체적으로 제공하지 않기때문에 스케줄링 전략을 세우는 것은 불가능 합니다. 스웜모드가 제공하는 기본 기능만으로도 어느 정도 목적에 부합한 전략을 세울 수 있습니다.

#### 노드 AVAILABILITY 변경하기
docker node ls 명령어를 처서 결과를 보면 AVAILABILITY 항목이 Active인 경우가 있는데 일밙거으로 매니저와 같은 마스터 노드는 최대한 부하를 받지 않도록 서비스를 할당받지 않게 하는 것이 좋습니다. 또는 특정 노드에 문제가 발생해 유지보수 작업을 수행할 때 해당 노드에 컨테이너를 할당하지 않게 하고 싶을 수 도 있습니다. 이를 위해 특정 노드의 AVAILABILITY를 설정해서 컨테이너의 할당 가능 여부를 변경할 수 있습니다.
#### Active
Active 상태는 새로운 노드가 스웜 클러스터에 추가되면 기본적으로 설정되는 상태로서, 노드가 서비스의 컨테이너를 할당받을 수 있음을 의미합니다. Active 상태가 아닌 노드를 Active 상태로 변경하려면 docker node update 명령어를 사용합니다.

docker node update \
—availability active
노드이름

#### Drain
노드를 Drain 상태로 설정하면 스웜 매니저의 스케줄러는 컨테이너를 해당 노드에 할당하지 않습니다. Drain 상태는 일반적으로 매니저 노드에 설정하는 상태지만 노드에 문제가 생겨 일시적으로 사용하지 않는 상태로 설정해야 할 때도 자주 사용됩니다.

docker node update \
—availability drain
노드이름

노드를 Drain 상태로 변경하면 해당 노드에서 실행 중이던 서비스의 컨테이너는 전부 중지 되고 Active 상태의 노드로 다시 할당됩니다. 그러나 이전에 언급한 것 처럼 Drain 상태의 노드를 Active상태로 다시 변경한다고 해서 서비스의 컨테이너가 다시 분산되어 할당되지는 않으므로 docker service scale 명령어를 사용해 컨테이너의 균형을 재조정해야합니다.

#### Pause

Pause 상태는 서비스의 컨테이너를 더는 할당받지 않는다는 점에서 Drain 과 같지만 실행중인 컨테이너가 중지되지 않는 점이 다릅니다.

docker node update \
—availability pause
노드이름


### 노드 라벨 추가
노드에 라벨을 추가하는 것은 노드를 분류하는것과 비슷합니다. 라벨은 키 벨류 형태를 가지고 있고 키값으로 노드를 구별할 수 있게 됩니다. 예를들어 하드웨어에 종속적인 그룹을 분류한다고 할때 ssd그룹 hdd 그룹으로 라벨링을 해서  해당 라벨에 따라서 그룹화해서 컨테이너를 할당할 수 있습니다. 이 외에도 볼륨 유무, 네트워크나 지역 및 하드웨어, 운영체제 등 여러 환경에 응용할 수 있습니다.

#### 노드 라벨 추가하기

docker node update \
--label-add storage=ssd
노드이름

설정된 라벨은 docker node inspect 명령으로 확인할 수 있습니다.

### 서비스 제약 설정
docker service create 명령어에 --constraint 옵션을 추가해 서비스의 컨테이너가 할당될 노드의 종류를 선택할 수 있습니다.

#### node.labels 제약조건
위 추가한 라벨을 예로 들자면 ssd라는 벨류를 가진 라벨의 노드만 서비스의 컨테이너를 할당합니다.

docker service create --name label_test \
--constraint 'node.labels.storage == ssd'
-- replicas=5
ubuntu:14.04
ping docker.com

이렇게하면 ssd의 벨류값을 가진 라벨을 가진 노드만 서비스 컨테이너를 할당받는것입니다.
이때 비교연산을위해 == 나 != 를 사용할 수도 있습니다.

#### node.id 제약조건
노드의 id를 명시해 서비스의 컨테이너를 할당할 노드를 선택합니다.

'Docker' 카테고리의 다른 글

도커 이미지 기본개념  (0) 2023.08.07
Dockerfile 기본개념  (0) 2023.08.07
도커 데몬  (0) 2023.05.31
docker/ expose 와 port 의 차이점  (0) 2023.05.31
도커와 컨테이너 생태계  (0) 2023.05.31