RIOT 에서 온라인 서비스 운영하기: PART II (한글 번역)

11월 4일, 2016

우리는 Kyle Allan과 Carl Quinn입니다. 우리는 Riot의 인프라 팀에서 일합니다. Riot이 전 세계의 인프라에서 백엔드 기능을 어떻게 배치하고 운영하는지 자세히 설명하는 시리즈의 두 번째 블로그 게시글에 오신 것을 환영합니다. 이 글에서는 deployment 생태계의 첫 번째 핵심 구성 요소 인 컨테이너 스케줄링에 대해 알아볼 것입니다.

Jonathan의 첫번째 글은 Riot의 배포 역사와 우리가 직면했던 문제에 대해서 이야기 했습니다. 특히 급히 성장하는 LoL을 지원하기 위해 인프라를 수동으로 구성함에 겪은 어려움들을 말했습니다. 그리고, 많은 툴 중 Docker를 이용하여 배포를 관리했습니다. 그리고 그 결과 Admiral이라는 클러스터 스케줄링과 관리를 하는 내부 툴로 발전하였습니다. (VMware에서도 이름이 비슷한 소프트웨어를 가지고있습니다. – 위대한 사람끼리는 비슷한 생각을 가진것 같군요)

앱 배포와 관련된 여정은 끝나지 않고, 끊임없이 진화하고 있습니다. 우리도 진화에 맞춰 준비중에 있습니다(잠재적으로 DC / OS 채택, 나중에 설명). 이 기사는 이 시점에 어떻게 도달했으며 왜 우리가 이러한 결정을 내린 이유를 설명합니다.

스케줄링은 무엇이고 왜 해야하는가?

Docker가 출시되고 Linux 컨테이너가 널리 이해되는 기술이되었을 때, 우리는 컨테이너 구현화를 통해 더 발전할 수 있다는 것을 알았습니다. Docker 컨테이너 이미지는 빌드되면 개발자, 테스트 및 프로덕션에 배포 할 수있는 환경을 제공합니다. 또한 실행되는 이미지의 의존성은 프로덕션 환경에서 그대로 유지됩니다.

특히 2번째 특성은 굉장히 중요합니다. Docker는 서버(호스트)에서 컨테이너를 분리한 뒤, 스케줄러를 사용하여 컨테이너를 호스트에 할당할 수 있습니다. 이는 서버와 어플리케이션 간의 결속을 제거합니다. (컨테이너는 여러 서버에서 실행가능)

우리는 Docker 이미지에 패키징 된 백엔드 서비스를 언제든지 배포하고 여러 대의 서버로 확장 할 수 있으므로 신속하게 변화에 적응할 수 있었습니다. 또, 플레이어 기능을 추가하고 트래픽이 많은 기능을 Scale out하고 업데이트 및 수정 사항을 신속하게 출시 할 수 있었습니다. 컨테이너 서비스를 프로덕션 환경에 배포하는 것을 고려할 때, 우리는 세 가지 문제에 직면하였습니다.
우리가 다룰 문제들:

 1.  서버들이 있을 때, 특정 서버들이 특정 컨테이너를 받기 위해 어떻게 해야하는가?
2. 컨테이너들이 실제로 어떻게 원격호스트에서 시작하는가?
3. 컨테이너가 죽으면 어떻게 되는가?

위 문제들을 해결하기 위해 우리는 클러스터단에서 운용되는 서비스인 스케줄러가 필요했습니다. 스케줄러는 클러스터 관리에 핵심이었으며, 재생산의 기능도 하였습니다. 예를 들면, 우리가 Hextech Crafting과 같은 서비스를 만들 때, 6개의 컨테이너 인스턴스가 필요했습니다. 스케줄러는 메모리와 CPU가 충분한 자원에 접근하여 컨테이너를 배치합니다. 만약 어떤 서버가 다운되더라도, 스케줄러가 알아서 컨테이너를 재배치 해줍니다.

스케줄러를 사용하려 했을 때, 우리는 프로덕션 환경에서 실제로 잘 작동하는 지 알아보기 위해서 테스트를 하루 빨리 해보고 싶었습니다. 추가적으로, 기존의 오픈소스 기능들이 우리의 환경에서 작동하여야 했으며, 우리 관리자들이 변화를 받아 들여야 했습니다.

왜 우리 것을 직접 만들었나?

Admiral에 대해 말하기 전에, 우리 클러스터 관리자들과 스케줄러의 환경을 조사했습니다. 누가 Docker의 컨테이너를 스케줄링 하고 있었으며, 어떻게 하고 있었나?

조사한 몇몇 프로젝트들:

Mesos + Marathon

  • 이 기술들은 꽤나 성숙되어 있었으며, 크게 확장 될 수 있었지만 복잡했으며 설치하기 어려웠음. 그래서 실험과 평가하는데 어려움이 있었음

  • Docker 환경에 잘 적응하지 못했으며, 컨테이너에 대한 지원이 부족함

  • 우리의 서비스들을 묶는 컨테이너 그룹 (pods)을 지원하지 못함

