스웜 모드 서비스

mohadang·2022년 6월 16일
0

도커

목록 보기
25/26
post-thumbnail

스웜 모드 서비스 개념

  • 도커 클라이언트에서 사용하는 명령어가 제어하는 것은 컨테이너이다. 그러나 스웜 모드에서 제어하는 단위는 컨테이너가 아닌 서비스이다.
  • 서비스는 같은 이미지에서 생성된 컨테이너의 집합이며, 서비스를 제어하면 해당 서비스 내의 컨테이너에 같은 명령이 수행된다.
  • 서비스 내에 컨테이너는 1개 이상 존재할 수 있으며, 컨테이너들은 각 워커 노드와 매니저 노드에 할당된다. 이러한 컨테이너들을 태스크라고 한다.
    • 공식적으로는 서비스 내의 컨테이너를 태스크라고 부른다.
  • 스웜 스케줄러는 서비스의 정의에 따라 컨테이너를 할당항 적합한 노드를 선정하고 ,해당 노드에 컨테이너를 분산해서 할당한다.
  • 각 노드에 컨테이너가 하나씩 할당될 수 도 있으며 하나씩 할당되지 않고 복수개 할당될 수 도 있다.
  • 함께 생성된 컨테이너를 레플리카(replica)라고 하며, 서비스에 설정된 레플리카의 수만큼의 컨테이너가 스웜 클러스터 내에 존재해야 한다.
  • 스웜은 서비스의 컨테이너들에 대한 상태를 계속 확인하고 있다가 서비스 내에 정의된 레플리카의 수만큼 컨테이너가 스웜 클러스터에 존재하지 않으면 새로운 컨테이너 레플리카를 생성한다.
  • 컨테이너가 할당된 노드가 다운되면 매니저는 사용 가능한 다른 노드에 같은 컨테이너를 생성, 서버가 다운되지 않더라도 서비스 내의 컨테이너 중 일부가 작동을 멈춰 정지한 상태로 있다면 이 또한 레플리카의 수를 충족하지 못하는 것으로 판단해 스웜 매니저는 새로운 컨테이너를 클러스터에 새롭게 생성한다.
  • 서비스는 롤링 업데이트(Rolling Update) 기능도 제공한다. 서비스 내 컨테이너들의 이미지를 일괄적으로 업데이트해야 할 때 컨테이너들의 이미지를 순서대로 변경해 서비스 자체가 다운되는 시간 없이 컨테이너의 업데이트를 진행할 수 있다.
    • 롱링 업데이트를 사용하지 않고 모든 서버나 컨테이너를 한 번에 재시작하면 제공하는 서비스에 다운 시간이 생김
    • 롱링 업데이트를 하면 지속적인 서비스가 가능

서비스 생성, 확인, 삭제

  • 서비스를 제어하는 도커 명령어는 전부 매니저 노드에서만 사용할 수 있다.

EX) docker service create

$ docker service create ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep1; done"
도커 서비스 생성
서비스의 레플리카 셋을 정의하지 않았으므로 1개의 컨테이너만 생성

$ docker service create ubuntu:14.04
서비스 내의 컨테이너는 detached 모드로, 즉 docker run 명령어의 -d 옵션을 사용해 동작할 수 있는 이미지를 사용해야 한다. 
다음과 같이 서비스를 생성하면 컨테이너 내부를 차지하고 있는 프로세스가 없어 컨테이너가 정지될 것이고, 
스웜 매니저는 서비스의 컨테이너에 장애가 생긴 것으로 판단해 컨테이너를 계속 반복해서 생성할 것이다

EX) docker service ls

$ docker service ls
ID             NAME            MODE         REPLICAS   IMAGE          PORTS
om1wnphdvtt4   jovial_merkle   replicated   1/1        ubuntu:14.04

스웜 클러스터 내의 서비스 목록 확인

EX) docker service ps

$ docker service ps jovial_merkle
ID             NAME                  IMAGE          NODE                  DESIRED STATE   CURRENT STATE            ERROR     PORTS
bp40g9k8w965   jovial_merkle.1       ubuntu:14.04   red-virtual-machine   Running         Running 2 minutes ago
g32rmfpitou4    \_ jovial_merkle.1   ubuntu:14.04   red-virtual-machine   Shutdown        Complete 2 minutes ago

서비스의 자세한 정보를 확인

EX) docker service rm

$ docker service rm jovial_merkle
jovial_merkle

서비스 생성을 위해 Private 저장소 또는 레지스트리에서 이미지를 받아올 경우, 
매니저 노드에서 로그인 한 뒤 docker service create 명령어에 --with-registry-auth을 
추가해 사용하면 워커 노드에서 별도로 로그인을 하지 않아도 이미지를 받아올 수 있다.

nginx 웹 서버 서비스 생성하기

