AWS費用と残存imageの追跡記録

たかが1セント。
されど1セント。

Portfolioには2週間以上触っていない。それでもAWSの当月合計は、ある日1セント増えました。 請求の誤りではなく、残っていたECR imageの正しい保管料でした。その原因と、残存0件の判定が見逃していた範囲を特定し、安全に削除した記録です。

約10分 / 実地確認: 2026-08-23

追加操作がない期間の変化

触っていない。
なのに、増えた。

2026年8月、5回のデプロイ試行を終えた後、ポートフォリオのAWS環境には2週間以上追加操作をしていませんでした。 それでもCost Explorerの合計は $2.42 から $2.43 へ変わりました。

1セントなら誤差として流せます。しかし「操作していないのに増えた」は、片付けたつもりの何かが残っている可能性を示します。 調べた結果、AWSの請求は正しく、こちらの完了判定が一段だけ足りませんでした。

01¢

料金は正しかった。「残存0件」という完了判定の方を、もう一度疑う必要があった。

画面上の丸めと内部の正確な金額

約0.003ドル/日。
普通は、1日では見えない。

Cost Explorerの画面はセント単位でも、内部ではさらに細かい金額が積み上がります。 今回は初日の値が表示境界の直前だったため、偶然翌日に変化が見えました。

2桁表示の境界$0.035
8月20日 / 内部の正確な値 $0.034983709 画面表示 $0.03
8月21日 / 内部の正確な値 $0.038224803 画面表示 $0.04
1日あたりの増加$0.003241094
約3.09日
画面に見える変化約1セント

料金・操作履歴・現在の実体を照合

操作ではなく、
保管だった。

請求、操作履歴、現在の実体は別の記録です。一つの画面だけで結論を出さず、三つを照合しました。

01 / 料金 / Cost Explorer

保管料だけが積み上がった

ECRのusage typeはTimedStorage-ByteHrsのみ。データ転送や新しい実行料金ではありませんでした。

02 / 操作履歴 / CloudTrail

新しい書き込みはなかった

木曜から金曜の変化に対応するPutImageやBatchDeleteImageはなく、最後のECR書き込みはそれ以前でした。

03 / 現在の実体 / ECR inventory

9個のタグ付きイメージが残っていた

3つの永続リポジトリに、過去3世代のコンテナが同じ構成で残っていました。

2026年8月23日のAWS Cost Explorer。合計2.43ドルで、EC2 Container Registryは0.04ドル。 原寸で確認
2026年8月23日の観測 ECRの$0.04は、新しいデプロイではなく、残っていたイメージの保管料でした。

3 repository × 3世代の内訳

3サービス × 3世代。
合計9イメージ。

ここでいうimageはIAM Role、Policy、Quotaではありません。Web、API、MLを動かすDocker containerです。

ECRの3リポジトリに残っていた3世代、合計9コンテナイメージ
repository 世代 01issue110-0580ae23世代 02sha-860c4c9ac91d世代 03sha-a1bad6a7af7d
webWebアプリケーション tag付きimagetag付きimagetag付きimage
apiバックエンドAPI tag付きimagetag付きimagetag付きimage
mlMLサービス tag付きimagetag付きimagetag付きimage
自動削除条件 01tagなし / 7日後

9個はすべてタグ付きでした。この自動削除条件には入りません。

自動削除条件 02tag付き / 20個まで保持

各リポジトリは3個だけ。保持上限20を超えないため削除されません。

残す物と消す物の境界空のrepositoryは残し、imageは消す

次回も使う空の置き場は永続。実行ごとの中身は撤収対象です。

残存確認が見ていた範囲の抜け

今回のタグは消した。
過去タグは見ていなかった。

既存の残存確認は、その実行の config.image_tag が消えたことを正しく確認していました。 しかし、別の試行で残ったタグは問い合わせ対象に入っていませんでした。

修正前 / 今回の実行だけを確認
describe-images
  --repository-name exact-repository
  --image-ids imageTag=config.image_tag

今回のタグがなければ0。古いタグが同じリポジトリにあっても見えません。

修正後 / repository内をすべて確認
describe-images
  --repository-name exact-repository

repository内の全imageを数え、1個でもあれば「残存0件」と判定しません。

削除してよい範囲

消す範囲は、狭く。

今回のtag + 復旧記録のdigest

自分の実行が所有し、内容識別子(digest)まで一致したimageだけを削除します。

存在を確認する範囲

見る範囲は、広く。

指定した3 repository内の全image

不明な残存物を黙認せず、残存確認を失敗させて人の調査へ回します。

検知で止め、自動で全削除しない理由

なぜタグを外して、
全部消さないのか。

技術的に全削除できないからではありません。自動cleanupへ「この置き場にあるものは、所有元を問わず消してよい」という判断を持たせないためです。

01

別実行のイメージ

手動実行、月次実行、別の試行が同じ永続repositoryを使います。残ったtagの所有元を確認せず消すことはできません。

02

中断からの復旧

push後、復旧用の記録(checkpoint)を残す前に止まったimageは、再開時に正しい内容識別子(digest)として採用できる可能性があります。

03

再起動と再スケール

参照中のイメージを消せば、稼働中タスクが落ちなくても、次の起動やスケールアウトを壊し得ます。

04

失敗の証拠

不明なタグは、調査すべき異常そのものです。cleanupが先に消すと、原因を確かめる材料まで失います。

検知 全部見る。残っていれば止める。

削除 所有権を証明できるものだけ消す。

できないからではなく、させない。

対象を照合した一度限りの削除

9個を明示削除し、
0を読み返す。

既存の9個は、3 repositoryと3 tagが事前確認と完全一致した場合だけ、専用のdestroy Roleで削除しました。

reactorfront/web
30

imageの一覧 / 識別子

reactorfront/api
30

imageの一覧 / 識別子

reactorfront/ml
30

imageの一覧 / 識別子

合計
90

tag付き / tagなしの両方で残存なし

残したもの3つの空ECRリポジトリ

次回の月次検証でも使う永続管理基盤。

消したもの9つの実行イメージ

過去の試行で残った保管課金対象。

変わらないもの既計上の$2.43

累積実績は戻らず、将来の保管増加を止めます。

小さな金額から見つけた実際の抜け

たかが1セント。
されど1セント。

01

金額の大小と、異常の重要度を分ける。

1セントでも、説明できない変化なら確認する価値があります。

02

請求額を撤収完了の証拠にしない。

料金は遅れて反映され、画面では丸められます。実体の有無はservice APIで確認します。

03

自動化の観測範囲と削除範囲を分ける。

全部見つけても、全部を自動で消してよいとは限りません。

AWS検証の全工程へ戻る

1セントの入口から、
構築・E2E・撤収の全体へ。

IAM、Terraform、ECS、認証付きE2E、非常時の自動destroy。親記事では、この調査の前提となったAWS検証全体を、ML編ではモデルの評価・採用・復旧を解説しています。