LMCTFY => Kubernetes

  • Kubernetes 은 LMCTFY에서 진화한 것입니다. 전도가 유망해 보였지만 우리가 원하는 게 있는지 잘 모름

  • Kubernetes 컨테이너 배치를 할 수 있는 시스템이 없음

Fleet

  • 최근에 생겨서 아직 기능 부족

  • 일반적인 앱 시스템보다는 배포 환경에 적합한 서비스

또한 우리는 Docker API를 REST방식으로 명령하는 툴을 사용해봤습니다. 이 때 우리는 배포를 어떻게 해야 조율이 잘 될 지 알았습니다. 그래서 우리의 스케줄러를 만들었고, 조사한 Kubernetes’ Pods and Marathon’s constraint system를 참고하여 최고의 조합을 만들었습니다.

ADMIRAL 요약

우리는 CUDL(ClUster Description Language)라는  JSON 기반 메타 데이터 언어를 작성한 후 Admiral을 만들기 시작했습니다. 이것은 Admiral이 RESTful API에서 사용한 언어가되었습니다. CUDL의 두 가지 주요 구성 요소는 다음과 같습니다.

  • Clusters – docker hosts들의 집합.

  • Packs – 컨테이너를 만들기 위한 메타데이터. Kubernetes Pod + Replication Controller와 비슷합니다.

Clusters와 Packs 에는 spec과 live라는 두 가지 측면이 있습니다. 각 측면은 컨테이너 라이프 사이클의 다른 단계를 나타냅니다. 아래에 부연설명하겠습니다.

Spec, 은 원하는 element의 상태를 나타내는 것입니다.

  • 소스 제어와 같은 일부 외부 자원으로부터 Admiral에 게시 됨

  • Admiral에 한 번 보내면 바꾸지 못함

  • Spec Cluster 및 호스트는 클러스터에서 사용 가능한 리소스를 나타냄

  • Spec Pack은 서비스를 실행하는 데 필요한 리소스, 제약 조건 및 메타 데이터를 설명합니다.

Live, 은 현재 element의 상태를 나타내는 것입니다.

  • 현재 실행중인 개체를 미러링합니다.

    • Live Cluster 및 호스트는 Docker 데몬 미러링

    • Live Pack은 Docker 컨테이너 그룹을 미러링

  • Docker 데몬과 통신하여 복구 가능

Admiral은 Go언어로 작성되었으며, 프로덕션 데이터 센터에서 실행될 때  Docker 컨테이너로 컴파일되고 패키징됩니다. Admiral에는 몇 가지 내부 하위 시스템이 있으며,  아래 다이어그램에 나와 있습니다.

사용자의 관점에서, Admiral과의 상호 작용은 REST API를 통해 Admiral과 통신하는 제공된 admiralctl 명령 줄 도구를 사용하여 수행됩니다. admiralctl을 사용하면 사용자는 표준 동사(post,delete,get)를 통해 Admiral의 모든 기능에 액세스 할 수 있습니다.
Post: New Pack스케줄링
Delete: Old Pack 삭제
Get : 현재 상태 가져오기

생산 과정에서 Admiral은 Hashicorp ‘s Consul을 사용하여 사양 상태를 저장합니다. Hashicorp Consul은 치명적인 오류 발생시 정기적으로 백업합니다. 완전한 데이터 손실이 발생한 경우 Admiral은 개별 Docker 데몬에서 검색 한 라이브 상태의 정보를 사용하여 스펙 상태를 부분적으로 다시 빌드 할 수도 있습니다.

Reconciler는 Admiral의 핵심에 있으며 스케줄링 워크 플로를 주도하는 핵심 하위 시스템입니다. 조정자는 실제 작동 상태와 원하는 사양 상태를 주기적으로 비교하고 불일치가있을 때 실시간 상태를 다시 가져 오는 데 필요한 작업을 예약합니다.

livestate 및 해당 드라이버 패키지는 실시간 호스트 및 컨테이너 상태를 캐시하고 REST API를 통해 클러스터 호스트의 모든 Docker 데몬과 통신을 제공하여 조정자를 지원합니다.

스케줄링 (심화)

Admiral의 Reconciler는 Spec Pack을 사용하여 효과적으로 Spec Pack을 Live Pack으로 바꿔줍니다. Spec Pack이 Admiral에 보내지면 Reconciler는 컨테이너를 작성하고 Docker 데몬을 사용하여 컨테이너를 시작합니다. 이 메커니즘을 통해 Reconciler는 앞에서 설명한 처음 두 개의  목표를 달성합니다. Reconciler가 Spec Pack을 받으면 다음을 수행합니다:

  1.  Cluster의 자원과 Pack의 제약 조건을 평가하여 컨테이너에 적합한 호스트를 찾습니다.

  2.  Spec의 데이터를 사용하여 원격 호스트에서 컨테이너를 시작할 수 있습니다.

