Published on

EMR YARN 큐 설정: Capacity Scheduler와 Spark ACCEPTED 대기 진단

Authors

이 글은 Hadoop과 Spark 공식 문서를 바탕으로 한 설정과 진단 가이드다. 실제 클러스터의 변경값과 성능 전후 결과를 제시하는 사례 보고는 아니다.

들어가며

이전 글에서는 Capacity Scheduler와 Fair Scheduler의 차이와 큐 상세 화면을 읽는 방법을 살펴봤다. 이 글에서는 Capacity Scheduler를 사용하는 EMR 환경에서 설정을 조정하고 Spark 애플리케이션의 리소스 대기와 실행 중 종료 문제를 진단하는 내용을 이어서 다룬다.

이 글은 후속 설정 가이드다. 설정 설명은 Hadoop 3.3.5와 Spark 3.5.6 공식 문서를 기준으로 하며 실제 적용값과 변경 절차는 사용하는 EMR 릴리스에 맞춰 확인한다.

Spark가 ACCEPTED에서 멈출 때 먼저 확인할 것

Spark가 YARN의 ACCEPTED 상태에 오래 머문다면 ResourceManager의 Application 상세에서 Diagnostics를 먼저 읽는다. 큐 전체에 메모리가 남아 있다는 사실만으로 새 AM이 실행될 수 있다고 판단하면 안 된다. AM 한도, 사용자별 한도, 컨테이너 요청 크기, 배치 가능한 노드의 자원과 라벨을 함께 확인한다.

보이는 증상먼저 확인할 내용다음에 읽을 내용
애플리케이션이 ACCEPTED에서 대기Diagnostics, AM Used와 AM Limit, 사용자별 제한아래의 AM 한도와 사용자 제한 설정
RUNNING인데 Executor를 충분히 확보하지 못함Pending 요청, 큐 최대 용량, 노드별 가용 자원아래의 YARN UI 진단 절차
Task 메모리는 남는데 AM을 시작하지 못함AM이 배치될 수 있는 노드 라벨과 해당 노드의 여유EMR Node Label과 CORE·TASK 배치
실행 중 컨테이너가 메모리 초과로 종료됨컨테이너 종료 사유와 Driver·Executor 로그아래의 메모리 부족 구분

YARN 큐 메모리 부족과 Executor OOM은 어떻게 다른가

큐의 자원 할당 대기는 실행할 컨테이너를 아직 확보하지 못한 상태다. 반면 Container killed by YARN for exceeding physical memory limits는 실행 중인 컨테이너가 물리 메모리 한도를 넘긴 경우다. JVM의 OutOfMemoryError도 로그를 따로 확인해야 한다. AM 비율을 높이는 것만으로 Executor의 메모리 초과나 JVM 힙 부족이 해결되는 것은 아니다.

이 글은 큐 설정과 자원 대기를 중심으로 다룬다. 실행 중 메모리 오류는 로그에서 실패한 프로세스를 확인하고, 해당 프로세스의 메모리·오버헤드 설정과 작업의 데이터 크기를 따로 조사해야 한다. Spark on YARN의 메모리 설정과 로그 확인


EMR YARN 큐 설정은 어디에 적용하는가

Capacity Scheduler 설정 예시 (EMR)

EMR 클러스터의 capacity-scheduler.xml을 수정하거나 EMR 설정 파라미터로 주입할 수 있다.

EMR 설정 객체를 사용한다면 capacity-scheduler Classification의 Properties에 큐 설정을 지정한다. 지원되는 Classification과 실행 중 재구성 동작은 EMR 릴리스별로 확인한다. Amazon EMR 애플리케이션 구성

<property>
  <name>yarn.scheduler.capacity.root.queues</name>
  <value>default,high-priority</value>
</property>
<property>
  <name>yarn.scheduler.capacity.root.default.capacity</name>
  <value>40</value>
</property>
<property>
  <name>yarn.scheduler.capacity.root.high-priority.capacity</name>
  <value>60</value>
</property>

Fair Scheduler로 전환 (EMR)

EMR에서 Fair Scheduler를 사용하려면 yarn-site.xml에서 스케줄러 클래스를 변경해야 한다.

<property>
  <name>yarn.resourcemanager.scheduler.class</name>
  <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
</property>

[!WARNING] 실행 중인 클러스터에서 스케줄러를 교체하면 ResourceManager 재시작이 필요하며 실행 중인 잡이 영향을 받을 수 있다. EMR에서는 클러스터 생성 시 설정하는 것을 권장한다.

Capacity Scheduler 실전 — maximum-am-resource-percent

