🧹

Amazon ECRを安全に掃除する ecrm - fujiwara-ware 2024 day 16

2024/12/16に公開

この記事は fujiwara-ware advent calendar 2024 の16日目です。

ecrm とは

https://github.com/fujiwara/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 のリポジトリを対象としますが、次のような使い方で複数アカウントに対応できます。

  1. AWS アカウント A で ecrm scan --output a.json を実行して保護対象をファイルに保存
  2. 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 を使って安全に掃除しましょう。

それでは、明日もお楽しみに!

参考資料

https://techblog.kayac.com/ecrm-oss

Discussion