Amazon EMR の Apache Spark ジョブが失敗し、"Container killed on request.Exit code is 137" というエラーが発生します。
簡単な説明
コンテナのメモリが不足すると、YARN は自動的にコンテナを停止し、次のエラーメッセージが表示される場合があります。
"Container killed on request" stage failure: 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-###-###-##-###.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-###-###-##-###.compute.internal.Exit status: 137.Diagnostics: Container killed on request.Exit code is 137"
解決策
ドライバーまたはコンテナのメモリを増やす
実行中のクラスターまたはシングルジョブのコンテナメモリを増やすには、まずクラスターのプライマリノードを接続します。次に、spark-defaults.conf Spark 設定ファイルの spark.executor.memory または spark.driver.memory パラメーターを変更します。
実行中のクラスター
spark-defaults.conf を開くには、以下のコマンドを実行します。
sudo vim /etc/spark/conf/spark-defaults.conf
コンテナメモリを増やすには、spark-defaults.conf の spark.executor.memory パラメータまたは spark.driver.memory パラメータを追加または変更します。
spark.executor.memory 10g
spark.driver.memory 10g
注: 10g は、クラスターで利用可能なリソースとワークロード要件に適した値に置き換えてください。
シングルジョブ
メモリを増やすには、次の spark-submit コマンドを実行するときに**--executor-memory** または --driver-memory オプションを使用してください。
spark-submit
--executor-memory 10g
--driver-memory 10g
...
注: 10g は、クラスターで利用可能なリソースとワークロード要件に適した値に置き換えてください。
スパーク設定の分類で maximizeResourceAllocation を true に設定することもできます。
Spark パーティションをさらに追加する
コンテナのメモリを増やすことができない場合は、Spark パーティションの数を増やして、処理されるデータ量と使用されるメモリ量を減らします。
Spark パーティションをさらに追加するには、まずクラスターのプライマリノードに接続し、Spark シェルで次のコマンドを実行します。
val numPartitions = 500
val newDF = df.repartition(numPartitions)
注: 500 は、データサイズに合ったパーティションの数に置き換えてください。
シャッフルパーティションの数を増やす
join や groupBy などの広範囲にわたる変換中に問題が発生した場合は、クラスターのプライマリノードに接続し、シャッフルパーティションをさらに追加します。デフォルト値は 200 です。
実行中のクラスター
spark-defaults.conf を開くには、以下のコマンドを実行します。
sudo vim /etc/spark/conf/spark-defaults.conf
シャッフルパーティションを設定ファイルに追加するには、次のコマンドを実行します。
spark.sql.shuffle.partitions 500
注: 500 は、データサイズに合ったパーティションの数に置き換えてください。
シングルジョブ
シャッフル・パーティションを追加するには、spark-submit を実行するときに --conf spark.sql.shuffle.partitions オプションを使用してください。
spark-submit
--conf
spark.sql.shuffle.partitions=500
...
注: 500 は、データサイズに合ったパーティションの数に置き換えてください。
エグゼキューターコアの数を減らす
エグゼキューターコアの数を減らすと、エグゼキューターが同時に処理するタスクの最大数も減ります。これにより、コンテナによるメモリ使用量が減ります。エグゼキューターコアの数を減らすには、まずクラスターのプライマリノードに接続してから、エグゼキューターコアのパラメータを変更します。
実行中のクラスター
プライマリノードで spark-defaults.conf ファイルを開きます。
sudo vim /etc/spark/conf/spark-defaults.conf
エグゼキューターコアの数を減らすには、spark.executor.cores パラメータを変更します。
spark.executor.cores 1
注: 1 は必要なエグゼキューターコアの最小数に置き換えてください。
シングルジョブ
エグゼキューターコアの数を減らすには、spark-submit の実行時に --executor-cores オプションを使用してください。
spark-submit
--executor-cores 1
...
インスタンスサイズを増やす
オペレーティングシステム (OS) のメモリが不足すると、OS oom_reaper が YARN コンテナを停止する場合もあります。oom_reaper が原因でエラーが発生した場合は、RAM の容量が多い、より大きな Amazon Elastic Compute Cloud (Amazon EC2) インスタンスを使用してください。YARN コンテナがすべての RAM を使用しないようにするには、yarn.nodemanager.resource.memory-mb を減らしてください。
oom_reaper がエラーの原因となったかどうかを判断するには、Amazon EMR インスタンスのログで dmesg コマンドの出力を確認してください。まず、YARN Resource Manager UI またはログを使用して、停止した YARN コンテナが実行されたコアノードまたはタスクノードを見つけます。次に、コンテナが停止する前と停止した後に、ノードの Amazon EMR インスタンスの状態ログを確認します。
次の例では、カーネルは YARN container_165487060318_0001_01_000244 に対応する ID 36787 のプロセスを停止します。
# hows the kernel lookingdmesg | 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
ディスク使用率とノードの劣化を確認する
前述のトラブルシューティングオプションで問題が解決しない場合は、インスタンスの状態ログの df -h フラグを使用してディスク使用率とノードの劣化を確認します。また、Amazon Health Dashboard でノードの状態も確認してください。
関連情報
Amazon EMR の Spark で発生する「Container killed by YARN for exceeding memory limits」というエラーを解決する方法を教えてください
Amazon EMR の Spark ジョブにおけるステージエラーの問題を解決する方法を教えてください