Capacity Scheduler를 사용하다 보면 반드시 한 번은 마주치는 설정이 있다. 잡을 제출했는데 ACCEPTED 상태에서 오랫동안 꿈쩍 않는다면 이 설정이 원인일 가능성이 높다.

ApplicationMaster(AM)란?

Spark 잡이 YARN 위에서 실행될 때 가장 먼저 ApplicationMaster 컨테이너가 클러스터에 뜬다. AM은 잡의 "관제탑"으로서 Executor 컨테이너의 요청과 관리 및 ResourceManager와의 리소스 협상을 담당한다.

AM이 먼저 자리를 잡아야 그 뒤에 Executor들이 뜰 수 있다. AM 컨테이너를 위한 자리가 없으면 잡 전체가 시작조차 못한다.

maximum-am-resource-percent 란?

<property>
  <name>yarn.scheduler.capacity.maximum-am-resource-percent</name>
  <value>0.1</value>
</property>

AM 용도로 사용할 수 있는 자원의 비율을 제한하는 설정이다. 실제 큐별 한도는 큐 용량과 사용자 제한 등을 반영하므로 클러스터 전체 메모리에 비율만 곱한 값과 항상 같지는 않다. YARN UI의 현재 AM 한도와 사용량을 함께 확인해야 한다.

  • 기본값: 0.1 (10%)
  • 큐별 설정으로 전역 기본값을 재정의할 수 있다.
  • AM 한도는 현재 사용량과 별개이며 나머지 자원이 Executor에 자동으로 할당되는 것은 아니다.

아래는 AM 한도 계산 기준 메모리를 100GiB로 가정하고 다른 제약과 할당 단위의 영향은 제외한 단순 비율 예시다.

가정한 기준 메모리maximum-am-resource-percent비율상 AM 한도
100GiB0.1 (10%)10GiB
100GiB0.2 (20%)20GiB

Spark의 client 모드에서 AM 힙 기본값은 512MiB이고 기본 오버헤드는 최소 384MiB다. 실제 컨테이너 요청량은 YARN의 최소 할당량과 증분 단위에 맞춰 조정될 수 있다. 예를 들어 896MiB 요청이 1024MiB로 조정되고 현재 AM 메모리 한도가 10GiB라면 메모리만으로 계산한 동시 AM 수는 10개다. CPU와 사용자 제한 등은 별도로 적용된다.

cluster 모드에서는 Driver가 AM 프로세스 안에서 실행되므로 spark.driver.memory와 관련 오버헤드 설정을 확인해야 한다.

참고 문서Apache Spark 3.5.6 공식 문서 - YARN의 배포 모드와 AM 메모리

주로 문제가 생기는 패턴

패턴 1: 짧은 잡이 대량으로 동시 제출될 때 파이프라인에서 여러 작은 Spark 잡이 동시에 트리거되면 각 잡마다 AM이 1개씩 필요해 한도에 빠르게 걸린다.

패턴 2: AM 메모리를 크게 설정했을 때

spark-submit --master yarn --deploy-mode client \
  --conf spark.yarn.am.memory=4g app.py

AM 힙을 4GiB로 설정하면 오버헤드까지 더한 컨테이너 요청량이 커진다. 같은 AM 한도에서 실행 가능한 애플리케이션 수가 줄어든다. 이 설정은 SparkContext가 생성되기 전에 제출 옵션 등에 지정한다.

패턴 3: 큐별 설정이 없을 때 큐별 설정이 없으면 전역 yarn.scheduler.capacity.maximum-am-resource-percent 값이 적용된다. 여러 팀이 같은 큐를 공유하면 서로의 잡이 AM 한도를 잡아먹는다.

해결 방법

방법 1: maximum-am-resource-percent 값 올리기

<property>
  <name>yarn.scheduler.capacity.maximum-am-resource-percent</name>
  <value>0.25</value>
</property>

[!WARNING] AM과 Executor가 같은 자원을 경쟁하는 환경에서는 1.0이 Executor 여유를 줄일 수 있다. 반면 AWS는 Managed Scaling과 Node Label을 함께 사용하며 여러 앱을 병렬 실행하는 구성에서 1을 안내한다. 파티션과 릴리스 조건 없이 일괄 금지하거나 권장하지 않는다. AWS Managed Scaling 예시값을 그대로 권장값으로 사용하지 말고 AM 크기와 목표 동시 실행 수 및 Executor에 필요한 자원을 기준으로 조정한다.

방법 2: 큐별로 개별 설정

<property>
  <name>yarn.scheduler.capacity.root.high-priority.maximum-am-resource-percent</name>
  <value>0.3</value>
