Amazon EMR の Spark で発生する「Container killed by YARN for exceeding memory limits」というエラーを解決したいです。
簡単な説明
次のいずれかの手順で、このエラーを解決します。
- メモリオーバーヘッドを増やします。
- エグゼキューターコアの数を減らします。
- パーティションの数を増やします。
- ドライバーおよびエグゼキュータのメモリを増やします。
解決策
このエラーの根本原因と適切な解決策は、ワークロードによって異なります。このエラーを解決するには、以下の各方法を次の順序で試す必要がある場合があります。このシーケンスの次の方法に進む前に、前のセクションで spark-defaults.conf に加えた変更をすべて元に戻してください。
メモリオーバーヘッドを増やす
メモリオーバーヘッドは、各エグゼキューターに割り当てられたオフヒープメモリの量です。デフォルトでは、メモリーオーバーヘッドはエグゼキューターメモリーの 10% または 384 のうち、高い方に設定されます。メモリオーバーヘッドは、Java NIO ダイレクトバッファ、スレッドスタック、共有ネイティブライブラリ、またはメモリマップファイルに使用されます。
メモリのオーバーヘッドを段階的に、最大 25% まで増やすことを検討してください。ドライバーまたはエグゼキューターのメモリとメモリオーバーヘッドの合計は、使用しているインスタンスタイプの yarn.nodemanager.resource.memory-mb より小さい必要があります。
spark.driver/executor.memory + spark.driver/executor.memoryOverhead < yarn.nodemanager.resource.memory-mb
ドライバーコンテナまたはエグゼキューターコンテナでエラーが発生した場合は、そのコンテナのみでメモリオーバーヘッドを増やすことを検討してください。クラスターの実行中、新しいクラスターの起動時、またはジョブの送信時にメモリオーバーヘッドを増やすことができます。
実行中のクラスター:
マスターノードの spark-defaults.conf を変更します。
例:
sudo vim /etc/spark/conf/spark-defaults.conf
spark.driver.memoryOverhead 512
spark.executor.memoryOverhead 512
新しいクラスター:
クラスターの起動時に、次のような設定オブジェクトを追加します。
[
{
"Classification": "spark-defaults",
"Properties": {
"spark.driver.memoryOverhead": "512",
"spark.executor.memoryOverhead": "512"
}
}
]
単一のジョブ用:
--conf オプションを使用すると、spark-submit の実行時にメモリのオーバーヘッドを増やすことができます。
例:
spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode cluster --conf spark.driver.memoryOverhead=512 --conf spark.executor.memoryOverhead=512 /usr/lib/spark/examples/jars/spark-examples.jar 100
メモリーのオーバーヘッドを増やしても問題が解決しない場合は、エグゼキューターコアの数を減らしてください。
エグゼキューターコアの数を減らす
エグゼキューターが実行できるタスクの最大数が減るため、必要なメモリ量が削減されます。このエラーが発生したドライバーコンテナやその他のエグゼキューターコンテナに応じて、ドライバーまたはエグゼキューターのコアを減らすことを検討してください。
実行中のクラスター:
マスターノードの spark-defaults.conf を変更します。
例:
sudo vim /etc/spark/conf/spark-defaults.conf
spark.driver.cores 3
spark.executor.cores 3
新しいクラスター:
クラスターの起動時に、次のような設定オブジェクトを追加します。
[
{
"Classification": "spark-defaults",
"Properties": {"spark.driver.cores" : "3",
"spark.executor.cores": "3"
}
}
]
単一のジョブ用:
--executor-cores オプションを使用すると、spark-submit の実行時にエグゼキューターコアの数を減らすことができます。
例:
spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode cluster --executor-cores 3 --driver-cores 3 /usr/lib/spark/examples/jars/spark-examples.jar 100
エラーメッセージが解消されない場合は、パーティションの数を増やしてください。
パーティションの数を増やす
パーティションの数を増やすには、未加工の Resilient Distributed データセットで spark.default.parallelism の値を増やすか、.repartition() 操作を実行します。パーティションの数を増やすと、パーティションごとに必要なメモリ量が削減されます。Spark は、効果的に速度を最大化するためにクラスタ RAM を多用しています。したがって Ganglia でメモリ使用量を監視し、クラスター設定とパーティショニング戦略がデータ需要の増加に対応できることを確認する必要があります。「Container killed by YARN for exceeding memory limits」というエラーメッセージが解消されない場合は、ドライバーとエグゼキューターのメモリを増やしてください。
ドライバーまたはエグゼキューターのメモリを増やす
このエラーがドライバーコンテナまたはエグゼキューターコンテナで発生する場合は、ドライバーまたはエグゼキューターのメモリを増やすことを検討してください (両方では増やさないでください)。ドライバーまたはエグゼキューターの合計メモリと、ドライバーまたはエグゼキューターのメモリオーバーヘッドを合計した値が、常に使用している EC2 インスタンスタイプの yarn.nodemanager.resource.memory-mb 値よりも小さいことを確認してください。
spark.driver/executor.memory + spark.driver/executor.memoryOverhead < yarn.nodemanager.resource.memory-mb
実行中のクラスター:
マスターノードの spark-defaults.conf を変更します。
例:
sudo vim /etc/spark/conf/spark-defaults.conf
spark.executor.memory 1g
spark.driver.memory 1g
新しいクラスター:
クラスターの起動時に、次のような設定オブジェクトを追加します。
[
{
"Classification": "spark-defaults",
"Properties": {
"spark.executor.memory": "1g",
"spark.driver.memory":"1g",
}
}
]
単一のジョブ用:
spark-submit を実行する際、--executor-memory および --driver-memory オプションを使用してメモリを増やします。
例:
spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode cluster --executor-memory 1g --driver-memory 1g /usr/lib/spark/examples/jars/spark-examples.jar 100
その他の解決策
エラーメッセージが解消されない場合は、次のことを試してください。
- ベンチマーク サンプルデータセットに対してアプリケーションを実行することをおすすめします。この方法では、メモリの問題につながる可能性のある速度低下や不均等なパーティションを特定しやすくなります。
- データのフィルター: 処理するデータ量は最小限であることを確認してください。データをフィルターしなかったり、アプリケーションの実行の後半でフィルター処理を行ったりした場合、過剰なデータが原因でアプリケーションの速度が低下する可能性があります。結果的に、メモリ例外が発生する可能性が高くなります。
- データセットのサイズ: 必要最小限のデータを処理することをおすすめします。データを分割し、必要なデータのみが取り込まれるようにします。
- パーティショニング戦略: 別のパーティショニング戦略の使用を検討してください。たとえば、代替キーでパーティション分割を行うと、大容量のパーティションや不均等なパーティションを避けることができます。
- EC2 インスタンスタイプ: EC2 インスタンスには、ワークロードに必要なメモリリソースがない可能性があります。大容量のメモリ最適化インスタンスタイプに切り替えると、エラーが解決する場合があります。インスタンスタイプを変更してもメモリ例外が発生する場合は、新しいインスタンスでトラブルシューティング方法を試してください。
関連情報
Spark の構成
Amazon EMR の Spark で「java.lang.ClassNotFoundException」が発生する場合の解決方法を教えてください