AWS Glue の抽出、変換、ロード (ETL) ジョブが「Container killed by YARN for exceeding memory limits」(メモリ制限を超えたため、コンテナが YARN によって強制終了されました) というエラーで失敗します。
簡単な説明
このエラーの最も一般的な原因を以下に示します。
- メモリを大量に消費する操作 (大きなテーブルの結合や特定の列値の分布にスキューがあるデータセットの処理など) に起因する基盤の Spark クラスターのメモリしきい値超過
- 該当するエグゼキューターに割り当てられたメモリよりも多くを消費するデータの FAT パーティション
- 分割できない大きなファイルによって生じる大きなインメモリパーティション
解決方法
このエラーを解決するには、次の解決方法を選択してください。
| |
---|
AWS Glue バージョン 1.0 および 2.0 | |
スタンダード | spark.executor.memory: 5g spark.driver.memory: 5g spark.executor.cores: 4 |
G.1x | spark.executor.memory: 10g spark.driver.memory: 10g spark.executor.cores: 8 |
G.2x | spark.executor.memory: 20g spark.driver.memory: 20g spark.executor.cores: 16 |
AWS Glue バージョン 3.0 | |
スタンダード | spark.executor.memory: 5g spark.driver.memory: 5g spark.executor.cores: 4 |
G.1x | spark.executor.memory: 10g spark.driver.memory: 10g spark.executor.cores: 4 |
G.2x | spark.executor.memory: 20g spark.driver.memory: 20g spark.executor.cores: 8 |
- ワーカータイプをアップグレードしてもエラーが解決されない場合は、ジョブのエグゼキューターの数を増やしてください。各エグゼキューターには一定数のコアがあります。この数値は、エグゼキューターで処理できるパーティションの数を決定します。データ処理ユニット (DPU) の Spark 設定は、ワーカータイプに基づいて定義されます。
- 結合などのシャッフル操作の前にエグゼキューターを均等に使用できるように、データが適切に並列化されていることを確認してください。すべてのエグゼキューター間でデータを再分割できます。これを行うには、ETL ジョブの AWS Glue DynamicFrame に上のコマンドを含め、Spark DataFrame に下のコマンドを含めます。
dynamicFrame.repartition(totalNumberOfExecutorCores)
dataframe.repartition(totalNumberOfExecutorCores)
- ジョブブックマークを使用すると、新しく書き込まれたファイルのみを AWS Glue ジョブで処理できます。これで AWS Glue ジョブによって処理されるファイルの数が削減され、メモリの問題が軽減されます。ブックマークには、前の実行で処理されたファイルに関するメタデータが格納されます。その後の実行では、ジョブはタイムスタンプを比較し、これらのファイルを再度処理するかどうかを決定します。詳細については、「ジョブのブックマークを使用した処理済みデータの追跡」を参照してください。
- JDBC テーブルに接続すると、Spark はデフォルトで同時接続を 1 つだけ開きます。ドライバーは、1 つの Spark エグゼキューターでテーブル全体を一度にダウンロードしようとします。これには時間がかかり、エグゼキューターのメモリ不足エラーが発生することもあります。代わりに、JDBC テーブルの特定のプロパティを設定して、DynamicFrame を介して並列でデータを読み取るように AWS Glue に指示できます。詳細については、「JDBC テーブルからの並列読み取り」をご参照ください。Spark DataFrame を介して JDBC からの並列読み取りを行うこともできます。詳細については、「JDBC からの Spark DataFrame の並列読み取り」を参照し、partitionColumn、lowerBound、upperBound、numPartitions などのプロパティを確認してください。
- 特に Python/Scala コードと Spark の関数やメソッドを組み合わせる場合は、ETL ジョブでユーザー定義関数を使用しないでください。例えば、if/else ステートメントまたは for ループ内の空のデータフレームを検証するために Spark の df.count() を使用しないでください。代わりに、パフォーマンスが優れた関数 (df.schema() や df.rdd.isEmpty() など) を使用してください。
- 開発エンドポイントで AWS Glue ジョブをテストし、それに応じて ETL コードを最適化します。
- 上記の解決方法のいずれも機能しない場合は、入力データをチャンクまたはパーティションに分割します。次に、1 つの大きなジョブを実行する代わりに、複数の AWS Glue ETL ジョブを実行します。詳細については、「バインドされた実行によるワークロード・パーティショニング」をご参照ください。
関連情報
OOM 例外とジョブの異常のデバッグ
AWS GlueでApache Sparkジョブをスケーリングし、データをパーティション分割するためのベストプラクティス
AWS Glue でメモリ管理を最適化する