</property>

방법 3: AM 메모리 줄이기

spark-submit --master yarn --deploy-mode client \
  --conf spark.yarn.am.memory=512m \
  --conf spark.yarn.am.memoryOverhead=384m app.py

[!TIP] 위 예시는 client 모드용이다. cluster 모드에서는 AM 안에서 Driver가 실행되므로 Driver의 메모리 요구량까지 고려해야 한다. 고정된 메모리 크기를 모든 애플리케이션에 권장할 수는 없다.

방법 4: 잡 동시 실행 수 제한

YARN 설정 변경 없이 파이프라인 레벨에서 동시 실행 Spark 잡 수를 제어하는 방법. 예: Airflow에서 pool을 활용해 동시 실행 수 상한을 두는 방식.

EMR에서 적용하기

[
  {
    "Classification": "capacity-scheduler",
    "Properties": {
      "yarn.scheduler.capacity.maximum-am-resource-percent": "0.2"
    }
  }
]

[!WARNING] 파일 기반 큐 설정 변경은 yarn rmadmin -refreshQueues로 반영할 수 있다. EMR의 재구성 절차는 릴리스와 설정 Classification에 따라 서비스 재시작을 포함할 수 있으므로 적용 전 해당 릴리스의 재구성 동작을 확인한다.

참고 문서Amazon EMR 공식 문서 - 실행 중인 클러스터 재구성

Capacity Scheduler 실전 — user-limit-factor / minimum-user-limit-percent

maximum-am-resource-percent가 "AM 컨테이너의 총량"을 제한한다면 이 두 설정은 큐 안에서 한 사용자(user)가 얼마나 리소스를 독점할 수 있는지를 제어한다.

minimum-user-limit-percent

<property>
  <name>yarn.scheduler.capacity.root.default.minimum-user-limit-percent</name>
  <value>25</value>
</property>

자원 경쟁이 있을 때 사용자별 사용 한도를 계산하는 비율의 하한이다. 모든 사용자에게 해당 비율의 자원을 동시에 보장한다는 뜻은 아니다. 사용자 수와 수요 및 큐의 가용 자원에 따라 실제 할당량이 달라진다.

큐 용량minimum-user-limit-percent동시 사용자 수사용자별 한도 계산의 기준
100%25%1명100% (독점 가능)
100%25%2명50%
100%25%4명25%
100%25%5명 이상25% (한도 계산 비율의 하한)

위 표는 다른 제약을 제외한 설명용이다. 사용자가 5명일 때도 각자 25%를 반드시 할당받는다는 뜻은 아니며 모든 사용자에게 동시에 적용할 수 있는 자원 보장량으로 합산해서는 안 된다.

user-limit-factor

<property>
  <name>yarn.scheduler.capacity.root.default.user-limit-factor</name>
  <value>1</value>
</property>

한 사용자가 큐 할당량의 몇 배까지 리소스를 쓸 수 있는지를 결정하는 승수(multiplier)다.

  • 기본값: 1 → 큐 용량(capacity)의 최대 1배까지만 사용 가능
  • 2로 설정 시 → 큐 용량의 2배까지 빌려 쓸 수 있음 (다른 큐가 여유 있을 때)

[!WARNING] user-limit-factor를 너무 높게 설정하면 한 사용자의 잡이 큐 용량을 훨씬 초과해 다른 사용자의 잡이 리소스를 받지 못하는 상황이 생긴다. 적절한 값은 사용자 수와 큐의 최대 용량 및 실제 수요에 따라 결정한다.


Capacity Scheduler 실전 — Preemption

Preemption(선점)은 YARN이 리소스 부족 상태인 큐를 위해 다른 큐의 실행 중인 컨테이너를 강제로 종료시키는 기능이다. 비어 있는 클러스터 리소스가 없을 때도 최소 용량을 보장할 수 있게 해주는 강력한 도구지만 잘못 설정하면 멀쩡히 실행 중인 잡이 갑자기 죽는다.

동작 방식

1. 큐 A가 capacity(최소 보장량) 이하로 떨어짐
2. RM이 큐 B의 컨테이너에 "종료 예고(grace period)" 전송
3. grace period 내에 자발적으로 반환하지 않으면 강제 kill
4. 회수된 리소스를 큐 A에 배분

주요 설정

<!-- Preemption 전체 활성화 -->
<property>
  <name>yarn.resourcemanager.scheduler.monitor.enable</name>
  <value>true</value>
</property>
<property>
  <name>yarn.resourcemanager.scheduler.monitor.policies</name>
  <value>org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity.ProportionalCapacityPreemptionPolicy</value>