Docker 호스트에서 컨테이너를 시작하는 예제를 살펴 보겠습니다. 이 예제에서는 로컬 Docker 데몬을 Docker 호스트로 사용하고 Admiral 서버의 로컬 인스턴스와 상호 작용할 것입니다.

우선, ‘admiral pack create <cluster name> <pack file>’명령을 사용하여 Pack을 시작합니다. 이 명령은 특정 Cluster를 대상으로 Spec Pack JSON을 Admiral 서버에 제출합니다.

명령을 실행 한 직후 거의 동시에 컨테이너가 시작되었음을 알 수 있습니다. 이 컨테이너는 아래와 같은 Pack 파일의 매개 변수를 사용하여 시작되었습니다:

{
     "name": "dat.blog_명령을 실행 한 직후 거의 동시에 컨테이너가 시작되었음을 알 수 있습니다. 이 컨테이너는 아래와 같은 Pack 파일의 매개 변수를 사용하여 시작되었습니다:scout",
     "description": "A pack of the Scout service for usage in our engineering blog post.",
     "service": {
          "location": "dev.local.test",
          "discovery": {},
          "appname": "dat.scout"
     },
     "containers": [
          {
               "image": "datd/scout",
               "version": "1.0.0",
               "ports": [{
                    "internal": 8080,
                    "external": 8080
               }]
          }
     ],
     "count": 1
}

다음으로, 우리는 admiral pack create ‘를 호출 한 후에`show` 명령을 사용하여 Admiral이 만든 Live Pack을 볼 수 있습니다. 여기서 명령은`admiral pack show <cluster name> <pack name>`입니다.

마지막으로 컨테이너 내에서 서비스를 실행하여 팩이 작동하는지 확인할 수 있습니다. `admiral pack show` 명령의 정보를 사용하여 우리는 우리의 서비스에 굉장히 중요한 CURL을 만들 수 있습니다 :

Admiral안에서 Reconciler는 항상 실행 중으로, Cluster의 Live 상태가 항상 원하는 Spec 상태와 일치하는지 확인합니다. 이렇게하면 컨테이너가 고장 나거나 충돌로 인해 종료되거나 하드웨어 오류로 인해 전체 서버를 사용할 수 없게 된 경우에도 복구 할 수 있습니다. Reconciler는 상태가 일치하도록 하여, Players가 방해를받지 않도록 하고 있습니다. 이 함수는 앞에서 설명한 세 번째이자 마지막 문제를 해결합니다. 컨테이너가 예기치 않게 종료되면 빠르게 복구되고 최소화된 영향만 줍니다.

아래에서는`admiral pack create` 명령을 통해 시작된 기존 컨테이너를 보여줍니다. 그런 다음 컨테이너를 종료하고 실행을 중지합니다. 몇 초 내에 Reconciler가 새 컨테이너 (ID가 다른 컨테이너)를 시작합니다. 실제 상태가 원하는 상태와 일치하지 않음을 확인하고 Reconciler가 새 컨테이너를 시작합니다.

자원과 제약들

컨테이너를 잘 배치하기 위해서, 아래와 같은 2가지가 필요합니다:

자원 – 메모리, CPU, I / O 및 네트워킹을 포함한 서버의 사용 가능한 리소스를 나타냅니다.

제약 – pack의 조건들. 스케줄러에게 pack이 배치될 수 있는 곳의 제한 사항을 알려줌. 예를 들면, 아래의 조건을 가진 인스턴스에 팩을 올리려고 할 때:

  • 클러스터의 서버마다 설치

  • ‘myhost.riotgames.com’ 이름의 서버에 설치

  • 표시를 해놓은 클러스터 서버에만 설치

우리의 자원을 정의함으로, 스케줄러에게 컨테이너를 어디에 배치할 지 유연성을 제공합니다. 팩의 조건을 제약함으로, 스케줄러의 선택에 영향을 주어 우리가 원하는 데로 설치가 될 수 있도록 합니다.

결론

Riot에서, Admiral 은 배포의 기능에서 굉장히 중요한 역할을 맡고 있습니다. Docker의 능력과 스케줄링 시스템으로 우리는 백엔드 기능을 사용자에게 더 빠르게 전달 할 수 있었습니다.

이 글에서는 Admiral의 몇 가지 기능에 대해 살펴보고 클러스터간 컨테이너 스케줄링에 대해 설명했습니다. Jonathan이 첫 번째 게시물에서 언급했듯이 오픈 소스 세계는 매우 유사한 모델로 빠르게 옮겨갔습니다. 앞으로 우리는 Admiral보다 DC / OS 배포에 중점을 둘 것입니다.

피드백은 항상 환영합니다.

Advertisements

RIOT 에서 온라인 서비스 운영하기: PART II (한글 번역)”에 대한 1개의 생각

  1. 핑백: RIOT 에서 온라인 서비스 운영하기: PART I (한글 번역) | Kyupok's AWS Study 블로그

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중