AWS Batchを利用してコンテナを定期実行する~後編~

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

こんにちは、幅広い視野を持つエンジニアを目指しています田中と申します

この記事はAWS Batchを利用してコンテナを定期実行する~前編~の記事の続きとなります
ECRとECS, dockerを使用します(単語の定義程度の理解で問題ありません)
TL;DR

目次

はじめに

前編をまだ読まれていない方は読んでくださいね
AWS Batchを利用してコンテナを定期実行する~前編~

目標

  1. AWS Batchで応用的な処理を実行する
  2. AWS Batchをジョブスケジューラとして利用する

手順

AWS Batchでカスタムイメージを使用するまで

Jenkinsのシェル実行機能

Jenkinsのシェル実行機能

画像のようにJenkinsのジョブではシェルスクリプトで処理を行うことができますが、AWS Batchでは可能でしょうか。検証してみます

ジョブ設定1

手始めにdockerコンテナのcgroup情報を見てましょう
ジョブ設定1

まず、Jenkinsのジョブと同じようにShebangを書いてシェルスクリプトを記述してみました
すると・・・
ジョブエラー1
エラーになってしまいました。シェルスクリプトとして解釈してくれないようです
公式ドキュメントにはコマンドとしか言及されていません(ジョブ定義のパラメータ - AWS Batch)
そして、どうやら改行も無視されてしまうようです

ところで、EC2のユーザデータやECSのコマンドも1行で書くお約束でした
下記画像はECSのチュートリアルのタスク定義です
ECS Sample App
ワンライナーでコンテンツ書き込むんですね・・・
これをAWS Batchでも試します

ジョブ設定2
こんな感じでしょうか
結果はNGでした。何か妨害工作(exec経由の単一プロセス実行)を感じます…
ジョブエラー2
コマンドの連続実行やパイプはできないようです。もう少し試行錯誤します

脱線
  • 依存ジョブを作る

依存ジョブ
逐次実行はできました
イケてない点

  1. インスタンスを毎回作るので遅い
  2. 次のコマンドに結果を渡せない
  3. 依存ジョブの最大は25個まで
  • ECSクラスタを利用する

AWS BatchはECSクラスタ、つまりはdockerホストなのでAWS CLIからECSのタスクとして発行します

  1. AWS CLIのdokcerイメージを利用する
  2. AWS CLIのコンテナを使ってECSのタスクを発行する

AWS CLIのイメージのCommandに以下のようにしてみます(API KEYやSECRET KEY、regionを環境変数として指定します)

成功?
成功・・・あまり良い方法ではないですね。本線に戻ります

dockerイメージを自作

Blackbeltの36ページにはイメージには事前に実行するプログラムを含ませておくように書かれています
予めよく読むべきでした

気を取り直してECRを設定します
AWSコンソールからコンピューティング→Elastic Container Serviceを選びましょう
ECR設定
左メニューからリポジトリを選択し、リポジトリの作成を押下
ECR設定

  • リポジトリ名には任意の名前を入力します

もうリポジトリができました!
ECR使用方法
リポジトリの利用方法が表示されています。ここにあるコマンドはこの後使いますのでメモしておきましょう!(後から見ることもできます)

docker環境の準備

続いてdockerイメージを自作するための環境を作成しましょう
EC2を利用しても良いのですが、AWS BatchがEC2クラスタを構築してくれているのでこちらを使わせてもらいましょう
EC2を利用する場合でも下記コマンドで一発でdocker環境が手に入ります

dockerイメージの構築

dockerイメージを作るためのベースとなるイメージをpullしましょう
Dockerfileを記述しカスタマイズ、docker buildを行っても良いですが、今回は既存の物を使わせてもらいましょう
私はAWSに対して処理を自動化したかったので以下のイメージを使いました

イメージがpullできたら

とコマンドを入力します

先ほどpullしたイメージがリストされています
このイメージのIMAGE_IDを使ってコンテナを起動しますのでメモしておきましょう!

