こんにちは、幅広い視野を持つエンジニアを目指しています田中と申します
この記事はAWS Batchを利用してコンテナを定期実行する~前編~の記事の続きとなります
ECRとECS, dockerを使用します(単語の定義程度の理解で問題ありません)
TL;DR
目次
はじめに
前編をまだ読まれていない方は読んでくださいね
AWS Batchを利用してコンテナを定期実行する~前編~
目標
- AWS Batchで応用的な処理を実行する
- AWS Batchをジョブスケジューラとして利用する
手順
AWS Batchでカスタムイメージを使用するまで
Jenkinsのシェル実行機能
画像のようにJenkinsのジョブではシェルスクリプトで処理を行うことができますが、AWS Batchでは可能でしょうか。検証してみます
ジョブ設定1
手始めにdockerコンテナのcgroup情報を見てましょう
まず、Jenkinsのジョブと同じようにShebangを書いてシェルスクリプトを記述してみました
すると・・・
エラーになってしまいました。シェルスクリプトとして解釈してくれないようです
公式ドキュメントにはコマンドとしか言及されていません(ジョブ定義のパラメータ - AWS Batch)
そして、どうやら改行も無視されてしまうようです
ところで、EC2のユーザデータやECSのコマンドも1行で書くお約束でした
下記画像はECSのチュートリアルのタスク定義です
ワンライナーでコンテンツ書き込むんですね・・・
これをAWS Batchでも試します
こんな感じでしょうか
結果はNGでした。何か妨害工作(exec経由の単一プロセス実行)を感じます…
コマンドの連続実行やパイプはできないようです。もう少し試行錯誤します
脱線
- 依存ジョブを作る
- インスタンスを毎回作るので遅い
- 次のコマンドに結果を渡せない
- 依存ジョブの最大は25個まで
- ECSクラスタを利用する
AWS BatchはECSクラスタ、つまりはdockerホストなのでAWS CLIからECSのタスクとして発行します
- AWS CLIのdokcerイメージを利用する
- AWS CLIのコンテナを使ってECSのタスクを発行する
AWS CLIのイメージのCommandに以下のようにしてみます(API KEYやSECRET KEY、regionを環境変数として指定します)
1 |
aws ecs register-task-definition --family test --container-definitions "[{\"name\":\"test\",\"image\":\"busybox\",\"cpu\":1,\"command\":["/bin/sh -c \"ls -la && cat /proc/self/cgroup\""],\"memory\":2000,\"essential\":true}]" |
dockerイメージを自作
Blackbeltの36ページにはイメージには事前に実行するプログラムを含ませておくように書かれています
予めよく読むべきでした
気を取り直してECRを設定します
AWSコンソールからコンピューティング→Elastic Container Serviceを選びましょう
左メニューからリポジトリを選択し、リポジトリの作成を押下
- リポジトリ名には任意の名前を入力します
もうリポジトリができました!
リポジトリの利用方法が表示されています。ここにあるコマンドはこの後使いますのでメモしておきましょう!(後から見ることもできます)
docker環境の準備
続いてdockerイメージを自作するための環境を作成しましょう
EC2を利用しても良いのですが、AWS BatchがEC2クラスタを構築してくれているのでこちらを使わせてもらいましょう
EC2を利用する場合でも下記コマンドで一発でdocker環境が手に入ります
1 |
yum install docker |
dockerイメージの構築
dockerイメージを作るためのベースとなるイメージをpullしましょう
Dockerfileを記述しカスタマイズ、docker buildを行っても良いですが、今回は既存の物を使わせてもらいましょう
私はAWSに対して処理を自動化したかったので以下のイメージを使いました
1 |
docker pull garland/aws-cli-docker |
イメージがpullできたら
1 |
docker images |
とコマンドを入力します
1 2 |
REPOSITORY TAG IMAGE ID CREATED SIZE garland/aws-cli-docker latest xxxxxxxxxxxx 2 weeks ago 96.4MB |
先ほどpullしたイメージがリストされています
このイメージのIMAGE_IDを使ってコンテナを起動しますのでメモしておきましょう!
1 |
docker run -it xxxxxxxxxxxx /bin/sh |
コンテナのシェルが表示されましたか?
あとはこのコンテナで必要なものをインストールしたり、任意のプログラム/スクリプトをデプロイします
準備が完了したらCtrl+Dを押下してコンテナを抜けましょう
次に、このコンテナからカスタマイズしたdockerイメージを作成します
1 |
docker ps -a |
と入力すると、先ほどカスタマイズしたコンテナが見えます
1 2 |
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES YYYYYYYYYYYY XXXXXXXXXXXX "/bin/sh" 2 weeks ago Exited (0) 2 days ago aqours_sunshine |
CONTAINER IDを使ってカスタマイズしたイメージを作成します次のコマンドを入力しましょう
1 |
docker commit YYYYYYYYYYYY -m="May our dream come true!" skyarch/test/awsbatchbase:latest |
-m="May our dream come true!"のところはコミットメッセージであり、skyarch/test/awsbatchbase:latestはタグ名なので任意のもので構いません
docker imagesを実行すると今作ったイメージが表示されています
1 2 |
REPOSITORY TAG IMAGE ID CREATED SIZE skyarch/test/awsbatchbase latest ABCDEFGHIJKL 2 days ago 116MB |
さていよいよこのイメージをECRにアップロードしていきます
まずは、ECRにログインします。ECRをセットアップした際に表示されていたコマンドを入力しましょう
1 2 |
aws ecr get-login --region [ECRを作成したリージョン] docker login -u AWS -p [ECRにログインするためのシグネチャ] [ECRのリポジトリのURL] |
成功すると、
1 |
Login Succeeded |
と表示されECRに接続することができます
ECRにアップロードするためのタグをイメージにつけましょう
1 |
docker tag skyarch/test/awsbatchbase:latest abcdfeghijkl.dkr.ecr.ap-northeast-1.amazonaws.com/skyarch/test/awsbatchbase:latest |
そしていよいよpushです!
1 |
docker push abcdefgjkl.dkr.ecr.ap-northeast-1.amazonaws.com/skyarch/test/awsbatchbase:latest |
成功したら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設定2
ページ下部から作成したCloudWatch Eventを編集します
CloudWatch Event設定3
CloudWatch Event設定4
スケジュールを設定します(時刻はUTCです)
cron式と言いつつ、"日"のフィールドに"*"を指定するとエラーになるので"?"を指定します
CloudWatch Event設定5
ユーザデータを指定します
先ほどLambda関数を作成しましたが、Lambdaのeventにデータを入れる設定をします
- ターゲットにLambda関数を選択
- 機能のセレクトボックスから先ほど作成したLambda関数を選択
- 入力の設定を展開し、定数(JSONテキスト)を選択
- 入力欄に下記内容を入力
1 |
{ "JobName": "任意のジョブ名", "JobQueue": "作成したジョブキューの名前", "JobDefinition": "作成したジョブのarn" } |
UIが頻繁に変わることに加え、ユーザデータの指定の場所がとても分かりづらいです!
これで、cron式で指定した日時になるとジョブが実行されて幸せになれます!!
まとめ
AWS Batchを使うことでスケーラブルでマネージ不要なHPC環境を低コストに実現できる!
AWS BatchとCloudWatch Eventを使うことでジョブを任意の日時に自動実行させることができ、マネージ不要のタスクスケジューラとして使える!
ここまで読んでくださりありがとうございました!
記事は以上になります。
このたびはご覧戴き、ありがとうございました。
・引用元および参考にさせていただいたサイト様
【公式】AWS Batchの開始方法
【公式】Docker
【公式】Docker hub
(初心者向け)Dockerの使い方
AWS BatchでPythonスクリプトを定期的に実行する
(CloudWatch Eventのトリガー使用方法およびLambdaのキックスクリプトをそのまま使用させていただいております)
投稿者プロフィール
最新の投稿
- AWS2021年12月2日AWS Graviton3 プロセッサを搭載した EC2 C7g インスタンスが発表されました。
- セキュリティ2021年7月14日ゼロデイ攻撃とは
- セキュリティ2021年7月14日マルウェアとは
- WAF2021年7月13日クロスサイトスクリプティングとは?