CloudWatch Eventスケジュール式(cron式)をトリガーにECSでタスクを起動するよう設定していたのだが、なぜかまれにタスクが同時に2個起動することがある。エラーが起きたからリトライされたというわけではなく、タスクは2個とも正常終了した。
CloudWatch Eventはそういうもので、ちょうど1回だけ起動することを保証していないとAWSドキュメントに書いてある。
1 つのイベントに応じてルールが複数回トリガーされました。CloudWatch イベント で、ルールのトリガーまたはターゲットへのイベントの提供で何が保証されますか。
まれに、単一のイベントまたはスケジュールされた期間に対して同じルールを複数回トリガーしたり、特定のトリガーされたルールに対して同じターゲットを複数回起動したりする場合があります。
CloudWatch イベント のトラブルシューティング
Lambdaでも同様にCloudWatch Eventスケジュール式をトリガーにしていると多重起動することがあるらしい。Lambdaの場合は同期実行数を1に設定しておけばよいと思いきや、それでもダメ。1つの Lambda 関数が起動して終了した後に、もう1つの Lambda 関数が起動してくる可能性があるため。
Lambda 関数の同時実行数を1にしても冪等性の担保から逃れることは出来ない | by noid11 | Medium
多重起動を防ぎたければ、DynamoDBを使ってロックを実装するのが良いらしい。ロックを解除しないままエラー終了してしまうと、ロックが残ったままになるので、DynamoDBテーブルにTTLを設定して、一定時間後に自動的に削除される(=ロック解除される)ようにしておくと良いかもしれない。TTLは指定時刻ピッタリでなく、最大48時間以内に削除されるという仕様だが…
【小ネタ】 DynamoDBのTTLで一部だけ無期限にしたい時は0でOK - Qiita
酷い話だ。
追記:
DynamoDBを使ってロックを実装しても、1個目のタスクが1分で終了してから2個目のタスクが起動されたことがあった。これはロックでは防げない…