🐆

AWS Glue Python Shellの長時間バッチ実行環境としての可能性を探る

に公開

はじめに

AWS Community Builderのぺんぎん(@jitepengin)です。

ここ数回の記事でAWS Glue Python Shellに触れてきました。
実運用で「月に1回、長時間動かしたい重めのバッチ」をどう実行するか悩むことはありませんか?
例えば週次処理、月次集計やバックフィル、外部システム連携など実行時間が数十時間に及ぶバッチでは、様々な設計判断が求められます。

そういった長時間処理でよくある構成がEC2を建てて、そこでバッチを実行するというものだと思います。

比較的簡単に実現できるのですが、サーバ管理、起動・停止の運用、キャパシティ不足、Spot中断の考慮など、処理そのもの以外の考慮事項が多くなってしまうことがあります。

一方でAWS Glue Python Shellは以下のような特徴があり、使いどころ次第では非常に便利です。

  • サーバレスでインフラ管理が不要
  • デフォルト48時間、最大168時間までジョブを実行可能
  • 実行した分だけの従量課金

今回は、Glue Python Shellを48時間動かす実験を通して、本当に安定して長時間動くのか、EC2と比べた場合のコスト・運用面の違いを整理し、長時間バッチ実行基盤としての現実的な選択肢になり得るかを考えてみたいと思います。


AWS Glue Python Shellの前提整理

これまでの記事にも記載していますが、改めてGlue Python Shellの主な特徴を整理します。

  • ジョブタイプ:Python Shell
  • 最大実行時間:デフォルト48時間、最大168時間
  • リソース指定:DPU(Data Processing Unit)単位、1/16DPU,1DPUから指定可能
  • 課金:DPU × 実行時間課金
  • インスタンス管理:不要(AWS管理)

Sparkを使わないため、以下のような用途と相性が良いと思います。

  • 比較的軽量なETL
  • API連携や外部I/O中心の処理

軽量ETLの文脈でのLambdaとの比較は以下の記事でまとめているので、参考にどうぞ!

https://zenn.dev/penginpenguin/articles/fe2c3999a05013


本当に48時間動くのか?検証してみた

仕様として48時間実行できることは理解していますが、本当に時間通り動くのか?途中で止まらないのか?というのは気になるところです。
そこで今回は、1時間ごとにログを出力し続けるシンプルなジョブを用意して、実際に48時間動かしてみました。

なお今回は48時間で検証しましたが、Glue Python Shellは設定次第で最大168時間(約7日)まで実行可能です。
そのため、週次・月次などの長時間バッチについても、同様なアプローチが取れるかという観点で読んでいただければと思います。

サンプルコード

import time
import datetime

def process_data():
    time.sleep(5)  # ダミー処理

