AWS Batch Preview Getting Started

# AWS Batchとは
AWS上でバッチ処理を実行するためのサービス。
詳細は[AWS Batch User Guide](http://docs.aws.amazon.com/batch/latest/userguide)を参照。

バッチの実処理はAmazon EC2 Container Service(Amazon ECS)で実行される。

# 要素

![aws_batch_architecture_v2.png](https://qiita-image-store.s3.amazonaws.com/0/61641/993cc3cb-a842-f44f-9fc6-8484eb2272bc.png)

## Job Definition
ジョブの定義。以下の内容などを定義する。

- どのDockerイメージを使うか
- どの位のvCPUsやメモリをコンテナに割り当てるか
- コンテナが実行するコマンド（Dockerの `CMD` 相当）
- コンテナに渡す環境変数
- データボリュームの設定
- どのIAM roleをJobに設定するか

## Job
AWS Batchによって実行されるジョブ。

Job Definitionをベースに作成する。
Job Definitionのいくつかのパラメータは上書きできる。

Job間の依存関係を設定することができる。

## Job Queue
Jobが投入されるキュー。キューのジョブはスケジュールされてCompute Environmentsで実行される。

キューに優先度(Priority)を設定できる。
キューが複数あるとき、優先度が高いキューのJobが優先的に処理される。

キューに対してCompute Environmentsを明示的に最大3つまで割当できる。

## Job Scheduling
Job QueueのJobをCompute Environmentsにスケジューリングする。

Job間の依存関係をもとにスケジューリングする。
依存関係がない場合は概ねJobの投入順に実行される。

## Compute Environments
Jobの実行環境。実態はAmazon ECSのコンテナインスタンス。

Compute Environmentsには以下の2種類がある。

- Managed Compute Environments
- Unmanaged Compute Environments

Managedの方はAWS BatchがよしなにAmazon ECS コンテナインスタンスを立ててくれる。
インスタンスは以下の2種類から選べる。

- EC2 On-Demand instance
- EC2 Spot instance

Unmanagedの方は自分でAmazon ECSコンテナインスタンスを立てる必要がある。
好みのAMIを使ってコンテナインスタンスを起動したい場合はこちらを使う。

指定したVPCやsubnetが標準でexternal IPを付与しない場合、AWS Batchのコンテナが外部ネットワークにアクセスするためにNATが必要になる。

Compute EnviromnetsにはEC2インスタンスと同様にTagをつけることができる。

# 使い方

## 前準備

### IAM Rolesの作成
以下のロールを作成する

- `AWSBatchServiceRole`
	- AWS Batchのロール
	- [AWS Batch Service IAM Role](http://docs.aws.amazon.com/batch/latest/userguide/service_IAM_role.html)を参照
- `ecsInstanceRole`
	- Compute Environments(実態はAmazon ECSインスタンス)のロール
	- [Amazon ECS Instance Role](http://docs.aws.amazon.com/batch/latest/userguide/instance_IAM_role.html)を参照
- `AmazonEC2SpotFleetRole`
	- Spot instanceを使用する場合に用意するロール
	- [Amazon EC2 Spot Fleet Role](http://docs.aws.amazon.com/batch/latest/userguide/spot_fleet_IAM_role.html)を参照

### Key Pairの作成
Compute Environments(実態はAmazon ECSインスタンス)へSSHでログインするためのキーペア。

### VPCの作成
割愛。

### Security Groupの作成
割愛。

### awscliのインストール
AWS Batchを使えるようawscliを最新版にアップデートする。

```bash
pip install --upgrade awscli
```

本記事は `aws-cli/1.11.30` で実行した。

## AWS Batchを使う
今回はawscliを使う。Webコンソールを使う場合は基本的にjsonと同じ内容をWebコンソールに入力すれば良い。

### Compute Environmentの作成
スケルトンを作成する。

```bash
aws batch create-compute-environment --generate-cli-skeleton > compute_environment.json
```

作成したスケルトンを以下のように編集する。

```json
{
    "computeEnvironmentName": "echoname", 
    "type": "MANAGED", 
    "state": "ENABLED", 
    "computeResources": {
        "type": "EC2", 
        "minvCpus": 0, 
        "maxvCpus": 256, 
        "desiredvCpus": 0, 
        "instanceRole": "arn:aws:iam::<account>:instance-profile/ecsInstanceRole",  /*ecsInstanceRoleのARNを指定*/
        "instanceTypes": [
            "optimal"
        ], 
        "subnets": [
            "subnet-********"  /*subnetを指定*/
        ], 
        "securityGroupIds": [
            "sg-********"  /*securityGroupを指定*/
        ]
    },
    "serviceRole": "arn:aws:iam::<account>:role/service-role/AWSBatchServiceRole"  /*AWSBatchServiceRoleのARNを指定*/
}
```

Compute Environmentを作成。

```bash
aws batch create-compute-environment --cli-input-json file://compute_environment.json
```

### Job Queueの作成
スケルトンを作成する。

```bash
aws batch create-job-queue --generate-cli-skeleton > job_queue.json
```

作成したスケルトンを以下のように編集する。

```json
{
    "jobQueueName": "echoname", 
    "state": "ENABLED", 
    "priority": 1, 
    "computeEnvironmentOrder": [
        {
            "order": 1, 
            "computeEnvironment": "echoname"  /*作成したComputeEnvironmentを指定*/
        }
    ]
}
```

Job Queueを作成。

```bash
aws batch create-job-queue --cli-input-json file://job_queue.json
```

### Job Definitionの作成
スケルトンを作成する。

```bash
aws batch register-job-definition --generate-cli-skeleton > job_definition.json
```

作成したスケルトンを以下のように編集する。

コンテナイメージはDockerHubの `busybox` を使用する。
また `name` パラメータを定義する。
これにより `Ref::name` 部分がジョブ送信時に指定した値またはデフォルト値（`alice`）に置換される。

```json
{
    "jobDefinitionName": "echoname", 
    "type": "container", 
    "parameters": {
        "name": "alice"
    }, 
    "containerProperties": {
        "image": "busybox", 
        "vcpus": 2, 
        "memory": 2000, 
        "command": [
            "echo",
            "Ref::name"
        ], 
        "volumes": [],
        "environment": [
            {
                "name": "age", 
                "value": "20"
            }
        ], 
        "mountPoints": [],
        "readonlyRootFilesystem": false, 
        "privileged": false
    }
}
```

Job Definitionを作成。

```bash
aws batch register-job-definition --cli-input-json file://job_definition.json
```

### Jobの送信
スケルトンを作成する。

```bash
aws batch submit-job --generate-cli-skeleton > job_scheduling.json
```

作成したスケルトンを以下のように編集する。
`name` パラメータの値として `bob` を指定する。

```json
{
    "jobName": "echoname", 
    "jobQueue": "echoname",  /*作成したJobQueueを指定*/
    "dependsOn": [],
    "jobDefinition": "echoname",  /*作成したJobDefinitionを指定*/
    "parameters": {
        "name": "bob"
    }, 
    "containerOverrides": {
        "environment": [
            {
                "name": "age", 
                "value": "30"
            }
        ]
    }
}
```

Jobを送信。

```bash
aws batch submit-job --cli-input-json file://job_scheduling.json
```

（注意）
WebコンソールからJobを送信する際、Job Definitionで定義したパラメータが表示されない（環境変数は表示される）。
ただしJobの実行結果を見ると、きちんとジョブ送信時に指定した値またはデフォルト値が使われている。
表示されないだけで内部ではパラメータは認識されている様子。

## 実行結果の確認
Jobの標準出力の内容をCloudWatchのログから確認できる。
ロググループは `aws/batch/job`。

実行結果は以下の通り。
`name` パラメータの値がJob送信時のものになっていることが確認できる。

```
bob
```