펜타시스템/입사 후 첫 프로젝트 공부 내용

Spark on YARN 정리

dev-lee 2026. 10. 21. 15:17

1. Spark on YARN 개요

Hadoop의 리소스 매니저인 YARN이 Spark의 드라이버와 익스큐터를 컨테이너로 띄워주는 실행 방식임

1.1 YARN을 사용하는 방식

  • 리소스 위임 : Spark가 직접 리소스를 관리하지 않고 YARN에 CPU·메모리 할당을 맡김
  • master 값 : --master yarn으로 지정하며 클러스터 위치는 HADOOP_CONF_DIR의 설정 파일에서 읽어옴
  • 주 사용처 : 온프레미스 Hadoop 환경, AWS EMR 등

YARN은 Spark 전용 매니저가 아니라 Hadoop 클러스터 전체의 범용 리소스 매니저이므로 Hive, MapReduce, Spark 작업이 같은 클러스터를 공유함


2. YARN 구성 요소

ResourceManager, NodeManager, ApplicationMaster, Container 네 가지가 핵심 구성 요소임

2.1 구성 요소별 역할

구성 요소 위치  역할
ResourceManager (RM) 마스터 노드 클러스터 전체 리소스를 관리하고 컨테이너를 할당함
NodeManager (NM) 워커 노드 노드의 컨테이너를 실행하고 리소스 사용량을 모니터링함
ApplicationMaster (AM) 컨테이너 내부 애플리케이션별로 하나씩 뜨며 RM에 리소스를 요청하고 작업을 조율함
Container 워커 노드 CPU·메모리가 할당된 실행 단위이며 Spark 익스큐터가 여기서 동작함

2.2 ResourceManager 내부

  • Scheduler : 큐 정책에 따라 컨테이너를 할당하며 실제 작업 모니터링은 하지 않음
  • ApplicationsManager : 애플리케이션 제출을 받고 첫 번째 컨테이너(AM)를 띄우며 AM 실패 시 재시작을 담당함

3. 실행 흐름

spark-submit 제출부터 익스큐터 실행, 종료까지의 과정임

3.1 cluster 모드

  1. spark-submit --master yarn --deploy-mode cluster로 제출함
  2. 클라이언트가 RM에 애플리케이션을 등록하고 Spark jar와 설정을 HDFS에 업로드함
  3. RM이 NodeManager 한 곳에 첫 컨테이너를 할당하고 ApplicationMaster가 실행됨
  4. Spark 드라이버가 ApplicationMaster 안에서 실행됨
  5. AM이 RM에 익스큐터용 컨테이너를 요청함
  6. 각 NodeManager에서 익스큐터가 실행되어 드라이버와 통신하며 태스크를 처리함
  7. 작업이 끝나면 컨테이너가 반환되고 애플리케이션이 종료됨

3.2 client 모드

  • 드라이버 위치 : spark-submit을 실행한 머신에서 실행됨
  • AM 역할 : 드라이버 실행 없이 익스큐터 리소스 요청만 담당함
  • 네트워크 조건 : 익스큐터가 드라이버로 접속해야 하므로 클러스터에서 제출 머신으로의 통신이 열려 있어야 함

3.3 client 모드와 cluster 모드 비교

구분 client  cluster
드라이버 위치 제출 머신 클러스터 내부 (AM 컨테이너)
AM 역할 리소스 요청만 드라이버 실행 + 리소스 요청
로그 확인 터미널에 바로 출력됨 yarn logs -applicationId <id>
제출 머신 종료 시 드라이버가 죽어 작업 실패 영향 없음
용도 spark-shell, 노트북, 디버깅 운영 배치 작업

4. 리소스 설정

익스큐터 수, 코어, 메모리 설정과 YARN 컨테이너 크기의 관계를 이해해야 함

4.1 제출 옵션

