Amazon ECRを安全に掃除する ecrm - fujiwara-ware 2024 day 16
この記事は fujiwara-ware advent calendar 2024 の16日目です。
ecrm とは
ecrm は、Amazon ECR (Elastic Container Registry) のリポジトリを安全に掃除するためのツールです。
なぜ作ったのか
Amazon ECR には、不要になったイメージを削除するためにライフサイクルポリシーを設定できます。ライフサイクルポリシーは、タグ付けされたイメージを一定期間で削除するためのルールです。
しかし、これを運用していて事故ったことがあります。ライフサイクルポリシーでは最新から数世代分タグのイメージを削除しないように保護していたのですが、とある ECS サービスのタスクが、古いイメージタグを参照し続けていたのです。
このプロジェクトでは、複数の ECS サービス(A, B)からおなじ ECR のイメージを参照していました。どんどんデプロイされているサービス(A)は最新のタグを参照するのですが、サービス(B)はあまりデプロイされないため、古いタグを参照し続けていました。そのため、ライフサイクルポリシーによって古いイメージが削除された結果、サービス B が動かなくなってしまいました。
このような事故を防ぐために、ecrm を作りました。
動作原理
ecrm はイメージを削除する前に、AWS アカウント内のリソースをスキャンします。
- Amazon ECS のタスク定義、サービス、実行中のタスク
- AWS Lambda 関数が参照しているイメージ
これらに指定されている(最新N世代の)イメージは、削除しないように保護されます。それ以外で push から一定期間が経過したイメージを削除します。
このような仕組みにより、まだ使っているイメージは削除せず、不要なイメージのみを安全に掃除することができます。
使い方
詳しくは README を参照してください。
設定ファイルを生成する
他の fujiwara-ware と同様に、設定ファイルを自動生成する機能があります。
ecrm generate
を実行すると、AWS アカウント上のリソース(ECR, ECS, Lambda)を検索し、自動的に設定ファイルを生成します。
生成されたファイルはリソース名の prefix などを元に適当にグルーピングされていますが、必要に応じて手動で編集してください。
# ecrm.yaml
clusters:
- name: my-cluster
- name_pattern: "prod*"
- name_pattern: "dev*"
task_definitions:
- name: "*"
keep_count: 3
lambda_functions:
- name: "*"
keep_count: 3
repositories:
- name_pattern: "prod/*"
expires: 90days
keep_tag_patterns:
- latest
- name_pattern: "dev/*"
expires: 30days
削除予定のイメージを表示する
ecrm plan
を実行すると、削除予定のイメージを表示します。
$ ecrm plan
REPOSITORY | TOTAL | EXPIRED | KEEP
-----------------------+--------------+---------------+--------------
dev/app | 732 (594 GB) | -707 (574 GB) | 25 (21 GB)
dev/nginx | 720 (28 GB) | -697 (27 GB) | 23 (875 MB)
prod/app | 97 (80 GB) | -87 (72 GB) | 10 (8.4 GB)
prod/nginx | 95 (3.7 GB) | -85 (3.3 GB) | 10 (381 MB)
ここで表示される EXPIRED
は削除予定のイメージ数です。KEEP
は削除しないイメージ数です。GB はイメージのサイズですが、これは単にイメージサイズの合計です。実際のコンテナレジストリ上ではイメージ間で重複したレイヤーを共有しているため、実際に削除されるサイズはこれよりも(かなり)小さくなることがあります。
削除する
ecrm delete
を実行すると、実際にイメージを削除します。
複数アカウントや ECS, Lambda 以外への対応
ecrm は、デフォルトでは1つのアカウント内での ECR のリポジトリを対象としますが、次のような使い方で複数アカウントに対応できます。
- AWS アカウント A で
ecrm scan --output a.json
を実行して保護対象をファイルに保存 - AWS アカウント B で
ecrm delete --scanned-files a.json
を実行して、アカウント A で保護したいイメージ以外を削除
このようにすることで、異なるアカウント間で ECR のリポジトリを安全に掃除することができます。また、ecrm delete
では複数のファイルを指定することができるため、複数のアカウントで利用中のイメージを全て保護した上で削除することもできます。
ecrm scan
が出力するのは以下のような JSON ファイルです。
[
"012345678901.dkr.ecr.ap-northeast-1.amazonaws.com/foo/bar:latest",
"012345678901.dkr.ecr.ap-northeast-1.amazonaws.com/foo/bar@sha256:abcdef1234567890..."
]
ecrm が対応していないサービスで使っているイメージを保護したい場合 (例えば Amazon EKS や AWS AppRunner など)、なんらかの手段でこの形式の JSON を生成して ecrm delete --scanned-files
に渡すことで、そのイメージを保護しつつ掃除することができます。
まとめ
ecrm は、Amazon ECR のリポジトリを安全に掃除するためのツールです。不要なイメージを削除する際に、まだ使われているイメージを削除しないように保護します。
複雑な運用をしていてライフサイクルポリシーでは不十分な場合に、ecrm を使って安全に掃除しましょう。
それでは、明日もお楽しみに!
参考資料
Discussion