概要
ECS Taskを定期実行したい要件があり、それをただ実行するならEventBridgeからcronのように呼び出すことになる。
しかし、ECS Taskそのものにはリトライ処理が無く、EventBridgeだけだと複数のジョブの処理などに限界があったので、今回はStepFunctionsを検証した。その辺りをざっくりまとめる。
なお、今回はAWSコンソールの作業のみでIaCは検証のため無し。
EventBridgeのリトライ処理について
EventBridgeでもリトライ処理はできるが、意図したエラーハンドリングが出来ない可能性がある。
例えば、ECS Taskでアプリが例外を吐いてもリトライされない。
おそらくECS Taskそのものが起動しないなどのエラーだけをリトライ処理できると思われるので、何をトリガーにリトライ処理をしたいかは確認しておく必要がある。
アプリのエラーについては素直にStepFunctionsを使うと良さそう。
下記の記事で詳しく記載されていた。
ちなみに自分の場合、FargateのECS Taskでも同様だったので、EventBridge自体の制約だと思われる。
[AWS] EventBridge Rules による ECS Scheduled Task はエラー時リトライできない
要件
- 自分で作成したコンテナイメージを使いたい
- コンテナイメージにコマンドを上書きして、実行させたい(イメージを共通化)
- リトライ処理したい
- 定期実行したい
コンテナイメージ
今回はシンプルにこんなコードを用意した。
コードの良し悪しはさておき、引数を取って、各関数を実行させられるかの確認。
<?php
function main(){
global $argc;
global $argv;
print("start: run php test function\n");
if ($argc != 2){
print("info: please set argument\n");
return;
}
$argval = $argv[1];
print($argval());
}
function example_1(){
print("result: exmaple 1\n");
}
function example_2(){
print("result: exmaple 2\n");
}
main();
?>
Dockerfileはこんな感じ。
FROM php:8.2
COPY main.php /usr/local/src/app/main.php
WORKDIR /usr/local/src/app
CMD ["php", "main.php"]
ECRとECS
まずはECRとECSを作成しておく。
ECRには先程のDockerfileをビルドしてPushしておく。
ECSは最小構成で、クラスター、タスク定義とサービスまでOK.
StepFunctions
ECS Run Taskを選択して、下記JSONを設定する。
{
"LaunchType": "FARGATE",
"Cluster": " arn:aws:ecs:ap-northeast-1:XXXXXX:cluster/example",
"TaskDefinition": "example:1",
"Overrides": {
"ContainerOverrides": [
{
"Name": "example",
"Command.$": "$.commands"
}
]
},
"NetworkConfiguration": {
"AwsvpcConfiguration": {
"Subnets": [
"subnet-XXXXXX"
],
"SecurityGroups": [
"sg-XXXXX"
],
"AssignPublicIp": "ENABLED"
}
}
}
ポイントとしては、パラメーターでOverrideしている箇所。
公式ドキュメント通りで、個人的にこのStepFunctionsの書き方が分かりにくいのだけど、commandsで渡した配列が、タスクのCommandに渡されるようになる。
https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/connect-ecs.html
"Overrides": {
"ContainerOverrides": [
{
"Name": "example",
"Command.$": "$.commands"
}
]
リトライ処理をコンソールでポチポチ設定すると下記のようなjsonが追加される。
"Retry": [
{
"ErrorEquals": ["States.ALL"],
"BackoffRate": 5.0,
"IntervalSeconds": 1,
"MaxAttempts": 2
}
]
実行する際には下記のようにコマンドを渡せばOK。
{
"commands": ["php", "./main.php", "example_2"]
}
ポイント: buildとIAMロールに注意
最初手で実行した際にいくつかエラーが出た。
そのうちの一つがexec /usr/local/bin/docker-entrypoint.sh: exec format error
。
これは開発環境がM1 Macだったことによる起因。
build時にplatformを指定すればOK.
docker build --platform linux/amd64 . -t XXXXX:latest
次に、IAM PassRoleでエラーになった。
これは下記の記事がドンピシャ。
ECSのタスク実行ロールとタスクロールを許可するポリシーを作って、StepFunctionsで実行する際に使用されているRoleにアタッチしてあげれば解決した。
Step FunctionsからECS RunTaskしようとしたら「ECS.AccessDeniedException」と出た時の対処法
EventBridge
EventBridgeの定期実行の設定は、今はスケジューラという箇所で設定できるようになっている(と最近知った)。
結果はCloudWatchLogsかStep Functionsで確認
下記はCloudWatchLogsで確認。Step Functionsの画面でも確認できるので、どちらも見ておくと良さそう。
まとめ
シンプルなECS TaskをStep Functionsで動かして、EventBridgeから呼び出す方法を書いた。
個人的には、Step FunctionsをEventBridgeから呼び出せるし、ECS Taskも実行できると知って、とても知識の手段が幅が広がったと感じてる。
適材適所で対応していきたい。
コメントを投稿するにはログインしてください。