AWS Batch on Fargate/EC2 + EventBridge を使ってみる
まず手元のmacOSにfinchをインストールしてコンテナを作成するところから
$ brew install finch
$ finch vm init
$ finch run --rm public.ecr.aws/finch/hello-finch:latest
public.ecr.aws/finch/hello-finch:latest: resolved |++++++++++++++++++++++++++++++++++++++|
index-sha256:a71e474da9ffd6ec3f8236dbf4ef807dd54531d6f05047edaeefa758f1b1bb7e: done |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:705cac764e12bd6c5b0c35ee1c9208c6c5998b442587964b1e71c6f5ed3bbe46: done |++++++++++++++++++++++++++++++++++++++|
config-sha256:6cc2bf972f32c6d16519d8916a3dbb3cdb6da97cc1b49565bbeeae9e2591cc60: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:ec080f7c92e9eb0227d60951f7c779648989116d97a5926f3e8684d4e46df196: done |++++++++++++++++++++++++++++++++++++++|
elapsed: 4.2 s total: 1007.7 (239.9 KiB/s)
@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@ @@@@@@@@@@@
@@@@@@@ @@@@@@@
@@@@@@ @@@@@@
@@@@@@ @@@@@
@@@@@ @@@# @@@@@@@@@
@@@@@ @@ @@@ @@@@@@@@@@
@@@@% @ @@ @@@@@@@@@@@
@@@@ @@@@@@@@
@@@@ @@@@@@@@@@@&
@@@@@ &@@@@@@@@@@@
@@@@@ @@@@@@@@
@@@@@ @@@@@(
@@@@@@ @@@@@@
@@@@@@@ @@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@
Hello from Finch!
Visit us @ github.com/runfinch
次に自分が使いたいPython環境が入ったコンテナを作成する
次にAmazon Elastic Container Registy(Amazon ECR)にコンテナをアップロードする。
$ aws ecr get-login-password --region ap-northeast-1 | finch login --username AWS --password-stdin 123456789.dkr.ecr.ap-northeast-1.amazonaws.com
WARNING: Your password will be stored unencrypted in /Users/ymotongpoo/.finch/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
$ finch build -t ymotongpoo-container/foo .
$ finch tag ymotongpoo-container/foo:latest 123456789.dkr.ecr.ap-northeast-1.amazonaws.com/ymotongpoo-container/foo:latest
$ finch push 123456789.dkr.ecr.ap-northeast-1.amazonaws.com/ymotongpoo-container/foo:latest
AWS Batchをウィザードに沿ってJobを作ろうと思ったら、実行ロールが無いと言われてエラーが出た。これは何だ?
IAMでこれ専用のロールを作っていたけど、許可ポリシー(permission policy)を適当な順番で設定してしまうと、信頼関係(Trust relationship)は上書きされないままになってしまうので、期待したとおりに動かない。
許可ポリシーは AWSBatchServiceRole
をそのまま付与して、信頼関係は次のようになっていることを確認する。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
ジョブを実行してみたらエラーで落ちた。詳細を確認すると次のような理由で落ちている。
ResourceInitializationError: unable to pull secrets or registry auth: The task cannot pull registry auth from Amazon ECR: There is a connection issue between the task and Amazon ECR. Check your task network configuration. RequestError: send request failed caused by: Post "https://api.ecr.ap-northeast-1.amazonaws.com/": dial tcp 3.112.65.177:443: i/o timeout
まさにこのエラーが出ている
いくつか記事を見ながら参考にする。(エラーメッセージの内容が変わったようで昔のエラーメッセージでも検索してみる)
- https://note.shiftinc.jp/n/nf456dd5900df
- https://dev.classmethod.jp/articles/vpc-endpoints-for-ecs-2022/
とりあえずロールに関しては AmazonEC2ContainterRegistyReadOnly
の許可ポリシーを追加してみたけどダメなんで、やっぱりネットワーク周りっぽさの問題のよう。
一旦Fargateベースは辞めて、EC2ベースなら動くのか試してみる。
このワークショップにしたがって実行してみたら、あっさり動作。やはりFargate特有のネットワークまわりの設定が原因とわかった。
今度はEventBridgeで作ったBatch on EC2のジョブ定義を呼び出すことをやってみる。
Batchを呼び出すためにロールを作成しないといけないようなので、チュートリアルに従ってロールを作成する。
カスタムで作成する。信頼関係はこれ。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
許可ポリシーはこれ。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"batch:SubmitJob"
],
"Resource": "*"
}
]
}
そしたら設定完了しようとしたときにこのエラー
The execution role you provide must allow AWS EventBridge Scheduler to assume the role.
エラーメッセージで調べたらこの記事が出てきて、信頼関係を次のように変えたらできた。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "scheduler.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
さあこれでいいぞと思ったら、スケジューラーの場合パラメーターをAWS Batchに渡せないので困った。ジョブ定義を複数作らないといけない様子。
今回はジョブ定義の数が少なくて済みそうなので、今回の学びをもとにCDKで自動でここまで作ってきたAWS Batch on EC2に定期実行のEventBrdigeを複数のジョブ定義で作ってみる。
と思ったら自分が完全に見逃してた。完全にこのre:Postの記事の通りで行けるんだけど、自分がUIに惑わされて見逃していた。
こんな色分けしてたら右下のボタン押しちゃうじゃん。正しくは左下の "Continue to create rule" を押さないといけない。
それを押すと上のre:Postに書かれてるプロセスに入れる。Targetで "Additional settings" の部分で "Configure target input" を "Constant (JSON text)" に変更して、その下のJSONエディタで次のように値を入力する。
{
"ContainerOverrides": {
"Environment": [{
"Name": "FOO",
"Value": "dynamic_value_1"
}, {
"Name": "BAR",
"Value": "dynamic_value_2"
}
]
}
}
作ったRuleをコピーしたいんだけどやり方がわからない。もしかしてそんな方法が存在しない?
EventBridgeのスケジュールで定期実行をしていたジョブが動作していないようだったので、実行結果を確認しようとしたけど、EventBridgeのコンソールにはそれらしきUIが存在しない。調べてみるとCloudTrailイベントから確認する模様。しかしCloudTrailのEvent historyに行ってみたものの、時間を絞ってみてもそれらしいイベントはみつからない。
とりあえずデッドレターキューの設定をしてなかったので、SQSでキューを作成して、定期実行してるルールのDLQの行き先として指定した。これでコンソール上で失敗して行き場がなくなったイベントをSQS上で確認できるようになった。
1つを開くとこのようにエラーが見られるので、これでデバッグ可能になった。どうやらロールの設定が間違っているようだったので修正した。