AWS Batchでバッチ処理はバッチリ?!
こんにちは!エンジニアの小幡です。最近だいぶ暖かくなってきましたね。
外出自粛が続いているので、一人用のホットプレートを買ってしまいました。好きな焼肉やら炒め物を昼休みに気軽に作れるので自分的にはQOL爆上がりです。
さて、表題のバッチ処理については弊社柿木からの記事もありましたが、EC2インスタンス上のcronで管理していたバッチ処理を順次AWS Batchへ移行しています。
そこで、今回は私が業務を通して初めて触ったAWS Batchや合わせて利用している周辺サービスについての概要を皆さまに共有できればと思います!
AWS Batchとは
バッチ管理・実行ができるフルマネージドのサービスです。利用するためには以下の3点を最低限設定する必要があります。
・ジョブ定義
・コンピューティング環境
・ジョブキュー
ジョブ定義
ジョブ定義とはその名の通り実行するバッチ処理作業がどのようなものかを定義するものです。設定する項目は多くありますが、その中でも代表的なものは以下の通りです。
・利用するDockerイメージ(ECRに事前にpushしておく)
・実行コマンド
・利用リソース(vCPU / メモリ)
・環境変数
ちなみに、弊社ではバッチ処理を記述する言語はRubyかGoですが、自分が担当している施策ではRuby on Railsを使っているのでRakeタスクを定義したプロジェクトをDockerイメージ化することで、ジョブ定義に使うECR上のDockerイメージを作成しています。
コンピューティング環境
ジョブ実行するEC2インスタンスを指定します。
ジョブキュー
バッチジョブを流し込むためのキュー環境を設定します。その際、上記で定義したコンピューティング環境を関連づけすることで実行されるリソースを指定します。
プラスアルファでより柔軟なバッチ運用がしたい!
さて、AWS Batchで設定したバッチ処理について重要なポイントとして、「複数のバッチ処理を連携させたい!」「定期的に実行させたい!」という要望があると思います。
これらの要望はそれぞれStep Functions、CloudWatchイベントにより実現させることができます!
複数バッチ連携で便利なStep Functions
実行時の入力を変えた同一のバッチを3並列で、かつ、開始時間に時間差をつけて処理したい!など少し複雑な要求があったとしましょう。
Step Functionsではそういったことも簡単に実現できてしまいます。
処理の流れはステートマシンと呼ばれる物を以下のようにJSON形式で記述することにより定義します。(ここでは実行時の入力を環境変数 USER_REMAINDER で渡すようにしています)
{
"Comment": "parallel test",
"StartAt": "Parallel",
"States": {
"Parallel": {
"Type": "Parallel",
"Next": "Final State",
"Branches": [
{
"StartAt": "GenerateRegisterBatch_1",
"States": {
"GenerateRegisterBatch_1": {
"Type": "Task",
"Resource": "arn:aws:states:::batch:submitJob.sync",
"Parameters": {
"JobDefinition": "{YOUR_BATCH_JOB_ARN}",
"JobName": "parallel_test_job",
"JobQueue": "{YOUR_BATCH_JOB_QUEUE_ARN}",
"ContainerOverrides": {
"Environment": [
{
"Name": "USER_REMAINDER",
"Value": "0"
}
]
}
},
"End": true
}
}
},
{
"StartAt": "Wait 15min",
"States": {
"Wait 15min": {
"Type": "Wait",
"Seconds": 900,
"Next": "GenerateRegisterBatch_2"
},
"GenerateRegisterBatch_2": {
"Type": "Task",
"Resource": "arn:aws:states:::batch:submitJob.sync",
"Parameters": {
"JobDefinition": "{YOUR_BATCH_JOB_ARN}",
"JobName": "parallel_test_job",
"JobQueue": "{YOUR_BATCH_JOB_QUEUE_ARN}",
"ContainerOverrides": {
"Environment": [
{
"Name": "USER_REMAINDER",
"Value": "1"
}
]
}
},
"End": true
}
}
},
{
"StartAt": "Wait 30min",
"States": {
"Wait 30min": {
"Type": "Wait",
"Seconds": 1800,
"Next": "GenerateRegisterBatch_3"
},
"GenerateRegisterBatch_3": {
"Type": "Task",
"Resource": "arn:aws:states:::batch:submitJob.sync",
"Parameters": {
"JobDefinition": "{YOUR_BATCH_JOB_ARN}",
"JobName": "parallel_test_job",
"JobQueue": "{YOUR_BATCH_JOB_QUEUE_ARN}",
"ContainerOverrides": {
"Environment": [
{
"Name": "USER_REMAINDER",
"Value": "2"
}
]
}
},
"End": true
}
}
}
]
},
"Final State": {
"Type": "Pass",
"End": true
}
}
}
これをAWSコンソール上のStep Functionsのステートマシン定義に貼り付けて横の更新ボタンを押すと、自動的に処理の流れを表したグラフが生成されます。すごい!
ちなみに、実際にAWS Batchを設定してからこれを実行すると以下のようにグラフの色が変わってどこまで処理が進んでいるのかが一目瞭然でわかるようになっています。とてもすごい!
定期的に実行させるためのCloudWatchイベント
ここまでで、シンプルなバッチ処理、それらを連携させる仕組みをかなりざっとですがご紹介しました。
ただ、バッチ処理といって忘れてはいけないのが定期実行の仕組みです。
CloudWatchのイベントからスケジュールや実行するターゲットを設定したルールを設定することでcronと同じように定期実行させることができます。
実行するターゲットとしてはAWS Batchのジョブはもちろん、Step Functionsのステートマシンも指定することができるので、CloudWatchイベント + Step Functions + AWS Batch でだいぶ柔軟なバッチ運用をすることができると感じています。
ちょっと困ったところ
だいぶ高機能でありがたいと思っている反面少し使いにくいかなと思っている部分があります。
特にAWS Batchのコンソール画面でジョブ定義をコピーして新しいジョブを作成したい時にコピーボタンがないなど、コンソールの機能がもう少し充実してたらなと感じます。(ジョブ定義で環境変数が多い場合などはコンソール上で手動&目視でコピーするのがとても大変。。。)
ただ、AWS CLIが使えれば、以下のように比較的簡単にコピーできるため、もっとAWS CLIに習熟しろよ!という試練だと受け取って今は学習中です!
$ aws batch describe-job-definitions --job-definition-name {ジョブ定義名} --status ACTIVE > {任意のファイル名}.json
# ローカルに保存された{任意のファイル名}.jsonを適宜編集し保存
$ aws batch register-job-definition --cli-input-json file://{保存したファイル名}.json
最後に
かなり駆け足で自分が学んできたAWSのバッチ関連のサービスについてご紹介しましたが、もし何か皆様のバッチライフの役に立ったなら幸いです!
そしてバッチに限らずエンジニアリング&スペースマーケットに少しでも興味がある方は下記Watendlyからの応募をお待ちしております!
この記事が気に入ったらサポートをしてみませんか?