EX) nginx 웹 서버 서비스 생성

$ docker service create --name myweb --replicas 2 -p 80:80 nginx
r3e9ujc8s1zmujxwf55h3id0p
overall progress: 2 out of 2 tasks
1/2: running
2/2: running
verify: Service converged

--name myweb : 서비스 이름 myweb 지정
--replicas 2 : 생성할 도커 갯수 2
-p 80:80 : 컨테이너의 80번 포트를 각 노드의 80번 포트로 연결


$ docker service ps myweb
ID             NAME      IMAGE          NODE                  DESIRED STATE   CURRENT STATE            ERROR     PORTS
tlve68yzxnd3   myweb.1   nginx:latest   red-virtual-machine   Running         Running 11 seconds ago

31gc0ijtqur5   myweb.2   nginx:latest   red-virtual-machine   Running         Running 11 seconds ago
  • host의 80번 포트로 접근하면 Nginx 웹 서버가 구동되고 있는 것을 확인할 수 있다.

Nginx 웹서버에 접근하면 어떤 노드에 접근하는 것일까?

  • swarm-manager와 swarm-worker1 노트에 생성됐다.
  • 그렇다고 해서 꼭 두 노드의 IP 주소로 접근해야만 Nginx 웹 서버에 접근할 수 있는 것은 아니다.
  • docker service create 명령어에서 -p 옵션에 80:80을 입력함으로써 스웜 클러스터 자체에 포트를 개방했다고 생각하면 쉽게 이해할 수 있다.
  • 스웜 클러스터 내의 어떠한 노드로 접근해도 위 서비스의 웹 서버에 접근할 수 있다.
  • Nginx 컨테이너가 없는 swarm-worker2 노드로 접근해도 서비스에 접근할 수 있다.
  • 같은 노드게 2개의 컨테이너가 할당될 수도 있으며 이는 전혀 문제가 안 된다. 컨테이너가 각 컨테이너들이 호스트의 80번 포트에 연결된 것이 아니며 실제로는 각 노드의 80번 포트로 들어온 요청을 위 4개의 컨테이너 중 1개로 리다이렉트(redirect)하기 때문이다. 따라서 각 호스트의 어느 노드로 접근하든 4개의 컨테이너 중 1개에 접근하게 된다.

EX) docker service scale

$ docker service scale myweb=4
myweb scaled to 4
overall progress: 4 out of 4 tasks
1/4: running
2/4: running
3/4: running
4/4: running
verify: Service converged

레플리카 셋의 수를 4개로 늘렸다.

$ docker service ps myweb
ID             NAME      IMAGE          NODE                  DESIRED STATE   CURRENT STATE            ERROR     PORTS
tlve68yzxnd3   myweb.1   nginx:latest   red-virtual-machine   Running         Running 12 minutes ago

31gc0ijtqur5   myweb.2   nginx:latest   red-virtual-machine   Running         Running 12 minutes ago

k0g77qibntum   myweb.3   nginx:latest   red-virtual-machine   Running         Running 13 seconds ago

8p2u2nkc121j   myweb.4   nginx:latest   red-virtual-machine   Running         Running 13 seconds ago

global 서비스 생성

  • 일반 모드 서비스
    • Nginx 웹 서버 서비스와 같이 레플리카 셋의 수를 정의해 그만큼의 같은 컨테이너를 생성하는 복제 모드(replicated)로서 실제 서비스를 제공하기 위해 일반적으로 쓰이는 모드
  • global 모드 서비스
    • 스웜 클러스터 내에서 사용할 수 있는 모든 노드에 컨테이너를 반드시 하나씩 생성
    • 글로벌 모드로 생성한 서비스는 레플리카 셋의 수를 별도로 지정하지 않는다.
    • 글로벌 서비스는 스웜 클러스터를 모니터링하기 위한 에이전트 컨테이너 등을 생성해야 할 때 유용

EX) --mode global

$ docker service create --name global_web --mode global nginx
puhmwv08f95n56c99f66192es
overall progress: 1 out of 1 tasks
s9ywh74vze0t: running
verify: Service converged

$ docker service ls
ID             NAME         MODE      REPLICAS   IMAGE          PORTS
puhmwv08f95n   global_web   global    1/1        nginx:latest

레플리카의 값이 global로 설정됨

$ docker service ps global_web
ID             NAME                                   IMAGE          NODE                  DESIRED STATE   CURRENT STATE            ERROR     PORTS
b6evk4mt10mt   global_web.s9yw

각 노드에 컨테이너가 하나씩 생성

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

EX) 특정 컨테이너 장애

