【 AWS 】Lambdaを使ってAWS BatchにjobをSubmitする方法(1)

# __「 00. はじめに 」__
__「AWS Lambda」__を使って、__「AWS Batch」__にjobをSubmitするまでの実装 (設定) 手順をまとめたいと思います:point_up:！

今回考えている構成は、下記の通り。

![overview (2).jpg](https://qiita-image-store.s3.amazonaws.com/0/180432/7b58c7c8-634c-490e-c5e8-d9edc2efbebc.jpeg)

### 処理フロー
> 1. 特定のBucketにファイルをアップロード (ユーザー)
2. ファイルアップロードを検知 (Lambda:トリガー)
3. AWS Batchにjobを投げる (Lambda: index.js)

この構成を実現するために実装が必要な部分は、下記の通り。
> (1) S3バケットの作成 _( 本記事では、割愛 )_
(2) AWS Batchの初期設定
(3) Amazon Lambda関数作成
(4) [検証]ファイルアップロード

![AWSBatch.jpg](https://qiita-image-store.s3.amazonaws.com/0/180432/17d4b7bb-68ed-bb17-f0de-b1466aaa215a.jpeg) __「 01. AWS Batchの初期設定 」__
---

## __AWS Batchとは？__

![aws_batch.jpg](https://qiita-image-store.s3.amazonaws.com/0/180432/0a89abc6-096d-4c1e-1461-49f901a14bac.jpeg)


__「Job definitions(ジョブ定義)」__を使って生成した__「 Jobs (ジョブ) 」__を__「 Job queues (ジョブキュー) 」__に投げると、job queuesに紐づいた__「 Compute environments (コンピューティング環境) 」__をプロビジョニングし、
job definition内で定義された__ECR__ ( EC2 Container Registory ) または、__Docker Hub__からコンテナイメージを取得して、
自動でバッチ処理を実行してくれるマネージドサービスです。

(※1) 後述「 __Minimum vCPUs__ 」を __0__ に指定しておくことで、実行しているタスクがない場合、
<font color="red">__インスタンスを起動してから1時間以内に自動で停止・削除__</font> __( Terminate )__ を行ってくれます。

---

_AWS Batchは、バッチ処理を行う実行コマンド、インフラ環境等をあらかじめ設定しておくためのものなので、
この時点では利用料金は無料です。AWS Batchの設定に基づいて起動したECS ( EC2クラスタ ) やその他、
AWS Batchにより起動したサービスにおいて従量課金モデルが適用されるので、デモ等を行った後は、
不要なインスタンスが立ち上がったままになっていないかチェックしてみてください！_

---

AWS Batchに触れたことのない私のようなユーザーは、
まず最初に、下記の2つの記事を読むとサービスのイメージを掴みやすいと思います。

> - [初めてのAWS Batch ( 必要な各コンポーネントを理解する ) ](https://dev.classmethod.jp/cloud/aws-batch-component/)
- [初めてのAWS Batch ( 利用時に考慮したことやったことまとめ ) ](https://dev.classmethod.jp/cloud/aws-batch-design/)

それでは、AWS Batchを扱う上で押さえておくべき3つのコンポーネントについて紹介したいと思います。
_(上記記事内でも触れられている内容ですが、さらに初心者にも分かりやすいよう表現したつもりです。)_

## __AWS Batch の3つのコンポーネントについて！__

![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/f7c63a64-b3ab-e90e-fc7f-f743469c1cab.png)
[ 図 : AWS Batchコンソール画面 ]

## __1. Job definitions__ __[ ジョブ定義 ]__
_ジョブとして起動するコンテナイメージ、実行コマンド、環境変数、マウントするボリューム等を
指定することができます。また、エラー発生時のリトライ回数の指定を行うことも可能です。_

<font color="teal">__分かりやすく一言で言うと、ジョブを生成する際のテンプレートです。__</font>

## __2. Job queues__ __[ ジョブキュー ]__
_AWS Batch用のジョブキューです。_ __FIFO (First In First Out)__ _に対応しており、
キューには優先順位をつけることができます。_

<font color="teal">__サブミットされたジョブを管理するキュー。
どのコンピューティング環境でジョブを実行するのか紐づけをすることが可能です。__</font>

## __3. Compute environments__ __[ コンピューティング環境 ]__
_バッチ処理を行うECS(クラスタ)の定義を行います。インスタンスタイプから、key pair、
ロールなどを指定することができます。また、AutoScalingの設定も可能です。_

<font color="teal">__実際に処理を行うコンピューティング環境の設定が可能です。__</font>

## 実践編

なにはともあれ、設定画面を見ずにテキストでできるだけ教えてもらっても意味がないので、
実際の設定を行いながら、解説を進めていきたいと思います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/ade66624-fa01-fa23-954d-ae78f60f4e99.png)

さっそく、__[ Get started ]__ をクリックして進めていきます。
はじめてAWS Batchの設定を行う際に表示される「初期設定ウィザード」はそのまま進めていき、
デフォルトのまま作成すると、後で個別の設定を行う際に楽になるので、とにかくデフォルトのまま進めていきます。
(※また、jobが実行されインスタンスが立ち上がりますので、削除しておいてください。)

> __[ 参考サイト ]__
 - [AWS Batchを使って5分以上かかる処理を実行してみる](https://dev.classmethod.jp/cloud/aws-batch-5min-over/)

### __1. Compute environments ( コンピューティング環境 ) の設定__
---
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/1cde0107-d464-15dd-bd84-74b2f22d369d.png)

- __Compute environment type__ は、「 <font color="red">__Managed__</font> 」のままにしておく。
- 今回は「初回設定ウィザード」を使って作成したコンピューティング環境と区別をしたいので、適当に名前を付ける。
- 「Desired VCPUs」は起動するインスタンスの希望するvCPUの数なので、1~2に設定しておくのが良いと思います。
- また、冒頭でも記載しましたが、「Minimun vCPUs」を __0__ に設定しておくと、  
起動したインスタンスの実行タスクがなくなってから一時間以内に自動的にterminatedしてくれます。

詳しい設定方法については、下記URLを参照いただければと思う。

- [コンピューティング環境の作成 - AWS公式サイト](http://docs.aws.amazon.com/ja_jp/batch/latest/userguide/create-compute-environment.html) 

実際に、上記条件で、コンピューティング環境を作成してみると、、
ECSのクラスターが自動生成されていることが確認できると思います。
AWS Batchの裏側ではECSが動いているので、AWS Batchでタスクを実行すると、
こちらでもステータスを確認することができます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/b1aac465-4753-29df-06c2-d2f9699f1e28.png)

### __2. job queues の設定__
---
新たにjob queuesを作成します。名前を適当に付けて、「Priority 1」「Select a compute environment 〇〇〇(さきほど作ったコンピューティング環境)」を設定し、Createボタンを押下すれば作業終了です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/a5764a3a-560d-27d8-943a-8ad814f01e85.png)

続いて、job definitionsの設定に移ります。

### __3. job definitions の設定__
---
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/6975e548-b378-37d4-4da4-09418f934a32.png)

# __「 02. AWS Lambda関数を作成する 」__
#### __1. 名前と、Lambda関数を実行するロールを選択します。__
> ![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/1d506e8e-cb38-0c0b-5cb1-8933473e79c5.png)
今回は、初期設定ウィザードに従って作成したユーザー(lambda_basic_execution)を使用します。

#### __2. トリガーの設定を行います。__
> 今回の構成では、S3(特定のファイルバケット)へのファイルアップロードをLambda関数のトリガーとして設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/b53b21c4-819f-c0cf-7755-c3d5599c6123.png)

> ![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/d2131711-41ee-7765-bcec-897dfd020ae0.png)

> ![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/511cc2d4-beb7-ff32-b1cf-3092445fe4f8.png)

> ![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/b8d3064c-9dd9-10b6-22f6-1119ab2f8198.png)
「トリガーの有効化」にチェックを入れておくと、設定後すぐに動作するようになります。

#### __3. 設定を追加します。__
> 2.で指定したイベントが発生すると、「AWS Batch」へ「job」を投げるソースコードを追加します。
今回は、コードを__インライン__で編集しますが、__ZIPファイル__や__S3__から読み込むことも可能です。

> ![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/d209dc3a-67d5-917d-2621-a5a6ea7de4dc.png)


```index.js
'use strict';

const AWS = require('aws-sdk');
const S3  = new AWS.S3();

// AWS Batch Setting
const BATCH         = new AWS.Batch({apiVersion: '2016-08-10'});
const JOBDEFINITION = 'YOUR_JOBDEFINITION';
const JOBQUEUE      = 'YOUR_JOBQUEUE';

console.log('Loading function');

exports.handler = (event, context, callback) => {

    // どこにファイルがアップロードされたのかを検知します。  
    let bucket = event.Records[0].s3.bucket.name;
    let key = event.Records[0].s3.object.key;
    let filePath = bucket + '/' + key;
    console.log(filePath);
       
    let params = {
        jobDefinition: JOBDEFINITION, 
        jobName: 'JOB_NAME(任意の値)',
        jobQueue: JOBQUEUE, 
        parameters: { 'path' : filePath } // jobにパラメータを付加することも可能です。
    };
    
    // Submit the Batch Job
    BATCH.submitJob(params, function (err, data) {
        if (err) console.log(err, err.stack);
        else console.log(data);
        if (err) {
            console.error(err);
            const message = `Error calling SubmitJob for: ${event.jobName}`;
            console.error(message);
            callback(message);
        } else {
            const jobId = data.jobId;
            console.log('jobId:', jobId);
            callback(null, jobId);
        } 
    });
};

```

> jobをサブミットする際に、任意のパラメーターも付与することができますが、
job queues側で事前に設定していないとエラーがでるので、ご注意ください。
ちなみに、上記ソースコードのparameter:pathをjob実行時に使用したい場合は、
下記のように設定することができます。

> ![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/b323d421-1914-7195-c032-7e5f8d9fb82a.png)

詳しくは、下記公式サイトをご参照ください。
http://docs.aws.amazon.com/batch/latest/userguide/job_definition_parameters.html


# __「 03. 実際に作成したLambda関数を動かしてみる。 」__

実際に、S3 _(トリガーで設定したバケット)_ にファイルをアップロードしてみると、
関数が実行されることが分かると思います。AWS Batchのダッシュボードにて __job__ のステータスを確認することが可能です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/180432/613d82f9-f250-6361-aa27-5772ce26b931.png)



# __「 04. おわりに 」__
実際に手を動かして、作業を行うことで知識が身につくと思うので、
みなさんも是非試してみてください。最後までお読みいただき、ありがとうございました。
記事も随時アップデートしていく予定なので、「いいね」よろしくお願いいたします。