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

最終更新日: 2021 年 6 月 14 日

Amazon EMR 上の Spark での「Container killed by YARN for exceeding memory limits (メモリ制限を超えたために 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 インスタンスに、ワークロードに必要なメモリリソースがない可能性があります。より大きなメモリ最適化インスタンスタイプに切り替えると、エラーが解決する場合があります。インスタンスタイプを変更してもメモリ例外が発生する場合は、新しいインスタンスでトラブルシューティング方法を試してください。