API Gateway + LambdaでAWS BatchのJobを実行する
こんにちは、菊池です。
API GatewayとLambdaで構成するAPIから、AWS Batchのジョブを実行する環境を作成してみました。Lambdaには向いていない長時間の処理などを、非同期にBatchで実行することで、スケーラブルなジョブ実行環境にできないかと思いました。
API Gateway + LambdaからBatch Jobを実行する
構成イメージは以下のようになります。
APIに対しリクエストを行うと、Lambda関数はBatchに対しジョブの実行を要求し、すぐにレスポンスを返します。Batchはその後、APIのリクエストとは非同期でジョブを実行します。
ElasticBeanstalkのworker環境や、StepFunctionsに実装したActivity State Machineの呼び出しでも、非同期にEC2上のアプリケーションを実行することは可能です。しかし、Batchを使うことで、ジョブの要求数に応じて環境をスケールさせて実行することができます。
構築
以下の順で構築していきます。
- Batch環境の作成
- Lambda関数の作成
- API Gatewaの作成
AWS Batchの準備
今回は特に処理内容はなんでもよかったので、以下の記事の手順でBatchのジョブキュー/ジョブ定義を作成しました。
次のLambda関数の作成で、ジョブキューのARNを指定する必要がありますが、マネジメントコンソールからは確認できませんでした。AWS CLIのdescribe-job-queues
で取得することができます。
$ aws batch describe-job-queues { "jobQueues": [ { "status": "VALID", "jobQueueArn": "arn:aws:batch:ap-northeast-1:xxxxxxxxxxxx:job-queue/first-run-job-queue", "computeEnvironmentOrder": [ { "computeEnvironment": "arn:aws:batch:ap-northeast-1:xxxxxxxxxxxx:compute-environment/first-run-compute-environment", "order": 1 } ], "statusReason": "JobQueue Healthy", "priority": 1, "state": "ENABLED", "jobQueueName": "first-run-job-queue" } ] }
Lambda関数の作成
Batchに対してJobをサブミットするLambda関数を用意します。Python 3.6のランタイムで以下のような関数を作成しました。
import boto3 def lambda_handler(event, context): client = boto3.client('batch') JOB_NAME = event['JobNeme'] JOB_QUEUE = "arn:aws:batch:ap-northeast-1:xxxxxxxxxxxx:job-queue/first-run-job-queue" JOB_DEFINITION = "first-run-job-definition:1" response = client.submit_job( jobName = JOB_NAME, jobQueue = JOB_QUEUE, jobDefinition = JOB_DEFINITION ) print(response) return 0
Jobを実行するだけの関数です。JobName
のみリクエストから受け取るようにしています。
関数のロールには、AWS BatchのSubmitJob
の実行権限を持つIAMポリシーをアタッチします。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": [ "batch:SubmitJob" ], "Resource": [ "*" ] } ] }
API Gatewayの作成
続いて、API Gatewayの作成です。
API Gatewayのマネジメントコンソールで、[新しいAPIの作成]からAPIとリソースを作成します。以下の記事を合わせて参照ください。
作成したリソースに、[メソッドの作成]からPOSTメソッドを作成し、セットアップします。[統合タイプ]にLambda関数を選択し、先ほど作成した関数を指定します。
メソッドが作成されました。次に、[アクション]から[APIのデプロイ]を選びます。ステージを選択すれば完了です。
APIが呼び出し可能になりました。APIのURLが確認できます。
実行してみる
それでは実行してみます。curlコマンドで作成したURLにPOSTします。
$ curl -X POST -d '{ "JobNeme" : "test" }' https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/test/testbatch
実行されたJobはAWS Batchのコンソールから確認できます。APIからの呼び出し直後は、RUNABLEのステータスです。
環境で定義したEC2の起動されると、ジョブが実行されます。しばらくすると、ステータスがSUCCEEDEDになりました。ジョブが完了したようです。
これで、APIから呼び出し可能な、スケーラブルなジョブ環境が構築できました。
まとめ
以上です。あとは、Batchジョブにアプリケーションを乗せることで、処理の実行が可能です。処理が非同期化されますので、完了時にSNSのプッシュなどを組み合わせると良いでしょう。