この記事はフリューAdvent Calendar 2025の16日目の記事です!
こんにちは!フリューでピクトリンクというアプリの開発をおこなっている森兼と申します。
この記事では、ECSのインフラストラクチャメンテナンスイベント(AWS_ECS_TASK_PATCHING_RETIREMENT)によるタスク再起動をきっかけに、タスクイメージの運用を考える機会となった時のことをお話しします!
第一の事件
ある朝、AWSコンソールを確認すると、とあるECSタスクが夜中からずっと起動に失敗し続け、タスク数が0になっていました。検証用の環境であったため、サービス影響などはありませんが起動失敗ログが大量に並ぶ光景は肝が冷えます。
そもそもデプロイもしていないのに再起動が走るのは何故かと思ったら、AWS側のメンテナンスイベントによるタスクの再起動でした。
このメンテナンスイベントは、事前に手動で更新をかけなかった場合に、自動でタスクを再起動してくれるのですが、この再起動が失敗しつづけていたのでした。
原因
停止済みコンテナのエラーメッセージには「CannotPullContainerError」と書いてあり、該当タグのイメージをECRに探しに行くと、実際にそのイメージは存在していません。 いったいなぜ消えてしまったのか。原因はECRのライフサイクルポリシーでした。 *1
該当クラスターは検証用に複数サービスを構築しており、サービスで共有のECRリポジトリへプッシュが頻繁に行われていました。今回問題となったタスクはこのサービスの中では更新頻度が比較的少なく、古いイメージをそのまま使用していました。
そして、ECRのライフサイクルは該当イメージが使用中かどうかは考慮しません。結果、このタスクで使用している古いイメージがライフサイクルで指定した制限数から押し出され、削除されてしまい、ECSは再起動に失敗し続けていたのでした。
対策
ECRのライフサイクル機能と共存しながらこの問題を解決したい場合、ライフサイクルルールと開発者の運用ルールをきちんと紐づけるのが有効だと思います。
ライフサイクルルールではタグ名に対してパターンマッチングが使用できます。頻繁にプッシュする検証用イメージとstableなイメージのタグ名のパターンを分けることで、安定稼働させているタスクのイメージが押し出されるリスクは低くなります。
例
検証用: dev-*, test-* → 保持数を少なめに 安定版: stable-* → 保持数を多めに or ライフサイクル対象外
また、単純にAWS Health Eventにメンテナンス通知が来た時点で、先んじて手動でデプロイ&イメージ更新をするのも有効だと思います!
第二の事件
一方でこんなパターンもありました。該当イメージタグのイメージはECRにちゃんとあるのに、「Cannnot Pull Imageエラー」が出てしまうパターンです。
原因は、ECSの「ソフトウェアバージョンの一貫性機能」によって、同じイメージタグであっても、デプロイ時と違うダイジェスト値のイメージはPullしてくれないためでした。
原因
「ソフトウェアバージョンの一貫性機能」とは、最初のタスクデプロイ時にイメージの「イメージダイジェスト」という値を保存し、イメージタグ名ではなくダイジェスト値でイメージを参照する仕組みです。
このダイジェスト値はイメージのビルド時に、イメージの中身のチェックサムを使って生成します。これにより、イメージタグ名は同じだが内容が違うイメージでデプロイされることを防いでくれる機能となっています。
今回のパターンでは、使用中のイメージを同じイメージタグ名で上書きしてしまった結果、該当ダイジェスト値のイメージが消失してしまい、再起動に失敗していたのでした。
対策
まず、イメージタグのlatest運用をしているならやめるのが重要だと思います。
そしてできればイメージをイミュータブル設定にし、上書き不可にするのが良いと思います。しかし、単純に上書き不可にしてイメージのpush回数が増えると、前述のライフサイクルルール問題につながりやすくなります。
つまり、イメージタグの運用方法をきちんと整えてからイミュータブルにするのが重要です。
また、推奨はされませんが、イメージタグ名だけでイメージを参照する設定値も一応あるようです。
Amazon ECS でソフトウェアバージョンの一貫性が設定可能に - AWS
最後に
今回は特にECSのインフラストラクチャメンテナンスイベント起因のケースをお話ししましたが、この問題は手動でタスクを再起動しようとした場合や、オートスケールによっても発生します。
検証環境のイメージタグはついつい適当な名前をつけてしまいそうになりますが、これを機に一貫した命名を心がけていきたいと思いました。
*1:ECRに設定できるイメージの自動削除ルール。保持するイメージの数やプッシュされてからの日数で削除できる。イメージタグ名によるパターンマッチングなども設定できる。