spark-submit \
  --master yarn \
  --deploy-mode cluster \
  --queue etl \
  --num-executors 10 \
  --executor-cores 4 \
  --executor-memory 8g \
  --driver-memory 4g \
  app.py
  • --num-executors : 요청할 익스큐터 수
  • --executor-cores : 익스큐터당 코어 수
  • --executor-memory : 익스큐터 JVM 힙 크기
  • --queue : 사용할 YARN 큐

4.2 컨테이너 메모리 구조

  • 컨테이너 크기 : executor-memory + memoryOverhead의 합으로 YARN에 요청됨
  • spark.executor.memoryOverhead : 힙 외 메모리(off-heap, 스레드 스택, 파이썬 프로세스 등)이며 기본값은 힙의 10%(최소 384MB)임
  • PySpark 사용 시 : 파이썬 워커 메모리가 overhead에 포함되어 부족해지기 쉬우므로 값을 여유 있게 잡아야 함
  • YARN 상한 : 요청한 컨테이너 크기가 yarn.scheduler.maximum-allocation-mb를 넘으면 제출 단계에서 실패함
YARN 설정  의미
yarn.nodemanager.resource.memory-mb 노드 하나가 컨테이너에 내줄 수 있는 총 메모리
yarn.scheduler.minimum-allocation-mb 컨테이너 최소 할당 단위 (요청값이 이 단위로 올림됨)
yarn.scheduler.maximum-allocation-mb 컨테이너 하나의 최대 크기

컨테이너 크기는 최소 할당 단위의 배수로 올림되므로 요청한 값보다 실제 점유 메모리가 더 클 수 있음


5. 스케줄러와 큐

YARN은 스케줄러 정책에 따라 여러 팀과 작업이 클러스터를 나눠 쓰도록 제어함

5.1 스케줄러 종류

스케줄러  특징
FIFO 먼저 제출된 작업부터 처리함. 단순하지만 공유 환경에는 부적합
Capacity 큐별로 용량을 보장하고 남는 리소스를 다른 큐가 빌려 쓸 수 있음. Apache Hadoop의 기본값
Fair 실행 중인 애플리케이션에 리소스를 균등하게 분배함

5.2 큐 운영

  • 멀티 테넌시 : 팀이나 워크로드별로 큐를 나눠 리소스를 격리함
  • ACCEPTED 상태 지속 : 큐에 여유 리소스가 없을 때 발생하며 작업이 RUNNING으로 넘어가지 못하고 대기함
  • Preemption : 보장 용량을 넘겨 쓰는 큐에서 컨테이너를 회수해 다른 큐에 돌려주는 기능임

6. Dynamic Allocation

부하에 따라 익스큐터 수를 자동으로 늘리고 줄이는 기능임

6.1 설정

  • spark.dynamicAllocation.enabled : 기능 활성화 여부
  • minExecutors / maxExecutors : 익스큐터 수의 하한과 상한
  • 셔플 데이터 보존 : 익스큐터가 제거되어도 셔플 파일을 읽을 수 있어야 하므로 아래 방식 중 하나가 필요함
방식  설명
External Shuffle Service NodeManager의 aux-service로 셔플 파일을 대신 서빙함 (spark.shuffle.service.enabled=true)
Shuffle Tracking 셔플 데이터를 가진 익스큐터를 유지하는 방식 (spark.dynamicAllocation.shuffleTracking.enabled=true, Spark 3.0 이상)

7. 의존성 배포

클러스터 노드에 Spark와 파이썬 라이브러리가 없어도 실행되도록 패키징해서 전달함

7.1 방법

  • spark.yarn.archive / spark.yarn.jars : Spark 라이브러리를 HDFS에 미리 올려 두면 제출할 때마다 업로드하지 않아 시작이 빨라짐
  • --py-files : 파이썬 모듈이나 zip 파일을 함께 배포함
  • --archives : venv-pack 등으로 만든 가상환경 압축 파일을 배포해 라이브러리 버전을 고정함
  • --jars / --packages : 추가 JAR 의존성을 지정함

