클라이이언트는 어플리케이션 실행을 요청한다. 어플리케이션은 Yarn API를 구현한 프로그램이면 된다.
이때, ResourceManager는 실행 요청이 유효할 경우 클라리언트에 새로운 Application ID를 할당한다.
ResourceManager는 NodeManager에게 Application Master 실행을 요청한다.
NodeManager는 ResourceManager의 요청을 받고, 컨테이너에서 ApplicationMaster를 실행한다.
이때, 컨테이너는 새로운 JVM을 생성해 ApplicationMaster를 실행한다.
ApplicationMaster는 ResourceManager에게 어플리케이션을 실행하기 위한 리소스를 요청한다.
이때 고려하는 리소스는 필요한 호스트
, 랙 정보
, 메모리
, CPU
, Network 정보
, 컨테이너 개수
등으로 구성된다. ResourceManager는 전체 클러스터의 리소스 상태를 확인한 후 ApplicationMaster에게 NodeManager 목록을 전달한다.
ApplicationMaster는 할당받은 NodeManager들에게 컨테이너 실행을 요청한다.
여기 써져 있는 Yarn Client는 우리가 실제로 잡을 서밋하는 클라이언트라고 보면 됨.
클라이언트가 어플리케이션을 Yarn Cluster 에서 실행하려면 Yarn Cluster 에서 신규 Application ID를 발급받아야 한다.
클라이언트는 ClientRMService 의 createNewApplication()
(createApplication()
)을 호출해서 Application ID 발급을 요청한다.
ClientRMService는 클라이언트의 요청에 새로운 Application ID와
Yarn 클러스터에서 최대로 할당할 수 있는 리소스 정보가 설정되어있는 GetNewApplicationResponse 객체를 전달한다.
클라이언트는 Application ID가 정상적으로 반환됐는지 확인하고, ClientRMService 의 submitApplication() 메소드를 호출한다.
이때 파라미터로 ApplicationSubmissionContext를 전달한다.
ApplicationSubmissionContext는 ResourceManager가 해당 어플리케이션의 ApplicationMaster를 실행하기 위한 다음 정보를 포함하고 있다.
클라이언트는 ClientRMService 의 getApplicationReport로 ResourceManager에게 ApplicationReport 를 요청한다.
ResourceManager는 어플리케이션이 정상적으로 등록됐을 경우, ApplicationReport를 반환한다.
ApplicationReport는 Yarn 클러스터에서 실행되는 어플리케이션의 통계정보를 담고 있다. 다음 정보를 포함한다.
ApplicationId
of the application.ApplicationMaster
is running.ApplicationMaster
.YarnApplicationState
of the application.Token
of the application (if security is enabled).ContainerId
of the container.Resource
allocated to the container.(vcpu, memory 등등)LocalResource
necessary for running the container such as binaries, jar, shared-objects, side-files etc.(실행파일 같은 거. 자바 library 등)NodeManager가 ApplicationMaster를 정상적으로 실행했을 경우, 해당 ApplicationMaster가 ResourceManager에게 등록돼야 한다.
그래야 ResourceManager는 클러스터 내에서 실행하는 여러 ApplicationMaster에게 자원을 할당하고, 상태를 모니터링 할 수 있다.
ApplicationMasterProtocol은 ResourceManager와 ApplicationMaster 사이에 필요한 인터페이스가 정의되어있다.
Yarn 은 ApplicationMasterProtocol을 구현한 기본 클라이언트인 AMRMClient, AMRMClientAsync 를 제공한다.
또한 기본 클라이언트 외에 직접 ApplicationMasterProtocol 인터페이스를 이용해서 구현할수도 있다.
ApplicationMasterProtocol
의 인터페이스들
allocate
(AllocateRequest
request): AllocateResponse
finishApplicationMaster
(FinishApplicationMasterRequest request): FinishApplicationMasterResponse
registerApplicationMaster
(RegisterApplicationMasterRequest
request): RegisterApplicationMasterResponse
ApplicationMaster 에 있는 클라이언트는 registerApplicationMaster() 메소드를 호출해서 ApplicationMaster등록을 요청한다.
이때 전달되는 RegisterApplicationMasterRequest 안에는 다음 내용이 포함된다.
ResourceManager의 ApplicationMaster목록을 관리하는 ApplicationMasterService는
자신이 관리하는 ApplicationMaster목록에 해당 ApplicationMaster를 추가한 뒤, AllocateResponse 객체를 반환한다.
AllocateResponse에는 다음과 같은 정보들이 있다.
ApplicationMaster
take some actions (resync, shutdown etc.).Container
.Container
s' statuses.Container
representing the containers whose resource has been increased.Container
representing the containers whose resource has been decreased.ApplicationMaster는 allocate() 메소드를 호출해서 어플리케이션을 실행하는데 필요한 리소스 할당을 요청한다.
이때 AllocateRequest 를 전달한다. AllocateRequest에는 다음과 같은 내용이 담겨있다.
ResourceRequest
to inform the ResourceManager
about the application's resource requirements.Container
which are being returned.UpdateContainerRequest
to inform the ResourceManager
about the change in requirements of running containers.allocate() 메소드는 ApplicationMaster의 클라이언트가 ResourceManager에게 자신의 상태를 알려주기 위한 heartbeat 용도로 사용된다.
ResourceManager는 AllocateRequest에 포함되어 있는 어플리케이션의 진행 상태나 heartbeat 전송 주기를 체크해서 ApplicationMaster의 상태를 알 수 있다.
이렇게 allocate() 메소드가 heartbeat 용도로 주기적으로 호출되기 때문에,
ApplicationMaster는 필요한 컨테이너를 한 번에 할당받지 못하더라도 최종적으로 필요한 모든 컨테이너를 할당받을 수 있다.
ApplicationMasterService는 컨테이너 할당 요청을 스케줄러에게 위임한다. 스케줄러는 해당 컨테이너가 가용한지를 알려준다.
ApplicationMasterService가 스케줄러의 응답 결과를 AllocateResponse에 설정한 뒤 ApplicationMaster에게 반환한다.
역할 | 위치 | 설명 |
---|---|---|
ApplicationMasterService | ResourceManager 내부 | AM 요청을 받아 스케줄러에 위임하고 결과를 AM에게 전달 |
Scheduler | ResourceManager 내부 | 클러스터 전체 리소스 기준으로 컨테이너 할당 가능 여부 결정 |
ApplicationMaster는 자신이 할당받은 컨테이너에서 어플리케이션을 실행해야 한다. 이때 ApplicationMaster는 NodeManager와 상호작용한다.
컨테이너에서 실행했던 어플리케이션들이 종료되면 ApplicationMaster도 종료되어야 한다.
ApplicationMaster의 종료로 하나의 어플리케이션의 라이프사이클이 종료된다.
ApplicationMaster의 클라이언트는 ResourceManager에게 ApplicationMaster의 종료를 요청한다.
ApplicationMasterService는 해당 ApplicationMaster를 ResourceManager에서 해제하고 FinishApplicationMasterResponse를 전달한다.
하둡 Map Reduce에서는 Map Task
와 Reduce Task
사이에 셔플 작업을 한다.
Map Task
: 입력 데이터를 작은 조각(split)으로 나누고, 각 조각에서 필요한 데이터를 맵핑해 (키, 값)
형태의 중간 데이터 생성Reduce Task
: 중간 데이터를 키별로 모아서 집계/처리Suffle
: Map Task
의 출력 데이터를 키 기준으로 나눠서 Reduce Task
로 전송하는 과정. 데이터 이동과 재배치셔플 단계에서 리듀스로 전송할 데이터를 파티셔닝하고, 파티셔닝 된 데이터를 네트워크로 전달한다.
Yarn 클러스터에서 Map Reduce 어플리케이션을 실행할 경우, Map Task
는 노드 매니저의 컨테이너에서 실행된다.
그런데 NodeManager는 컨테이너에서 실행 중이던 어플리케이션 실행이 종료될 경우 컨테이너도 함께 종료시킨다.
이렇게 컨테이너가 종료된다면 Map Task
는 Reduce Task
에 데이터를 전달할 수 없게된다.
따라서 별도의 조치를 취하지 않으면 셔플이 일어날 수 없다.
Yarn은 이런 상황의 방지를 위해서 Auxiliary Service(보조 서비스)
를 제공한다.
Auxiliary Service는 NodeManager 사이의 서비스 제어를 위한 기능이다.
이 서비스를 이용해서 서로 다른 NodeManager 사이에 데이터를 전달하거나, 다른 NodeManager를 제어할 수 있다.
Auxiliary Service를 Map Reduce에 적용하면 Map Task
를 실행하는 NodeManager와 Reduce Task
를 실행하는 NodeManager 사이에 셔플(데이터 전송 및 재배치)이 가능해진다.
클라이언트가 ResourceManager에게 어플리케이션 실행을 요청한다.
ResourceManager는 해당 어플리케이션의 ApplicationMaster를 실행한다.
Yarn은 Map Reduce의 ApplicationMaster로 MRAppMaster를 제공한다.
ResourceManager가 ApplicationMaster 실행을 요청하면 NodeManager가 컨테이너에서 MRAppMaster를 실행한다.
MRAppMaster는 또 다른 NodeManager에게 Map Task
의 실행을 요청한다.
NodeManager는 컨테이너에서 Map Task
를 실행한다.
NodeManager에서 실행된 Map Task
는 태스크 수행 결과를 셔플을 통해 Reduce Task
에 전달한다.
ShuffleHandler
이다. source어플리케이션 실행 요청
ApplicationMaster 실행
Map Task 실행 요청
Map Task 수행 및 결과 생성
Shuffle 단계 (데이터 전송 및 재배치)
Reduce Task
가 실행될 NodeManager들이 Map Task
가 생성한 데이터를 네트워크로 받아옴 (즉, Pull 방식) > 이 과정을 Shuffle이라 함ShuffleHandler
이다. sourceReduce Task 실행 및 최종 결과 생성
MapReduce의 Shuffle 에서 사용할 서비스를 다음 두가지 방법으로 커스텀하게 설정할 수 있다.(pluggable)
요즘은 MapReduce를 직접 구현하기보다는 Spark, Flink, Streaming과 같은 전문 프레임워크를 활용한다. 이러한 프레임워크들은 내부적으로 YARN 위에서 실행될 수 있도록 셔플이나 리소스 관리 같은 복잡한 기능들을 이미 구현해 두었기 때문에, 사용자는 추상화된 고수준 API만 활용하면 된다. 따라서 YARN의 세부 워크플로를 몰라도 프레임워크를 사용하는 데에는 큰 문제가 없다.
그러나 내부 동작 원리를 이해하고 넘어가는 것은 중요하다. 이를 통해 아키텍처 설계 방법, 구현 기법, 디자인 패턴, 대규모 데이터 처리에서 검증된 안정적인 방식들을 배울 수 있으며, 이는 다른 서비스 요구사항을 구현할 때 유용한 아이디어로 활용될 수 있다. 또한 특정 API를 사용하지 않는 상황이나 예상치 못한 오류, 버그 해결 과정에서도 이러한 이해가 문제를 파악하고 해결책을 찾는 데 큰 도움이 될 것