Amazon EMR の Spark で「リクエストによりコンテナが強制終了しました。終了コードは 137 です」というエラーを解決するには、どうすればよいですか。

最終更新日: 2022 年 8 月 1 日

Amazon EMR の Apache Spark ジョブが、「リクエストによりコンテナが強制終了しました」というステージ障害で失敗します。

原因: org.apache.spark.SparkException: ステージ障害によりジョブが中断されました: ステージ 3.0 のタスク 2 が 4 回失敗しました。最新のエラー: ステージ 3.0 でタスク 2.3 が失われました (TID 23, ip-xxx-xxx-xx-xxx.compute.internal, executor 4): ExecutorLostFailure (実行中のタスクの 1 つが原因でエグゼキュータ 4 が終了しました) 理由: コンテナが失敗したとしてマークされた: container_1516900607498_6585_01_000008 on host: ip-xxx-xxx-xx-xxx.compute.internal.終了ステータス: 137。診断: リクエストによりコンテナが強制終了しました。終了コードは 137 です

簡単な説明

コンテナ (Spark エグゼキュター) のメモリが不足すると、YARN が自動的にコンテナを強制終了します。これにより「リクエストによりコンテナが強制終了しました。終了コードは 137 です」というエラーが起こります。このエラーは、さまざまなジョブステージで、ナロー変換とワイド変換どちらでも発生する可能性があります。YARN コンテナは、OS のメモリが不足しているときに OS oom_reaper によって強制終了されることもあり、「コンテナは要求に応じて強制終了されます。終了コードは 137 です」というエラーが起こります。

解決方法

次のいずれかの方法で「終了ステータス: 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 タスクで処理されるデータの量が減り、単一のエグゼキュターが使用するメモリ全体が少なくなります。Spark パーティションを追加するには、次の Scala コードを使用します。

val numPartitions = 500
val newDF = df.repartition(numPartitions)

シャッフルパーティションの数を増やす

ワイド変換中 (joingroupBy など) にエラーが発生した場合、シャッフルパーティションを追加します。デフォルト値は 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.nodemanager.resource.memory-mb を下げて、YARN コンテナが Amazon EC2 の RAM をすべて使い果たさないようにすることもできます。

エラーが oom_reaper によるものかどうかは、Amazon EMR インスタンスログで dmesg コマンドの出力を確認することで検出できます。まず、強制終了した 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