Amazon EMR의 Apache Spark 작업이 ‘Container killed on request’ 단계 실패와 함께 실패합니다.
Caused by: org.apache.spark.SparkException: Job aborted due to stage failure: Task 2 in stage 3.0 failed 4 times, most recent failure: Lost task 2.3 in stage 3.0 (TID 23, ip-xxx-xxx-xx-xxx.compute.internal, executor 4): ExecutorLostFailure (executor 4 exited caused by one of the running tasks) Reason: Container marked as failed: container_1516900607498_6585_01_000008 on host: ip-xxx-xxx-xx-xxx.compute.internal. Exit status: 137. Diagnostics: Container killed on request. Exit code is 137
간략한 설명
컨테이너(Spark 실행기)에 메모리가 부족하면 YARN이 자동으로 컨테이너를 종료합니다. 이는 "Container killed on request. Exit code is 137" 오류를 유발합니다. 이러한 오류는 좁은 변환과 넓은 변환 모두에서 서로 다른 작업 단계에 발생할 수 있습니다. YARN 컨테이너도 OS의 메모리가 부족할 때 OS oom_reaper에 의해 종료되어 ‘Container killed on request. Exit code is 137’ 오류를 유발합니다.
해결 방법
다음 방법 중 하나 이상을 사용하여 "Exit status: 137" 단계 실패를 해결합니다.
드라이버 또는 실행기 메모리를 늘림
spark.executor.memory 또는 spark.driver.memory 파라미터(어느 컨테이너가 오류를 유발했는지에 따라 다름)를 조정하여 컨테이너 메모리를 늘립니다.
실행 중인 클러스터에서 다음을 수행합니다.
마스터 노드에서 spark-defaults.conf를 수정합니다. 예:
sudo vim /etc/spark/conf/spark-defaults.conf
spark.executor.memory 10g
spark.driver.memory 10g
단일 작업에 대해 다음을 수행합니다.
spark-submit을 실행할 때 --executor-memory 또는 --driver-memory 옵션을 사용하여 메모리를 늘립니다. 예:
spark-submit --executor-memory 10g --driver-memory 10g ...
Spark 파티션 추가
컨테이너 메모리를 늘릴 수 없는 경우(예: 노드에 maximizeResourceAllocation을 사용하는 경우)에는 Spark 파티션의 수를 늘립니다. 이렇게 하면 단일 Spark 태스크에서 처리하는 데이터 양이 줄어들어 단일 실행기에서 사용하는 전체 메모리가 줄어듭니다. 다음 Scala 코드를 사용하여 Spark 파티션을 더 추가합니다.
val numPartitions = 500
val newDF = df.repartition(numPartitions)
셔플 파티션의 수를 늘림
넓은 변환(예: join 또는 groupBy) 중에 오류가 발생하는 경우, 셔플 파티션을 더 추가합니다. 기본값은 200입니다.
실행 중인 클러스터에서 다음을 수행합니다.
마스터 노드에서 spark-defaults.conf를 수정합니다. 예:
sudo vim /etc/spark/conf/spark-defaults.conf
spark.sql.shuffle.partitions 500
단일 작업에 대해 다음을 수행합니다.
spark-submit을 실행할 때 --conf spark.sql.shuffle.partitions 옵션을 사용하여 셔플 파티션을 더 추가합니다. 예:
spark-submit --conf spark.sql.shuffle.partitions=500 ...
실행기 코어 수를 줄임
실행기 코어 수를 줄이면 실행기가 동시에 처리하는 최대 태스크 수가 줄어듭니다. 이렇게 하면 컨테이너에서 사용하는 메모리 양이 줄어듭니다.
실행 중인 클러스터에서 다음을 수행합니다.
마스터 노드에서 spark-defaults.conf를 수정합니다. 예:
sudo vim /etc/spark/conf/spark-defaults.conf
spark.executor.cores 1
단일 작업에 대해 다음을 수행합니다.
spark-submit을 실행할 때 --executor-cores 옵션을 사용하여 실행기 코어 수를 줄입니다. 예:
spark-submit --executor-cores 1 ...
인스턴스 크기 증가
YARN 컨테이너도 OS의 메모리가 부족할 때 OS oom_reaper에 의해 종료될 수 있습니다. 이 오류가 oom_reaper로 인해 발생하면 RAM이 더 많은 큰 용량의 인스턴스를 사용하세요. YARN 컨테이너가 Amazon EC2의 RAM을 모두 사용하지 못하도록 yarn.nodemanager.resource.memory-mb를 낮출 수도 있습니다.
dmesg 명령 출력에 대한 Amazon EMR 인스턴스 로그를 검토하여 오류가 oom_reaper로 인한 것인지 확인할 수 있습니다. 먼저 종료된 YARN 컨테이너가 실행 중이었던 코어 또는 태스크 노드를 찾습니다. YARN 리소스 관리자 UI 또는 로그를 사용하여 이 정보를 찾을 수 있습니다. 그런 다음 컨테이너가 종료되기 전과 후에 이 노드의 Amazon EMR 인스턴스 상태 로그를 확인하여 프로세스가 중단된 원인을 확인합니다.
다음 예에서는 YARN container_165487060318_0001_01_000244에 해당하는 ID 36787의 프로세스가 커널(Linux의 OOM 킬러)에 의해 종료되었습니다.
# hows the kernel looking
dmesg | tail -n 25
[ 3910.032284] Out of memory: Kill process 36787 (java) score 96 or sacrifice child
[ 3910.043627] Killed process 36787 (java) total-vm:15864568kB, anon-rss:13876204kB, file-rss:0kB, shmem-rss:0kB
[ 3910.748373] oom_reaper: reaped process 36787 (java), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
관련 정보
Amazon EMR 기반의 Spark에서 "Container killed by YARN for exceeding memory limits" 오류를 해결하려면 어떻게 해야 합니까?
Amazon EMR에서 Spark 작업의 단계 실패 문제를 해결하려면 어떻게 해야 합니까?