$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
1a3815bc0205   nginx:latest   "/docker-entrypoint.…"   10 seconds ago   Up 9 seconds    80/tcp    myweb.4.y3p8m6j63izo922u0d8d50ryh
18ae8bbe28e3   nginx:latest   "/docker-entrypoint.…"   10 seconds ago   Up 9 seconds    80/tcp    myweb.3.f8mjncmjuis5wpcvlrvpn1w4v
d5c1596243cb   nginx:latest   "/docker-entrypoint.…"   30 seconds ago   Up 29 seconds   80/tcp    myweb.2.kpd6031qjfqd2b190u08aqug0
63f1b3fd6f51   nginx:latest   "/docker-entrypoint.…"   30 seconds ago   Up 29 seconds   80/tcp    myweb.1.7sguc6ut8o6sz2vvu2u50hfhj
f3d16236b350   nginx:latest   "/docker-entrypoint.…"   5 minutes ago    Up 5 minutes    80/tcp    global_web.s9ywh74vze0tcbqm837e56esd.b6evk4mt10mtik3tw3dcyvwar

$ docker rm -f myweb.1.7sguc6ut8o6sz2vvu2u50hfhj
myweb.1.7sguc6ut8o6sz2vvu2u50hfhj

컨테이너 강제 종료


$ docker service ps myweb
ID             NAME          IMAGE          NODE                  DESIRED STATE   CURRENT STATE
       ERROR                         PORTS
6wz9esxaeq8q   myweb.1       nginx:latest   red-virtual-machine   Running         Running 4 seconds ago

7sguc6ut8o6s    \_ myweb.1   nginx:latest   red-virtual-machine   Shutdown        Failed 10 seconds ago        "task: non-zero exit (137)"
kpd6031qjfqd   myweb.2       nginx:latest   red-virtual-machine   Running         Running about a minute ago
f8mjncmjuis5   myweb.3       nginx:latest   red-virtual-machine   Running         Running 44 seconds ago

y3p8m6j63izo   myweb.4       nginx:latest   red-virtual-machine   Running         Running 44 seconds ago

myweb.1 을 보면 새로운 컨테이이너가 생성됐음을 확인 가능

docker service ps 명령어에서 NAME 항목에 _ 가 붙어있는 컨테이너는 어떠한 이유로든 동작을 멈춘 컨테이너로서, 서비스에서의 컨테이너 변경 기록을 나타낸다.

EX) 특정 노드 장애

swarm-worker1$ service docker stop
특정 노드 장애

$ docker node ls
특정 노드 STATUS가 Down 상태로 변경됨

다운 됐던 도느를 다시 시작해 정상적인 상태를 회복해도 장애를 복구하기 위해 다른 노드로 옮겨진 컨테이너가 해당 노드에 자동으로 할당되지는 않는다.(rebalance)

$ docker service scale myweeb=1
$ docker service scale myweeb=4
새로운 노드를 추가하거나 다운됐던 노드를 다시 복구했을 때 서비스의 컨테이너 할당의 
균형을 맞추기 위해서는 cale 명령어를 이용해 컨테이너의 수를 줄이고 다시 늘려야 한다.

docker ps --filter is-task=true
스웜의 서비스로 생성된 컨테이너만 확인

서비스 롤링 업데이트

EX) docker service update

$ docker service create --name myweb2 --replicas 3 nginx:1.10
$ docker service update --image nginx:1.11 myweb2

이미지를 업데이트하려면 --image 옵션 설정

$ docker service create --replicas 4 --name myweb3 --update-delay 10s --update-parallelism 2 nginx:1.10

--update-delay 10s : 컨테이너를 10초 단위로 업데이트
--update-parallelism 2 : 업데이트 작업을 한번에 2개의 컨테이너에 수행

EX) 롤링 업데이트 설정 확인

root@red-virtual-machine:~# docker service inspect --pretty myweb

ID:             uyodwj0vbp8ix44wedlixm12t
Name:           myweb
Service Mode:   Replicated
 Replicas:      4
Placement:
UpdateConfig:
 Parallelism:   1
 On failure:    pause
 Monitoring Period: 5s
 Max failure ratio: 0
 Update order:      stop-first
RollbackConfig:
 Parallelism:   1
 On failure:    pause          <-- 업데이트 도중 오류가 발생하면 롤링 업데이트 중지
 Monitoring Period: 5s
 Max failure ratio: 0
 Rollback order:    stop-first
ContainerSpec:
 Image:         nginx:latest@sha256:2bcabc23b45489fb0885d69a06ba1d648aeda973fae7bb981bafbb884165e514
 Init:          false
Resources:
Endpoint Mode:  vip
Ports:
 PublishedPort = 80
  Protocol = tcp
  TargetPort = 80
  PublishMode = ingress
  

--update-failure-action continue 지정으로 On failure 변경 가능

EX) docker service rollback myweb

$ docker service rollback myweb
서비스 롤링 업데이트 후, 서비스를 롤링 업데이트 전으로 되돌리는 롤백(rollback)
profile
mohadang

0개의 댓글