AWS Glue ETL ジョブが「Container killed by YARN for exceeding memory limits」というエラーで失敗するのはなぜですか?

最終更新日: 2022 年 4 月 27 日

AWS Glue の抽出、変換、ロード (ETL) ジョブが「Container killed by YARN for exceeding memory limits」(メモリ制限を超えたため、コンテナが YARN によって強制終了されました) というエラーで失敗します。

簡単な説明

このエラーの最も一般的な原因を以下に示します。

  • メモリを大量に消費する操作 (大きなテーブルの結合や特定の列値の分布にスキューがあるデータセットの処理など) に起因する基盤の Spark クラスターのメモリしきい値超過
  • 該当するエグゼキューターに割り当てられたメモリよりも多くを消費するデータの FAT パーティション
  • 分割できない大きなファイルによって生じる大きなインメモリパーティション

解決方法

このエラーを解決するには、次の解決方法を選択してください。

  • G1.x のワーカータイプをより高いメモリ構成を持つ G2.x にアップグレードします。ワーカータイプの仕様の詳細については、「Spark ジョブのJob プロパティの定義」の「ワーカータイプ」セクションを参照してください。
  • AWS Glue 2.0 から 3.0 への移行の詳細については、「AWS Glue 2.0 から AWS Glue 3.0 への移行」を参照してください。
  • 次の表でワーカータイプの仕様に関する情報を参照することもできます。
AWS Glue バージョン 1.0 および 2.0  
スタンダード spark.executor.memory: 5g spark.driver.memory: 5g spark.executor.cores: 4
G1.x spark.executor.memory: 10g spark.driver.memory: 10g spark.executor.cores: 8
G2.x 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
G1.x spark.executor.memory: 10g spark.driver.memory: 10g spark.executor.cores: 4
G2.x 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 の並列読み取り」を参照し、partitionColumnlowerBoundupperBoundnumPartitions などのプロパティを確認してください。
  • 特に Python/Scala コードと Spark の関数やメソッドを組み合わせる場合は、ETL ジョブでユーザー定義関数を使用しないでください。例えば、if/else ステートメントまたは for ループ内の空のデータフレームを検証するために Spark の df.count() を使用しないでください。代わりに、パフォーマンスが優れた関数 (df.schema()df.rdd.isEmpty() など) を使用してください。
  • 開発エンドポイントで AWS Glue ジョブをテストし、それに応じて ETL コードを最適化します。
  • 上記の解決方法のいずれも機能しない場合は、入力データをチャンクまたはパーティションに分割します。次に、1 つの大きなジョブを実行する代わりに、複数の AWS Glue ETL ジョブを実行します。詳細については、「バインドされた実行によるワークロード・パーティショニング」をご参照ください。