AWS Glue の抽出、変換、ロード (ETL) ジョブが失敗し、"Container killed by YARN for exceeding memory limits" エラーが発生します。
簡単な説明
このエラーの一般的な原因は以下のとおりです。
- 基盤となる Apache Spark クラスターのメモリーしきい値を超えるメモリーを大量に消費する操作。これらの操作には、大規模テーブルの結合や、分布に偏りがあるデータセットの処理などが当てはまります。
- それぞれのエグゼキューターに割り当てられている量よりも多くのメモリを消費するデータのファットパーティション。
- 分割できない大容量ファイルが原因で、メモリ内のパーティションが増大した場合。
解決策
このエラーを解決するには、次の 1 つまたは複数の手順を実行します。
ワークタイプをアップグレードする
G.2x 構成では利用可能なメモリが増えるため、ワーカータイプをアップグレードします。ワーカータイプを G.1x から次のワーカータイプにアップグレードできます。
- G.2x
- G.4x
- G.8x
- G.12
- G.16x
- R.1x
- R.2x
- R.4x
- R.8x
ワーカータイプの仕様の詳細については、「Spark ジョブのジョブプロパティの定義」および「AWS Glue バージョン」を参照してください。
ジョブのエグゼキューター数を増やす
ワーカータイプのアップグレード後もエラーが解消されない場合は、ジョブのエグゼキューター数を増やします。各エグゼキューターには、一定数のコアが存在します。この個数により、エグゼキューターが処理できるパーティションの数が決まります。ワーカータイプは、データ処理ユニット (DPU) の Spark 構成を定義します。
データを更新する
AWS Glue が結合などのシャッフル操作の前に、各エグゼキューターを均等に使用できるようにするには、データが並列であることを確認します。すべてのエグゼキューターにわたり、データを再分割するには、ETL ジョブに次のいずれかのコマンドを含めます。
DynamicFrame では、次のコマンドを含めます。
dynamicFrame.repartition(totalNumberOfExecutorCores)
DataFrame では、次のコマンドを含めます。
dataframe.repartition(totalNumberOfExecutorCores)
ジョブブックマークを使用する
ジョブブックマークを使用すると、AWS Glue ジョブは新しく書き込まれたファイルのみを処理します。この設定により、AWS Glue ジョブが処理するファイルの数が減り、メモリの問題が軽減されます。ブックマークには、前回の実行で処理されたファイルのメタデータが保存されます。後続の実行において、ジョブはタイムスタンプの比較を行い、これらのファイルを再度処理するかどうかを判断します。詳細については、「ジョブのブックマークを使用した処理済みデータの追跡」を参照してください。
DynamicFrame を使用してデータを並列に読み取る
JDBC テーブルへの接続時、Spark はデフォルトでは、単一の同時接続のみを開きます。ドライバーは、単一の Spark エグゼキューターにより、テーブル全体の一括ダウンロードを試行します。このダウンロードには時間がかかり、エグゼキューターでメモリ不足 (OOM) エラーを引き起こす可能性があります。代わりに、JDBC テーブルの特定のプロパティ構成において、AWS Glue が DynamicFrame を使用し、データを並列で読み取るよう指示します。または、Spark DataFrame を使用しても、JDBC からの並列読み取りを行うことができます。詳細については、Spark のウェブサイトで「JDBC to other databases (他のデータベースに対する JDBC)」を参照してください。
ETL ジョブで高パフォーマンス関数を使用する
ETL ジョブでは、特に Python または Scala コードを Spark の関数やメソッドと組み合わせる場合は、ユーザー定義関数の使用を避けてください。たとえば、if/else ステートメントや for ループにおいて、空の DataFrames を検証する際は、Spark の df.count() を用いないようにします。代わりに、df.schema()、df.rdd.isEmpty() などの、パフォーマンスに優れた関数を使用してください。
AWS Glue ジョブのテストと最適化
AWS Glue ジョブを本番環境で実行する前に、インタラクティブセッションで AWS Glue をテストし、ETL コードを最適化します。
上記の解決方法がいずれも機能しない場合は、入力データをチャンクまたはパーティションに分割します。次に、単一の大規模ジョブを実行するのではなく、複数の AWS Glue ETL ジョブを実行するようにします。詳細については、「実行に上限を設定してワークロードをパーティション化する」を参照してください。
関連情報
OOM 例外とジョブの異常のデバッグ
Best practices to scale Apache Spark jobs and partition data with AWS Glue (AWS Glue を使用して Spark ジョブをスケーリングし、データを分割する際のベストプラクティス)
Optimize memory management in AWS Glue (AWS Glue でのメモリ管理を最適化する)