概要
- ECSで定時バッチを実行するのにはEventBridgeが使える
- EventBridgeからECSを直接呼び出すとECSタスク起動失敗を把握できないときがある
- 確実にやるならStepFunctionsを使おう
ECSで定時バッチを実行する
実行するときだけECSタスクを起動したい理由
- コストを抑えたい
- 不要な監視対象を作りたくない
- 稼働中のアプリケーションサーバと別にすることで負荷を減らしたい
- etc.
ECSタスクスケジューリング機能を使う
cronなどを設定して定期的なECSタスク実行ができる機能が既にある。
実行時間の設定とターゲットとなるECSタスクのタスク定義などを設定するだけで定時バッチが組める優れもの。
EventBridgeを使うときの罠
EventBridgeから直接ECSタスクをターゲットにする流れは以下のとおり。
EventBridgeによるECS起動呼び出し後のECSエラーについてEventBridgeは責任を持たないという罠がある。
以下の記事も参考されたし。
スケジュールされたタスクは、EventBridge ルールをトリガーに RunTask API によって起動されます。RunTask API の実行に失敗した場合、EventBridge の再試行ポリシーに従いリトライが行われますが、RunTask API はタスクの開始が行われた時点で正常実行として終了します。
ECSタスク起動自体の失敗が実際に発生すると、ECSタスクの異常系ログ監視では気がつけないので非常に厄介。
さらにEventBridgeからリトライもやりにくい。
StepFunctionsはいいぞ
前述の記事でも紹介されているStepFunctionsを噛ませる流れは以下のとおり。
ちなみに複数のバッチそれぞれにタスク定義を作るのではなく、バッチ用の共通タスク定義に各バッチのコマンドを上書きしている。
StepFunctionsはEventBridgeと違い、ECSタスクが突然の死を迎えた時にもエラーとして扱う。
EventBridgeからStepFunctionsの呼び出しは失敗するのか
サポートに確認した。
はい。なんらかの影響により失敗する可能性はございます。
再試行ポリシー[1]がございますので、こちらの内容をご確認いただきますようお願いいたします。
---[1]関連部位抜粋---
ルールで指定されたターゲットにイベントが正常に配信されないことがあります。
例えば、ターゲットリソースが使用できない場合や、EventBridge にターゲットリソースへのアクセス許可がない場合、またはネットワーク状態が原因で発生します。
再試行可能なエラーのためにイベントがターゲットに正常に配信されない場合、EventBridge はイベントの送信を再試行します。
ECSタスクを直で起動するときのような罠はないらしい。
また、失敗した場合には、ドキュメント[1]記載のとおりメトリクス[2]で確認可能でございます。
バッチの数が多くなったときのために、 FailedInvocations
のメトリクスを監視するとより完璧に近づくと思う。
ECSタスクからCloudWatch Logsへのログの転送遅延について(追記)
この構成で実装したところ、ECSタスクは問題なく実行されたのにLambdaで成功ログを見つけられないエラーが発生した。
考えられる原因はLambda関数の不具合かECSタスクからログ転送の遅延が考えられ、今回は後者の可能性があると踏んでサポートに問い合わせてみた。
ECS タスク を確認したところ基盤側には問題がなく、またネットワーク疎通に関する問題も確認できませんでした。
一方で、実際には CloudWatch Logs へのログ反映が遅くなっていた事象が発生しております。
原因を明確に特定できずに恐れ入りますが、状況からはログの送信が遅延していた可能性が考えられるものとなります。
ログはネットワークを経由して送信するものとなりますため、遅延は発生しうるものとなります。
ここで SLA のような形で規定秒数以内に送信完了することは保証されておらず、具体的にどの程度の遅延となるかの情報は公開されていないため、遅延内容に関する具体的な内容をご案内することが叶わず恐れ入ります。
とのことなので、手っ取り早く解決したい為今回はLambda関数の呼び出し前にWait処理を入れることで回避することにした。