Swarm 모드에서 서비스가 동작하는 방식

Swarm 모드에서 서비스가 동작하는 방식

Docker Engine이 Swarm 모드로 동작할 때 애플리케이션 이미지를 배포하려면 서비스(service) 를 만들어야 합니다. 서비스는 보통 더 큰 애플리케이션 안에서 하나의 마이크로서비스를 담당하는 이미지라고 생각하면 쉬워요. 예를 들어 HTTP 서버, 데이터베이스, 또는 분산 환경에서 실행하고 싶은 어떤 실행 프로그램이든 서비스가 될 수 있습니다.

서비스를 만들 때는 어떤 컨테이너 이미지를 사용할지, 실행 중인 컨테이너 안에서 어떤 명령을 수행할지 지정합니다. 그리고 다음과 같은 서비스 옵션도 함께 정의할 수 있습니다:

  • Swarm 외부에서 서비스에 접근할 수 있게 해주는 포트
  • 서비스가 Swarm 안의 다른 서비스들과 연결되도록 하는 오버레이 네트워크
  • CPU 및 메모리 제한과 예약(reservation)
  • 롤링 업데이트 정책
  • Swarm에서 실행할 이미지의 복제본(replica) 수

출처: 공식문서

본문

서비스, 태스크, 컨테이너

서비스를 Swarm에 배포하면 Swarm 매니저가 여러분이 정의한 서비스 구성을 원하는 상태(desired state) 로 받아들입니다. 그런 다음 Swarm의 노드들에 서비스를 하나 이상의 복제 태스크(replica task) 로 스케줄링합니다. 이 태스크들은 Swarm 안의 각 노드에서 서로 독립적으로 실행됩니다.

예를 들어, HTTP 리스너 3개 인스턴스 사이에서 로드 밸런싱을 하고 싶다고 가정해 볼게요. 아래 다이어그램은 복제본 3개를 가진 HTTP 리스너 서비스를 보여줍니다. 리스너의 3개 인스턴스 각각은 Swarm 안에서 하나의 태스크입니다.

컨테이너는 격리된 프로세스입니다. Swarm 모드 모델에서 각 태스크는 정확히 하나의 컨테이너를 실행합니다. 태스크는 스케줄러가 컨테이너를 배치하는 "슬롯(slot)"과 비슷한 개념이에요. 컨테이너가 살아있는 상태가 되면, 스케줄러는 태스크가 실행 중(running) 상태임을 인식합니다. 만약 컨테이너가 헬스 체크에 실패하거나 종료되면, 태스크도 함께 종료됩니다.

태스크와 스케줄링

태스크는 Swarm 내에서 스케줄링의 원자 단위(atomic unit) 입니다. 서비스를 생성하거나 업데이트해서 원하는 서비스 상태를 선언하면, 오케스트레이터가 태스크를 스케줄링하여 그 원하는 상태를 실현합니다. 예를 들어, HTTP 리스너 3개 인스턴스를 항상 실행하라고 오케스트레이터에 지시하는 서비스를 정의했다고 해볼게요. 그러면 오케스트레이터는 태스크 3개를 생성하는 방식으로 응답합니다. 각 태스크는 스케줄러가 컨테이너를 생성해서 채우는 슬롯입니다. 컨테이너는 태스크의 구체적인 실체(instantiation)입니다. 이후 HTTP 리스너 태스크가 헬스 체크에 실패하거나 크래시되면, 오케스트레이터는 새 복제 태스크를 만들어 새 컨테이너를 실행합니다.

태스크는 단방향 메커니즘입니다. ASSIGNED, PREPARING, RUNNING 등의 상태를 단조롭게(monotonically) 진행합니다. 태스크가 실패하면 오케스트레이터는 해당 태스크와 컨테이너를 제거하고, 서비스가 지정한 원하는 상태에 따라 새 태스크를 생성해 교체합니다.

