Amazon EMR の Spark で「メモリ制限を超えたために YARN によってコンテナが強制終了されました」というエラーを解決するにはどうすればよいですか?

最終更新日: 2019 年 4 月 9 日

Amazon EMR の Spark で「メモリ制限を超えたために YARN によってコンテナが強制終了されました」というエラーを解決するにはどうすればよいですか?

簡単な説明

このエラーを解決するには、次のいずれかの方法を使用します。

  • メモリオーバーヘッドを増やす
  • エグゼキューターコアの数を減らす
  • パーティション数を増やす
  • ドライバーとエグゼキューターのメモリを増やす

解決方法

このエラーの根本的な原因と適切な解決策は、ワークロードによって異なります。エラーが解決されるまで、次の順序で、以下の各方法を試す必要があります。別の方法に進む前に、前の方法の操作中に spark-defaults.conf に加えた変更を元に戻してください。

メモリオーバーヘッドを増やす

メモリオーバーヘッドは、各エグゼキューターに割り当てられたオフヒープメモリの量です。デフォルトでは、メモリオーバーヘッドはエグゼキューターメモリの 10% か 384 のどちらか大きい方に設定されています。メモリオーバーヘッドは、Java NIO ダイレクトバッファー、スレッドスタック、共有ネイティブライブラリ、またはメモリーマップファイルに使用されます。

メモリオーバーヘッドを最大 25% まで徐々に増やすことを検討してください。ドライバーまたはエグゼキューターのメモリとドライバーまたはエグゼキューターのメモリオーバーヘッドの合計が、Amazon Elastic Compute Cloud (Amazon 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.driver.memoryOverhead 512
spark.executor.memoryOverhead 512

新しいクラスターでは:

クラスターを起動するときに、次のような設定オブジェクトを追加します。

[
  {
    "Classification": "spark-defaults",
    "Properties": {
      "spark.driver.memoryOverhead": "512",
      "spark.executor.memoryOverhead": "512"
    }
  }
]

単一のジョブでは:

spark-submit を実行するときにメモリオーバーヘッドを増やすには、--conf オプションを使用します。例:

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"
    }
  }
]

単一のジョブでは:

spark-submit を実行するときにエグゼキューターコアの数を減らすには、--executor-cores オプションを使用します。例:

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 Datasets の spark.default.parallelism の値を増やすか、または.repartition() 操作を実行します。パーティション数を増やすと、パーティションごとに必要なメモリ量が減ります。Spark は速度を最大化するための効果的な方法としてクラスター RAM を頻繁に使用するので、Ganglia でメモリ使用量を監視し、クラスター設定とパーティション分割戦略が増大するデータのニーズを満たしていることを確認することが重要です。それでも「メモリ制限を超えたために YARN によってコンテナが強制終了されました」というエラーメッセージが表示される場合は、ドライバーとエグゼキューターのメモリを増やしてください。

ドライバーとエグゼキューターのメモリを増やす

エラーがドライバーコンテナまたはエグゼキューターコンテナのいずれかで発生した場合は、ドライバーとエグゼキューターの両方ではなく、ドライバーまたはエグゼキューターのどちらかでメモリを増やしてください。ドライバーまたはエグゼキューターメモリとドライバーまたはエグゼキューターメモリのオーバーヘッドの合計が常に、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 インスタンスに、ワークロードに必要なメモリリソースがない可能性があります。より大きなメモリ最適化インスタンスタイプに切り替えると、エラーが解決する場合があります。インスタンスタイプを変更してもメモリの例外が発生する場合は、新しいインスタンスでこの記事の前半で説明した方法を試してみてください。