dbt Run Seems Finished, But Memory Still Rising: Uncovering Hidden OOM in AWS Fargate

まとめ

dbt-athenaの処理が完了してるはずなのに、使用メモリが上がり続けてOOMが発生

回避はできたけど詳しい原因はわからないまま

発生した事象

  • 環境
    • ECS(Fargate)
    • dbt-athenaでparquetからicebergに変換

dbt-athenaを使用して、179 modelを一回のdbt runで実行(parquetからicebergへ変換)
するとECS Fargateで下記のOOMエラーが発生
\"Reason\":\"OutOfMemoryError: Container killed due to memory usage

全てのmodel(179個)の処理は終了している様子なのに、
dbtが最後に出力する
07:48:17 Done. PASS=100 WARN=0 ERROR=2 SKIP=0 TOTAL=102 みたいなlogは出力されないままmemoryが上昇していきout of memoryが発生する

根本解決してないけどわかったこと

一部のmodelでpartitioned_byを設定していて、この設定を除去するとOOMは発生しなくなった

query処理時間が長くかかっているmodelを2つ特定した
そのmodelファイルではconfigでpartitioned_byを指定していた

{{ config(
        materialized=incremental(),
        unique_key=unique_keys,
        partitioned_by=[
            "created_at"
        ]
) }}

この設定を除去したところout of memoryは発生せず正常終了した
timestampカラムをそのままpartition設定するのは、こちらの使用方法のミス(値の数だけpartitionが設定され意味をなさないから)

まだ不明なこと

partitioned_byを指定していた modelはquery処理時間が長くかかっていたものの、最終的にはquery実行が成功している

dbt側での用途は不明だが、partitoined_byに指定したカラムをdistinctするsqlが2minほどかかっていた

select distinct created_at from "awsdatacatalog"."target_databasenamehoge"."tablenamehoge__tmp_not_partitioned" order by created_at

dbtはなぜqueryの実行完了を検知できなかったのか、何の処理が走ってmemory使用率が上昇したのかは不明

pollingのtimeout設定を追加できたらな…と思って調べたみたけど、dbt-athenaが「athenaのquery実行をどれくらい待つか」の設定値は存在してないみたい

dbt コミュニティのslackにも同じ事象で詰まっている記載は見つけられなかった

備考: 調査のためにやったこと

  • Cluster insightの有効化
    • –> Memory使用率を確認するため
  • dbt threadsを下げる
  • ECS TaskのMemory&CPU を上げる
  • Elementary関連のコメントアウト
  • Cloud Trailの確認
    • –> dbtからAWS側に何かリクエストしているかを確認したけど、特に何もしてなかった
  • dbt runに--no-write-jsonオプション追加
    • –> 成果物(run_results.jsonなど)の生成をOFFにする
  • Dockerfileに PYTHONUNBUFFERED=1を設定
    • –> Python プログラムの 標準出力(stdout)と標準エラー(stderr)をバッファリングせずに、即時に出力する設定
    • これも効果無し
  • awslogs mode=をblockingに変更
    • –> コンテナのlogを同期的にcloud watch logsに送られるようにする
    • 効果無し
  • ECSにloginするための設定
    • –> すんなり入れなかった^ 入ったところで何をするか決まっていなかったので諦めた
  • dbt-athenaからdbt-athena-communityに変更
    • –> 効果はなかったけど、dbt-athenaはメンテされていないのでdbt-athena-communityを使う設定にしておく
  • dbt/targetの容量を確認するためentrypoint.shを追加
    • –> dbtが成果物の生成を完了させた後、memoryが上昇していっていると判断できた
  • dbt-core, dbt-athena-communityをdown grade
  • dbtのselectors.yml(tag設定)を設定し、分割してdbt runをおこなった
    • –> query処理時間が長くかかっているmodelを2つ特定できた

最後に

まだまだ謎が多い…
思い出としてここに残しておきます