Docker Swarm 모드의 기본 로직은 범용 스케줄러이자 오케스트레이터입니다. 서비스와 태스크라는 추상화는 그들이 구현하는 컨테이너에 대해 알지 못합니다. 가상 머신 태스크나 컨테이너화되지 않은 프로세스 태스크 같은 다른 유형의 태스크도 구현할 수 있다고 가정해 볼 수 있어요. 스케줄러와 오케스트레이터는 태스크의 유형에 대해 중립적입니다. 다만 Docker는 컨테이너 태스크만 지원합니다.

아래 다이어그램은 Swarm 모드가 서비스 생성 요청을 받아들이고 워커 노드에 태스크를 스케줄링하는 과정을 보여줍니다.

대기 중(pending) 서비스

서비스가 현재 Swarm의 어떤 노드에서도 태스크를 실행할 수 없도록 구성될 수 있습니다. 이 경우 서비스는 pending 상태로 남아 있습니다. 서비스가 pending 상태로 남을 수 있는 몇 가지 예를 들어볼게요.

서비스가 배포되지 않도록 막는 것이 목적이라면, pending 상태로 만들려고 애쓰지 말고 서비스의 복제본 수를 0으로 스케일 다운하세요.

  • 모든 노드가 일시 중지(paused) 또는 드레인(drained) 상태일 때 서비스를 생성하면, 노드가 사용 가능해질 때까지 서비스는 pending 상태입니다. 실제로는 가장 먼저 사용 가능해진 노드가 모든 태스크를 받게 되므로, 프로덕션 환경에서는 이렇게 하는 것이 좋지 않습니다.
  • 서비스에 특정 메모리 양을 예약할 수 있습니다. Swarm의 어떤 노드도 필요한 메모리 양을 갖추지 못했다면, 태스크를 실행할 수 있는 노드가 나타날 때까지 서비스는 pending 상태로 남습니다. 예를 들어 500 GB처럼 아주 큰 값을 지정하면, 정말로 그 요구를 충족시킬 수 있는 노드가 없는 한 태스크는 영원히 pending 상태로 남게 됩니다.
  • 서비스에 배치 제약 조건(placement constraints)을 적용할 수 있는데, 특정 시점에 그 제약 조건을 충족하지 못할 수도 있습니다.

이런 동작은 태스크의 요구사항과 구성이 Swarm의 현재 상태와 반드시 밀접하게 연결되어 있지 않다는 점을 보여줍니다. Swarm 관리자로서 여러분은 Swarm의 원하는 상태를 선언하기만 하면, 매니저가 Swarm의 노드들과 협력하여 그 상태를 만들어 냅니다. Swarm 위의 태스크를 일일이 세세하게 관리할 필요가 없습니다.

복제 서비스와 글로벌 서비스

서비스 배포 방식에는 복제(replicated)글로벌(global) 두 가지 유형이 있습니다.

복제 서비스의 경우 실행하려는 동일한 태스크의 수를 지정합니다. 예를 들어, 동일한 콘텐츠를 제공하는 복제본 3개로 HTTP 서비스를 배포하기로 결정할 수 있습니다.

글로벌 서비스는 모든 노드에서 하나의 태스크를 실행하는 서비스입니다. 미리 지정된 태스크 수가 없습니다. Swarm에 노드를 추가할 때마다 오케스트레이터가 태스크를 생성하고 스케줄러가 그 태스크를 새 노드에 할당합니다. 글로벌 서비스로 적합한 예로는 모니터링 에이전트, 안티바이러스 스캐너, 또는 Swarm의 모든 노드에서 실행하려는 다른 유형의 컨테이너가 있습니다.

아래 다이어그램은 회색으로 표시된 3개 복제 서비스와 검은색으로 표시된 글로벌 서비스를 보여줍니다.

더 알아보기

  • Swarm 모드에서 노드가 어떻게 동작하는지 알아보세요.
  • Swarm 모드에서 PKI가 어떻게 동작하는지 배워보세요.