def main():
    start_time = datetime.datetime.now()
    max_hours = 48
    max_seconds = max_hours * 3600

    print(f"[INFO] Job started at {start_time}", flush=True)

    next_log_seconds = 3600  # 次のログは1時間後

    while True:
        process_data()

        elapsed = (datetime.datetime.now() - start_time).total_seconds()

        if elapsed >= next_log_seconds:
            elapsed_hours = int(elapsed // 3600)
            print(f"[INFO] Elapsed time: {elapsed_hours} hours", flush=True)
            next_log_seconds += 3600

        if elapsed >= max_seconds:
            break

    print(
        f"[INFO] Job completed at {datetime.datetime.now()} "
        f"(total: {elapsed/3600:.2f} hours)",
        flush=True
    )

if __name__ == "__main__":
    main()

確認結果

CloudWatch

CloudWatch Logsには以下のようなログが継続的に出力されました。

[INFO] Job started at 2026-01-14 09:01:45.644511
[INFO] Elapsed time: 1 hours
[INFO] Elapsed time: 2 hours
[INFO] Elapsed time: 3 hours
[INFO] Elapsed time: 4 hours
[INFO] Elapsed time: 5 hours
[INFO] Elapsed time: 6 hours
[INFO] Elapsed time: 7 hours
[INFO] Elapsed time: 8 hours
[INFO] Elapsed time: 9 hours
[INFO] Elapsed time: 10 hours
[INFO] Elapsed time: 11 hours
[INFO] Elapsed time: 12 hours
[INFO] Elapsed time: 13 hours
[INFO] Elapsed time: 14 hours
[INFO] Elapsed time: 15 hours
[INFO] Elapsed time: 16 hours
[INFO] Elapsed time: 17 hours
[INFO] Elapsed time: 18 hours
[INFO] Elapsed time: 19 hours
[INFO] Elapsed time: 20 hours
[INFO] Elapsed time: 21 hours
[INFO] Elapsed time: 22 hours
[INFO] Elapsed time: 23 hours
[INFO] Elapsed time: 24 hours
[INFO] Elapsed time: 25 hours
[INFO] Elapsed time: 26 hours
[INFO] Elapsed time: 27 hours
[INFO] Elapsed time: 28 hours
[INFO] Elapsed time: 29 hours
[INFO] Elapsed time: 30 hours
[INFO] Elapsed time: 31 hours
[INFO] Elapsed time: 32 hours
[INFO] Elapsed time: 33 hours
[INFO] Elapsed time: 34 hours
[INFO] Elapsed time: 35 hours
[INFO] Elapsed time: 36 hours
[INFO] Elapsed time: 37 hours
[INFO] Elapsed time: 38 hours
[INFO] Elapsed time: 39 hours
[INFO] Elapsed time: 40 hours
[INFO] Elapsed time: 41 hours
[INFO] Elapsed time: 42 hours
[INFO] Elapsed time: 43 hours
[INFO] Elapsed time: 44 hours
[INFO] Elapsed time: 45 hours
[INFO] Elapsed time: 46 hours
[INFO] Elapsed time: 47 hours
[INFO] Elapsed time: 48 hours
[INFO] Job completed at 2026-01-16 09:01:49.059613 (total: 48.00 hours)

およそ48時間動作していることがログからも確認できました。

Glue Job run monitoring


GlueのJob Run monitoring 上でも、48時間実行されていることを確認できます。
Run StatusはTimeoutとなっていますが、これは最大実行時間(48時間)に到達したためで、想定通りの挙動です。

今回は1DPU×48時間のジョブ実行となり、DPU hoursも想定通り48となっています。
また、48時間実行での料金は、$21.12となりました。

実行してみた所感

  • ジョブ開始から終了まで人の介入は不要
  • 中断・タイムアウトなし
  • ログはCloudWatchだけで完結

当たり前と言えばそうですが、この結果からGlue Python Shellは仕様通り長時間安定稼働するということを実際のログとメトリクスで確認できた形になります。

ちなみにCost explorer上では48時間の処理が完了するまで、コストを確認することができませんでした。
当たり前と言えばそうですが、意図せず長時間実行してしまうと料金が跳ね上がってしまうので注意が必要です。
つまり、気付くための仕組みも考える必要があります。


EC2(m6i.xlarge)との比較

次に、同程度のスペック感としてEC2(m6i.xlarge)で実行するケースと比較してみます。

Glue Python Shell(1DPU)

  • vCPU:4
  • Memory (GiB):16

m6i.xlarge

  • vCPU:4
  • Memory (GiB):16

コスト観点(48時間実行)

前提:

  • 実行頻度:月1回と仮定
  • 実行時間:48時間
観点 Glue Python Shell EC2 m6i.xlarge
実行コスト 実行時間分のみ課金 起動時間分課金
未使用時コスト なし 停止すればなし(アタッチしているEBSのコストやElastic IPが発生)
事前準備 不要 AMI/起動設定が必要
実行基盤 想定単価 48 時間コスト
EC2 Spot (m6i.xlarge) $0.0828/時間 $3.97
EC2 On-Demand (m6i.xlarge) $0.248/時間 $11.90
Glue Python Shell (1 DPU) $0.44/時間 $21.1

単純な実行コストで考えるとEC2の方が安く抑えることが可能です。
ただし、EC2の場合、Elastic IPの有無、EBSのサイズ、バッチ以外の時間帯での起動有無、OSパッチやメンテナンスといった要素が積み重なり、実質的な運用コストはさらにかかってしまうと考えてください。

運用負荷観点

EC2はコストを下げられる一方で、考慮事項や運用設計が確実に増えることに注意が必要です。
なお「起動失敗有無」は、ユーザが考慮・設計上対処する必要があるかどうかという観点で記載しています。
こちらは後程解説します。

観点 EC2(特に Spot) Glue Python Shell
起動・停止 自前制御 マネージド
起動失敗有無 まれにある ほぼなし
中断対応 必要 不要
OS管理 必要 不要
長時間実行 設計依存 168時間まで
事前準備 AMI/起動設定が必要 不要

EC2での実行時の注意点

Spotインスタンスはもちろんですが、オンデマンドインスタンスでも起動できないケースは存在します。
代表的なものとしては以下のようなものがあります。

  • InsufficientInstanceCapacity
    AWS側に十分なオンデマンドキャパシティがない場合に発生。停止状態からの再起動でも起こり得ます。

  • InstanceLimitExceeded
    リージョンで起動できるインスタンス数の制限に達した場合に発生。サービスクォータの引き上げで追加可能。

  • UnauthorizedOperation
    必要なIAM権限がない場合に発生。

  • The requested configuration is currently not supported
    特定のAZ/インスタンスタイプやAMIの組み合わせがサポートされていない場合に発生。

発生確率が低いものもありますが、オンデマンドインスタンスでも起動できないリスクはあるという点は押さえておく必要があります。
これは、普段は停止しておいて、たまにしか動かさない長時間バッチにとっては、運用上無視できない不確実性になります。

そこで、起動確実性を担保する方法として、オンデマンドキャパシティ予約があります。

オンデマンドキャパシティ予約とは

特定のAZでインスタンスのキャパシティを事前に確保する手段です。
つまり、確実に起動できるように事前予約しておくというものです。

メリットとしては、起動失敗のリスクを低減させることができますが、注意点としてインスタンスが停止中でも予約分のオンデマンド料金は発生するというものがあります。

そのため、低頻度バッチに対して常時コストを支払う設計が妥当かどうかが、キャパシティ予約を使うかの判断ポイントになります。


AWS Glue Python Shellを使う場合の割り切り

AWS Glue Python Shellにも当然制約はあります。

  • 最大実行時間(デフォルト48時間、最大168時間)
  • DPUベースの設定のためCPU/メモリを細かく指定できない
  • OSレベルのカスタマイズは不可

そのため、

  • 常時起動が必要
  • 168時間を超える可能性がある
  • OS制御が必須

といった場合は、EC2の方が適しています。
つまり、ある程度の制約を理解したうえで割り切って使う場合には非常に便利なサービスとなります。


まとめ

今回の記事では、AWS Glue Python Shellを実際に48時間動かす検証を行い、EC2と比較しながら長時間バッチ実行基盤としての適性を整理しました。
Glue Python ShellとEC2の比較は、単純なコスト比較だけでは判断できず、運用コストや連携するサービス等様々な観点で比較が必要です。

Glue Python Shellは低頻度、長時間実行、運用コスト最小化という要件が求められる場合に長時間バッチ実行基盤として採用する選択は現実的な選択肢となります。
安定して最後まで動くことを最優先したいという要求に対して、Glue Python Shellは非常に相性が良いと感じました。

一方で、高頻度、長時間実行、OSレベルで自由度が必要ということであればEC2を採用するのが良いと思います。
その際は前述したようにElastic IPの有無、EBSのサイズ、キャパシティ予約の要否をしっかりと検討したうえで判断いただくのが良いと思います。

長時間バッチの基盤選定では、「安さ」だけでなく、どこまで不確実性や運用負荷を許容できるか を踏まえて判断することが重要です。
そういった中で、Glue Python Shellは、「安定して最後まで動くこと」を最優先したいバッチに対して、現実的で、割り切りやすい選択肢になると思います。

今回の記事が、長時間バッチ実行を検討している方の参考になれば幸いです。

Discussion