</property>

<!-- 관찰 전용 여부: true면 선점 및 kill 이벤트를 보내지 않음 -->
<property>
  <name>yarn.resourcemanager.monitor.capacity.preemption.observe_only</name>
  <value>false</value>
</property>

<!-- grace period: 자발적 반환 대기 시간 (ms) -->
<property>
  <name>yarn.resourcemanager.monitor.capacity.preemption.max_wait_before_kill</name>
  <value>15000</value>
</property>

큐 단위 Preemption 비활성화

특정 큐의 컨테이너를 다른 큐를 위한 선점에서 제외하려면 다음 설정을 사용할 수 있다. 큐 내부 선점 설정과 다른 원인의 컨테이너 종료까지 모두 막는 것은 아니다.

<property>
  <name>yarn.scheduler.capacity.root.critical-queue.disable_preemption</name>
  <value>true</value>
</property>

[!WARNING] Executor 종료 시 Spark는 Task를 재시도할 수 있지만 재시도 한도 등을 초과하면 실패할 수 있다. cluster 모드에서는 Driver가 AM 안에 있으므로 AM 종료와 애플리케이션 재시도 정책도 함께 확인해야 한다. observe_only=true는 선점 판단을 관찰하기 위한 모드이며 실제 자원 회수는 수행하지 않는다.

참고 문서Apache Hadoop 3.3.5 공식 문서 - Capacity Scheduler 설정과 선점

YARN UI로 스케줄러 문제 진단하기

잡이 이상하게 느리거나 ACCEPTED에서 멈추거나 갑자기 실패한다면 YARN ResourceManager UI가 첫 번째 진단 도구다.

접근 방법 (EMR)

EMR 콘솔 → 클러스터 선택 → Application user interfaces 탭 → ResourceManager 링크

또는 SSH 터널을 통해 직접 접근:

# EMR 마스터 노드에 SSH 포트 포워딩
ssh -i your-key.pem -N -L 8088:localhost:8088 hadoop@<master-dns>
# 브라우저에서 http://localhost:8088 접속

주요 확인 탭

Scheduler 탭 (/scheduler)

Capacity Scheduler의 전체 큐 상태를 한눈에 볼 수 있다.

항목의미
Used Capacity현재 사용 중인 리소스 비율
AM UsedAM 컨테이너가 사용 중인 리소스
AM Limitmaximum-am-resource-percent 기준 AM 한도
Pending리소스 대기 중인 컨테이너 수

[!TIP] AM Used가 AM Limit에 근접하거나 같다면 → AM 한도 부족 가능성을 Diagnostics에서 확인 Pending이 높고 Used Capacity가 낮다면 → 큐 설정과 요청 크기 및 노드별 가용 자원 확인

Applications 탭 (/cluster/apps)

  • State 필터: ACCEPTED 상태 잡이 많다면 AM 한도 또는 큐 용량 부족
  • Elapsed Time: 비정상적으로 오래 실행 중인 잡 탐지

Application 상세와 Spark UI

ResourceManager의 Application 상세 화면에서는 Diagnostics와 실행 시도 정보를 확인한다. /proxy/<app-id>/는 해당 애플리케이션 UI로 연결되는 경로이며 Spark UI와 ResourceManager 상세 화면의 표시 항목은 구분해서 읽는다.

  • Diagnostics: 잡이 pending인 이유와 Preemption 발생 여부 메시지 확인 가능
  • Containers: 각 컨테이너의 상태와 노드 위치 확인

마무리

Spark 애플리케이션이 대기할 때는 YARN UI의 진단 메시지와 실제 할당량을 먼저 확인하고 관련 한도를 좁혀 가야 한다. AM에 필요한 자원이 부족한 상황과 이미 실행 중인 애플리케이션이 추가 Executor를 기다리는 상황을 구분해 살펴본다.

이 글에서 다룬 주요 확인 항목은 다음과 같다.

설정확인 포인트
maximum-am-resource-percentAM 사용량과 현재 AM 한도 및 대기 사유 확인
minimum-user-limit-percent큐 내부의 사용자별 자원 배분 기준 확인
user-limit-factor한 사용자가 큐의 보장 용량을 넘어 사용할 수 있는 범위 확인
선점 설정자원 회수 조건과 컨테이너 종료의 영향을 함께 확인

설정값을 바꾸기 전에는 사용 중인 버전의 공식 문서와 실제 적용값을 확인해야 한다. 변경 후에는 같은 화면에서 AM 사용량과 대기 요청 및 큐별 사용량이 어떻게 달라졌는지 비교한다.


관련 글