目的
AWS Fargate 上の AWS Batch job を Lambda から実行します。
便利なので Lambda から Batch を実行したかったんです。
概要図
準備
AWS Batch
コンピューティング環境の作成
AWS Batch のトップページから「コンピューティング環境」->「作成」と選択します。
Fargate を選択して、名前を入力します。
環境名は「takahara-fargate-batch」としました。
次にスポットインスタンスとvCPU数を設定します。
ここは料金と処理速度性能に関わります。
スポットインスタンスは料金が安くなる代わりに、処理を中断する可能性がごく僅かにあります。
ネットワーク設定はデフォルトVPC・パブリックサブネット・セキュリティグループを選択しました。
ECRやS3などのサービスのエンドポイントのドメイン名解決にはインターネットアクセスもしくはVPCエンドポイントが必要です。
パブリックサブネットを避けたい時はプライベートサブネットに NAT ゲートウェイを建てるか、各種サービスにVPCエンドポイントを設置しましょう。
確認画面から「コンピューティング環境を作成」ボタンを押しましょう。
ジョブキューの作成
トップページから「ジョブキュー」->「作成」と選択します。
Fargate を選択して、名前を入力します。
ジョブキュー名は「takahara-fargate-job-queue」としました。
「接続されたコンピューティング環境」は先ほど作成したコンピューティング環境を選択してください。
ジョブ定義
トップページから「ジョブ定義」->「作成」と選択します。
Fargate を選択して、名前を入力します。
ジョブキュー名は「takahara-fargate-batch-task」としました。
パブリックIPは割り当てましょう。(理由は上述のようにインターネットアクセスが必要なため)
Docker Image はデフォルトですが、コマンドに["echo","Ref::word"]
を設定しています。
Refを使うと、Lambda からジョブを実行した時にパラメータを引数として渡せます。
今回はword
を引数として渡しています。
ECS タスクの実行ロールはデフォルトの「ecsTaskExecutionRole」を選択しましたが、このままだと不便なことも多いです。
たとえば Batch job が S3 にアクセスしたい時です。
この IAM ロール作成方法は後述します。
ユーザーはroot、ログドライバーはawslogsを選択します。
これでAWS Batchの準備は完了です。
Lambda
コード
LambdaのコードはTypeScriptで記述しました。
AWS SDK は v3 を使用しました。
公式ドキュメント以外はほぼ資料がありませんでしたが、よく読むと v2 とはパラメータの渡し方が異なるだけでした。
import { BatchClient, SubmitJobCommand } from "@aws-sdk/client-batch";
const batchClient = new BatchClient({ region: "ap-northeast-1" });
const JOB_QUEUE = "takahara-fargate-job-queue";
const JOB_DEFINITION = "takahara-fargate-batch-task";
export const handler = async () => {
const params = new SubmitJobCommand({
jobName: String(Math.floor(new Date().getTime() / 1000)),
jobQueue: JOB_QUEUE,
jobDefinition: JOB_DEFINITION,
parameters: { word: "AWS Bacth job!" },
});
return batchClient.send(params);
};
たったこれだけです。
job 名は unix time で現在時刻を入れています。
parameters は Batch 実行時に引数として渡せる変数を格納します。
コードは下記リポジトリにアップロードしています。
Lambda用ビルド設定はレポジトリの方を参照してください。
https://github.com/KensukeTakahara/aws-batch-by-lambda
デプロイ
Lambda関数を作成してください。
ランタイムは Node.js 18 を選択しました。
作成が完了したらコードをデプロイしてください。
IAM ロールを追加で設定します。
下記ページから IAM ロール編集画面に移動してください。
インラインポリシーで下記のポリシーを追加しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "batch:SubmitJob",
"Resource": [
"arn:aws:batch:ap-northeast-1:XXXXXXXXXXXX:job-definition/takahara-fargate-batch-task",
"arn:aws:batch:ap-northeast-1:XXXXXXXXXXXX:job-queue/takahara-fargate-job-queue"
]
}
]
}
XXXXXXXXXXXX
は各自の AWS アカウント ID に差し替えてください。
以上で準備は完了です!
実行
Lambdaのテスト画面からテストを実行してみましょう。
実行は成功するはずです。
AWS Batch のジョブ画面を見るとジョブが作成されています。
ここから Batch の出力結果を CloudWatch logs で確認できます。
無事、Lambda から渡した文字列が出力されていますね。
まとめ
無事、Lambda から AWS Fargate 上の Batch job が実行できました。
これで柔軟な Batch 実行が可能になりますね。
おまけ
ECS タスク実行ロール
ECS タスクがデフォルトの IAMロール しか使えないと非常に不便なので、独自の IAM ロールを使います。
やり方は簡単で IAM ロールの「信頼関係」のタブで ECS タスクを信頼されたサービスに設定しましょう。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}