コンテナのシェルが表示されましたか?
あとはこのコンテナで必要なものをインストールしたり、任意のプログラム/スクリプトをデプロイします
準備が完了したらCtrl+Dを押下してコンテナを抜けましょう
次に、このコンテナからカスタマイズしたdockerイメージを作成します

と入力すると、先ほどカスタマイズしたコンテナが見えます

CONTAINER IDを使ってカスタマイズしたイメージを作成します次のコマンドを入力しましょう

-m="May our dream come true!"のところはコミットメッセージであり、skyarch/test/awsbatchbase:latestはタグ名なので任意のもので構いません
docker imagesを実行すると今作ったイメージが表示されています

さていよいよこのイメージをECRにアップロードしていきます
まずは、ECRにログインします。ECRをセットアップした際に表示されていたコマンドを入力しましょう

成功すると、

と表示されECRに接続することができます
ECRにアップロードするためのタグをイメージにつけましょう

そしていよいよpushです!

成功したらAWS Batchで指定できます。Commandにはデプロイしてあるプログラムやスクリプトを実行するように指定してあげます
自作イメージを指定
さてジョブを発行してみると・・・?
ジョブの実行結果
大成功です!シェルスクリプトが実行できました。そしてシェルスクリプトなので環境変数なりでジョブごとに処理の範囲を決めてあげることで簡単に並列実行できますね!(n件の処理をm個に分割など)

さて、次はAWS Batchをタスクスケジューラとして使いましょう!

CloudWatch Eventとの連携

次はAWS BatchをCloudWatch Eventと連携させてジョブを定期実行させます
まず、下記のようなLambda関数を作りましょう!

batch = boto3.client('batch')

def submit_job(event):
    result = batch.submit_job(
    jobName=event['JobName'],
    jobQueue=event['JobQueue'],
    jobDefinition=event['JobDefinition']
    )
    return result

def lambda_handler(event, context):
    result = submit_job(event)
    print(result)
    return None

続いてCloudWatch Eventをトリガーとして追加します

CloudWatch Event設定1

LambdaのDesigner→トリガーの追加→CloudWatch Eventを選択
CloudWatch Event設定1

CloudWatch Event設定2

ページ下部から作成したCloudWatch Eventを編集します
CloudWatch Event設定2

CloudWatch Event設定3

CloudWatch Event設定3
ページ右上のアクションから編集を選択

CloudWatch Event設定4

スケジュールを設定します(時刻はUTCです)
CloudWatch Event設定4
cron式と言いつつ、"日"のフィールドに"*"を指定するとエラーになるので"?"を指定します

CloudWatch Event設定5

ユーザデータを指定します
先ほどLambda関数を作成しましたが、Lambdaのeventにデータを入れる設定をします
CloudWatch Event設定5

  • ターゲットにLambda関数を選択
  • 機能のセレクトボックスから先ほど作成したLambda関数を選択
  • 入力の設定を展開し、定数(JSONテキスト)を選択
  • 入力欄に下記内容を入力

UIが頻繁に変わることに加え、ユーザデータの指定の場所がとても分かりづらいです!
これで、cron式で指定した日時になるとジョブが実行されて幸せになれます!!

まとめ

AWS Batchを使うことでスケーラブルでマネージ不要なHPC環境を低コストに実現できる!
AWS BatchとCloudWatch Eventを使うことでジョブを任意の日時に自動実行させることができ、マネージ不要のタスクスケジューラとして使える!
ここまで読んでくださりありがとうございました!
記事は以上になります。
このたびはご覧戴き、ありがとうございました。

・引用元および参考にさせていただいたサイト様
【公式】AWS Batchの開始方法
【公式】Docker
【公式】Docker hub
(初心者向け)Dockerの使い方
AWS BatchでPythonスクリプトを定期的に実行する
(CloudWatch Eventのトリガー使用方法およびLambdaのキックスクリプトをそのまま使用させていただいております)
 

投稿者プロフィール

スカイブロガー

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Time limit is exhausted. Please reload CAPTCHA.