初めてのAWS Batch – 利用時に考慮したことやったことまとめ –

2017.10.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンニチハ、千葉です。

AWS Batchを導入する機会があり、やったこと、設計したことなどをまとめました。

AWS Batchってなに?は、こちらにまとめましたので御覧ください!前提知識として必要になります。 本エントリーでは、設計時に考えたことをまとめます!

ECR

Dockerコンテナを格納するリポジトリが必要になります。プライベートリポジトリであるECRを利用しましょう。リポジトリを利用する認証もIAMロールで対応できるのでシンプルに利用できます。 AWS Batch環境の作成前に、リポジトリを作成しダミー用コンテナイメージをアップしておきましょう。

IAMロール

必要なIAMロールです。AWS Batch作成前に事前に作成しました。EC2のインスタンス用とコンテナ用の2種類が必要になります。

EC2インスタンス用ロールとしては、「AmazonEC2ContainerServiceforEC2Role」ポリシーをアタッチします。 コンテナ用については、コンテナで利用するポリシーをアタッチします。

AMIの作成

Batchで起動されるECS用のAMIを用意します。デフォルトだとAmazon ECS-Optimized Amazon Linux AMIで起動されます。ディスク容量を変更したり、インスタンスストアを利用したい場合はカスタムAMIを作成する必要があります。

参考:コンピューティングリソース AMI の作成

今回は、インスタンスストアを利用する環境でしたので以下のようにAMIを作成しました。

ECSオプティマイズAMI(Amazon ECS-Optimized Amazon Linux AMI)よりEC2を作成し、

  1. ユーザーデータに以下を指定
    #!/bin/bash
    yum update -y
    echo '#!/bin/bash' > /var/lib/cloud/scripts/per-boot/initial_instance_store.sh
    echo 'mkfs -t ext4 /dev/xvdb;mount /dev/xvdb /media/ephemeral0' >> /var/lib/cloud/scripts/per-boot/initial_instance_store.sh
    chmod 750 /var/lib/cloud/scripts/per-boot/initial_instance_store.sh

  2. ボリューム設定でインススタンスストアを追加(インスタンスストア:/dev/sdb)

  3. インスタンスを停止しAMIを作成

このAMIをAWS Batchで指定します。

AWS Batch環境の構築

ここでようやくAWS Batchの管理コンソールから操作を行います。

Compute environments

Compute environmentsを作成します。これは起動するEC2に関する環境定義となります。

ポイントとしては、vCPUsの設定になります。ここの設定はAutoScalingに反映されます。例えばですが、EC2:コンテナを1:1で起動させたい場合は、コンテナで指定するvCPUs・メモリサイズを、利用するインスタンスサイズとイコールにします。例えばですが、

環境:r3.xlarge(vCPUs4、メモリ30.5GB)、コンテナのリソースもvCPUs4、メモリ30.5GB メモリ29GB等に設定

実際にインスタンスで利用できるメモリは30.5GBより小さくなる場合があり、EC2が自動で起動しなくなることがありました。そのため、スペックより小さい値でメモリを設定します

Min:0 ※0にするとジョブキューがない場合はEC2は0。r3.xlargeの場合は4に指定すると1インスタンスが起動する、8にすると2インスタンスが起動する。 Max:40 ※最大40にすると、最大で10インスタンスが起動します。

Minを0にすると、キューがない場合EC2インスタンスが0になりリソース費用がかかりません。逆に、ジョブ実行時にEC2インスタンスの起動が必要になるためラグが発生します。システムに応じて変更する必要があります。 Min、Maxはコンテナをどれくらい起動させるかを考えながら指定します。

Job queues

ジョブキューに関する定義です。ジョブキューには、Compute environmentsで作成した環境を指定できます。また、Compute environmentsに優先順位をつけて複数指定できます。そのため、常時EC2を2台起動、追加でスポットインスタンスも利用みたいな構成もとれます。

Job definitions

起動するコンテナを定義します。これは、ECSのTask定義と同等と考えて大丈夫そうです。コンテナで利用する、コンテナのリソース(vCPUs、メモリ)、コンテナイメージ、実行コマンド、ローカルディスクのマウント設定などができます。また、リトライ回数も定義可能です。これらを決める必要があります。

Job

ジョブ実行時に渡す変数を決めましょう。ポイントは、手動でリトライするときに簡単にできるように設計することです。例えば、ID:999の処理を再実行したい場合、コンテナの環境変数にID:999を渡したときに同じ処理を実行できれば再実行しやすいですよね。また環境に依存値も環境変数で渡します。テスト環境や本番環境で固有な値(例えばDB接続情報など)あたりも環境変数に登録できると柔軟性が高いでしょう。この他にもアプリケーションによって、必要なパラメータがあれば適宜環境変数で指定し、コンテナが処理できるように設計します。

エラー時の通知

アプリケーションエラー時の通知用として、 SNSを作成しました。アプリケーションにてエラー時はSNSを利用してメール通知するようにします。

※コンテナ用のロールに「AmazonSNSFullAccess」をアタッチが必要です

ログ出力

アプリケーションで必要なログは、標準出力に出力するように設定します。こうすることで、自動でCloudWatch Logsへログが登録されます。エラー時のデバックや解析用に設定しておくとよいでしょう。 またCloudWatch Logsに保存すると、S3、Kinesis、Elasticsearch Serviceとも連携できます。

キューの監視

処理依頼が沢山来た場合、キューが滞留します。滞留したらアラートがほしいですよね。 ただ、今のところAWS BatchではCloudWatchと連携の機能がないので、アラートが必要な場合はLambdaで実装する必要があります。boto3で確認したところlist_jobsでジョブのステータスを指定してジョブを取得できそうです。「RUNNABLE」になっているジョブの数をカウントすれば、滞留していないかを確認できそうです。

最後に

AWS Batchを利用する上で考慮したことをまとめました。SQSを利用した構成より簡単に実装できたので、バッチ処理が必要な場合はAWS Batchを使っていきたいです。

参考