AWS Batchの使い所

この記事は、[ゆめみ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/yumemi)の10日目の記事です。

AWS Batchを調べたので、そのことを書いてみます。

## AWS Batch is 何


> バッチコンピューティングのための環境をフルマネージドで提供
・ AWS Batchがインスタンスの起動や停止をおこなうため、スケジューラや計算ノードなどの管理が不要
・ ジョブはDockerコンテナイメージを元をに作成し、自動でスケールするコンピューティング環境で実行する
・ コンピューティング環境ではインスタンスタイプやvCPU数、スポットインスタンス利用有無などを任意に指定可能
・ 100万vCPUクラスの大規模な計算にも対応

[https://www2.slideshare.net/AmazonWebServicesJapan/20190911-aws-black-belt-online-seminar-aws-batch](https://www2.slideshare.net/AmazonWebServicesJapan/20190911-aws-black-belt-online-seminar-aws-batch) の 25ページ目

とあります。具体的な構成を理解するにあたり、[過去のBlack Belt](https://aws.amazon.com/jp/blogs/news/webinar-bb-aws-batch-2019/)のQAが参考になります。

## AWS BatchとECS

[過去のBlack Belt](https://aws.amazon.com/jp/blogs/news/webinar-bb-aws-batch-2019/)のQAに下の記載があります。

> Q. AWS Batch と Amazon ECS、AWS Fargate の使い分けについて教えて下さい。
A. AWS Batch では内部的に Amazon ECSを使用しつつ、キューイングされた計算処理を順次実行していくようなバッチコンピューティング環境に特化しております。そのため、このようなバッチ処理であれば AWS Batch をご利用いただき、それ以外のインタラクティブな処理を含む汎用的なワークロードではECS及びECSの機能の一部であるFargateをご利用いただければと思います。

実際に AWS Batchのコンピューティング環境とジョブ定義を作ってみると、ECSにクラスターとジョブ定義が作成されることを確認できます。AWS Batchに対応するコンピューティング環境に対応する ECSのクラスターが作成され、AWS Batchのジョブ定義に対応するECSのタスク定義が作成されます。そのためかAWS Batchのコンピューティング環境を作るにはECSを理解していないと、パラメターの意味を理解できません。

AWS Batchのキューを作る時には実行したい「ジョブ定義」と実行環境の「コンピューティング環境」を指定します。そうすると、(ECSクラスターを構成するEC2が0台なら)ECSクラスターを構成するEC2が起動し、そこでECSタスクが実行されます。

ざっくりと 「キューをポーリングしてECSタスクを実行してくれるサービス」であると私は理解しました。

## 用途

逐次、投入されるキューを捌いていくバッチ処理が向いていると思います。例えば「ユーザがアップロードしたファイルがS3にあるので、チェックと加工を行いDBに投入する」といったものです。オンラインAPIで即時に結果を返すようなものは不適当だと思います。ファイルをアップロードした後はDBなどでスタースを管理して、終了を知るには、定期的な目視確認か、メールやslackなどの通知になります。(頑張れば作り込めるのですが・・・)

または、一度に大量のキューが投入されるので、全てのキューを速やかに処理するケースもあります。例えば、「Pushなどの配信を指定された時間から配信を開始して、可能な限り、短時間で配信を終わらせる」です。

## 近い構成との比較検討

### SQSのキューをポーリングして処理を実行する。キューの数に応じてオートスケールする

AWS Batchが登場する前は、SQSとEC2を組み合わせて自前で実現していました。

一番の違いはSQSをポーリングする必要がありません。プロセスを常に起動させキューをポーリングして実行する仕組みは意外と大変です。必要な時に呼び出してくれる仕組みはシステム運用ではとても楽ができますし、実装も楽になります。

次はオートスケールは向かないケースがあるからです。1日を通して継続的にキューが投入されることで、残りのキューは増減し、ゼロになる期間が短いケースではオートスケールで台数を調整できると思います。

オートスケールが不向きと考えているのは、一度に大量のキューが投入され、次にキューが投入されるまでの時間が長い場合です。こういうケースは大量に投入された全てのキューを速やかに処理することが求められます。
キューが投入された後にスケールアウトするのは容易なのですが、下の2つの要件を満たすスケールインのタイミング調整が困難です。

1. キューが空になるまではスケールインしたくない。
2. キューが空になったら速やかにスケールインしたい。

キューが減ってきてスケールインしてしまうと単位時間あたりに処理されるキューの数が減るので、キューが投入されてから、キューが空になるまでの処理時間が長くなります。

AWS Batchでは 「最大 vCPU」までスケールアウトして、使われていないvCPUがでるまではスケールインしません。


### AWS Lambda

Lambdaはサーバレスな実行環境なので、管理コストを減らせられます。最近、メモリーとvCPUの上限が引き上げられ、メモリーが10Gbyte、vCPUが6になりました。実行時間にも上限があり15分です。

手軽な処理には向いていてAWSのサービス間をつなげるのには便利ですが、大量のメモリーや、処理時間が長い場合には不向きです。


### AWS Glue

データファイルのチェック、加工だけなら AWS Glueが候補に挙がります。AWS Glueはベースが Apache Spark なので処理対象のデータ量と処理時間、コストの見積もりを適切に行う必要があります。

検索エンジンに検索ワードを「aws glue 料金」と入力すると「aws glue 料金 高い」がサジェストされます。
料金を調べると「最小請求期間は 10 分」という説明が目につくので、これが料金を高くする要因だと推測しています。AWS Glueはデータが少量の場合には不向きです。


## AWS Batch for AWS Fargate

今月に[発表されました](https://aws.amazon.com/jp/about-aws/whats-new/2020/12/severless-batch-scheduling-with-aws-batch-and-aws-fargate/)。

コンピューティグ環境の管理が楽になるのと、ECSのクラスターを構成するEC2の起動待ちが無いのはいいですね。
Fargate Spotも使えるのでお財布に優しいです。

## スケジューリング

バッチ処理には所定の時間になったら処理を開始するスケジューリング機能が必要です。いくつかの候補は下のものです。

1. AWS BatchというかECSタスクを使う
2. OSSならHinemosやRundeckなどのジョブスケジューラ、Jenkinsのスケジューリング機能からキューをAWS Batchにキューを投入する 
3. AWSとの連携を重視するなら Apache Airflowのマネージドサービス[「Amazon Managed Workflows for Apache Airflow」](https://aws.amazon.com/jp/managed-workflows-for-apache-airflow/)が最近、発表されました。まだ触っていないので、どんなものか、とても気になります。

## ジョブの連携

前処理と後処理など、AWS Batchのジョブを関連づけることがあります。

複雑でなければ、AWS Batchの「ジョブの依存関係」や「配列ジョブ」があります。複雑で状態遷移が必要であれば Step Functionとの組み合わせになります。

ジョブ間のデータの受け渡しは S3やDBなどを使う必要があります。