모든 노드에 같은 라이브러리를 설치하는 방식은 관리가 어려워서 가상환경 아카이브로 배포하는 쪽이 일반적임


8. 모니터링과 로그

애플리케이션 상태와 로그는 YARN 명령어와 웹 UI로 확인함

8.1 상태 확인과 종료

yarn application -list
yarn application -status <applicationId>
yarn application -kill <applicationId>

8.2 로그 확인

  • yarn logs : yarn logs -applicationId <id>로 드라이버와 익스큐터 로그를 모아서 봄
  • 로그 집계 : yarn.log-aggregation-enable=true여야 종료 후에도 로그가 HDFS에 보관됨
  • Spark UI : 실행 중에는 RM 웹 UI의 ApplicationMaster 링크로 접근함
  • Spark History Server : 종료된 애플리케이션의 이벤트 로그를 기반으로 UI를 다시 보여줌

8.3 애플리케이션 상태

상태  의미
ACCEPTED RM이 접수했으나 AM 컨테이너를 아직 못 받은 상태
RUNNING AM이 실행 중인 상태
FINISHED 정상 종료 (최종 상태는 SUCCEEDED / FAILED로 구분됨)
KILLED 사용자 또는 관리자가 강제 종료한 상태

9. 자주 만나는 문제

메모리 초과와 리소스 대기가 가장 흔한 장애 유형임

9.1 문제별 원인과 해결

증상 원인 해결
Container killed by YARN for exceeding memory limits 힙 외 메모리 사용량이 컨테이너 한도 초과 memoryOverhead 증가
ACCEPTED 상태에서 진행 안 됨 큐 또는 클러스터 리소스 부족 큐 상태 확인, 요청 리소스 축소
제출 단계 실패 (Required executor memory is above the max threshold) 요청 크기가 maximum-allocation-mb 초과 메모리 요청 축소 또는 YARN 설정 상향
AM 반복 실패 드라이버 오류 또는 AM 컨테이너 종료 yarn logs 확인, spark.yarn.maxAppAttempts 조정

9.2 AM 재시도

  • spark.yarn.maxAppAttempts : AM 실패 시 재시도 횟수이며 기본값은 YARN 설정(yarn.resourcemanager.am.max-attempts)을 따름
  • 주의점 : 재시도되면 애플리케이션 전체가 처음부터 다시 실행되므로 멱등성이 없는 작업은 별도 처리가 필요함

10. 장단점

기존 Hadoop 자산을 활용하는 환경에서는 안정적이지만 클라우드 네이티브 환경에서는 운영 부담이 있음
장점  단점
기존 Hadoop 클러스터와 리소스를 공유함 Hadoop 환경을 따로 구축·운영해야 함
큐 기반 멀티 테넌시와 자원 격리가 성숙함 의존성 패키징이 컨테이너 이미지 방식보다 불편함
HDFS와 같은 노드에서 돌아 데이터 로컬리티에 유리함 클라우드 네이티브 환경에서는 Kubernetes로 이동하는 추세임

요약

항목  핵심 내용
구조 RM이 컨테이너를 할당하고 AM이 익스큐터를 조율함
배포 모드 운영은 cluster, 대화형 작업은 client
메모리 컨테이너 크기는 executor-memory + memoryOverhead이며 YARN 상한을 넘으면 제출 실패
리소스 공유 Capacity/Fair 스케줄러와 큐로 팀 간 자원을 격리함
Dynamic Allocation External Shuffle Service 또는 Shuffle Tracking 필요
로그 로그 집계를 켜고 yarn logs로 확인함
대표 장애 memoryOverhead 부족, 큐 리소스 부족(ACCEPTED 지속)

Spark on YARN은 RM과 AM이 컨테이너 단위로 리소스를 할당하는 구조이며, 컨테이너 메모리 구성과 큐 설정을 이해하면 대부분의 장애를 해결할 수 있음