Kubernetesノードのお掃除屋さんEraserを使ってみよう

こんにちは！今回はKubernetesクラスタのノード上に蓄積された**不要なコンテナイメージ**をクリーンアップしてくれるツール、**Eraser**についてご紹介します。Kubernetes中級者向けに、カジュアルな雰囲気でEraserの概要から導入方法、ユースケース、内部アーキテクチャ、実際の動かし方まで解説していきます。Eraserって便利ですよね！それでは早速見ていきましょう。

## 1. Eraserとは何か

**Eraser**とは、Kubernetesクラスタ内の各ノードに残っている未使用のコンテナイメージを自動的に削除してくれるオープンソースのツールです ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=Eraser%20is%20an%20open,images%20run%20on%20your%20nodes))。CNCF（Cloud Native Computing Foundation）のサンドボックスプロジェクトとして登場し、主に**「非稼働（non-running）のコンテナイメージ」**を一覧に基づいてクラスター全体から綺麗に消し去ってくれます ([Eraser | CNCF](https://www.cncf.io/projects/eraser/#:~:text=Eraser%20uses%20vulnerability%20data%20to,Kubernetes%20nodes%20in%20a%20cluster))。要するに、クラスターの**お掃除屋さん**ですね。

では、なぜこんなツールが必要なのでしょうか？KubernetesではPodをデプロイすると、そのイメージが各ノードにプルされます。しかしPodを削除した後も、その**イメージ自体はノード上に残り続ける**ことがあります。クラスターを長く運用していると、このような**使われていない古いイメージ**がどんどん蓄積してしまいがちです。これにはいくつか問題点があります:

- **ストレージ容量の圧迫**: 不要なイメージが増えるとディスク容量を消費し、ノードのストレージが圧迫されます ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=,by%20reducing%20the%20storage%20requirements))。特に大規模クラスターや長期間稼働している環境では馬鹿になりません。
- **パフォーマンスへの影響**: イメージが山積みになると、クラスターのパフォーマンスにも悪影響があります ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=,by%20reducing%20the%20storage%20requirements))。たとえば、新しいPod起動時にイメージキャッシュの管理に時間がかかったり、Kubernetesのガベージコレクション処理が頻繁に走ってしまうことがあります。
- **セキュリティリスク**: 古いイメージには既知の脆弱性が含まれている可能性があります ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=,by%20reducing%20the%20storage%20requirements))。そうした脆弱なイメージがノード上に残っていると、万一それが再度使われてしまった場合にセキュリティ上のリスクとなり得ます。

こうした問題を解決するために生まれたのがEraserです。Eraserは**脆弱だったり不要になったコンテナイメージ**を検出してクラスターから自動削除してくれるので、クラスターノードの状態を常にクリーンかつ安全に保つことができます ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=Eraser%20is%20an%20open,images%20run%20on%20your%20nodes))。いわばKubernetesノードの「掃除機」のような役割を果たしてくれるわけですね。

## 2. Eraserの導入方法

では実際にEraserを使ってみましょう！まずはクラスターへの導入方法です。EraserはKubernetesのカスタムリソース定義（CRD）としてインストールします ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=1,to%20receive%20alerts%20and%20notifications))。方法は大きく分けて2通りあります: **kubectlを使う方法**と**Helmを使う方法**です。

### kubectlでインストールする

一番手軽なのは、公式が提供するマニフェストをkubectlで適用する方法です。以下のコマンド一発で、CRDやコントローラなどEraserに必要なリソースがクラスターにデプロイされます。

```bash
# Eraserをマニフェストからインストール
kubectl apply -f https://raw.githubusercontent.com/eraser-dev/eraser/v1.4.0/deploy/eraser.yaml
```

※バージョンは執筆時点（v1.4.0）の例です。最新のリリースに応じてURL中のバージョン番号を変更してください ([Installation | Eraser Docs](https://eraser-dev.github.io/eraser/docs/installation#:~:text=To%20install%20Eraser%20with%20the,file%2C%20run%20the%20following%20command))。

上記コマンドを実行すると、`eraser-system`というNamespaceにEraserのコントローラがデプロイされ、必要なCRD（後述するImageListやImageJobなど）が登録されます。`kubectl get pods -n eraser-system`でコントローラが立ち上がっているか確認してみましょう。`eraser-controller-manager-xxxxx`というPodが**Running**状態になっていればOKです。

### Helmでインストールする

Helm愛好者の方は、Helm Chartを使ってインストールすることもできます。EraserのHelmチャートは公式で提供されています。以下の手順でリポジトリを追加し、インストールしましょう。

```bash
# Eraser Helmリポジトリを追加
helm repo add eraser https://eraser-dev.github.io/eraser/charts
helm repo update

# Eraserをインストール（リリース名は eraser とし、Namespace は eraser-system）
helm install eraser eraser/eraser -n eraser-system --create-namespace
```

Helmでインストールすると、今後のアップグレードや設定変更もHelmで一元管理できる利点があります。内部的には先ほどのマニフェストと同じリソースが作成されます ([eraser/charts/eraser/README.md at main · eraser-dev/eraser · GitHub](https://github.com/eraser-dev/eraser/blob/main/charts/eraser/README.md#:~:text=helm%20repo%20add%20eraser%20https%3A%2F%2Feraser,helm%20repo%20update))。

いずれの方法でもインストール後は、`eraser-system` NamespaceにEraserのコントローラ（コントローラマネージャ）が動作します。また、Eraser用のConfigMap（設定用）やCRDが出来上がっているはずです。デフォルト設定では**24時間に1回**の間隔でクリーンアップ処理が実行されるようになっています ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=After%20deploying%20Eraser%2C%20it%20will,h))（後述のArchitectureセクションで詳しく説明します）。

## 3. Eraserのユースケース

Eraserがどんな場面で役立つか、具体的なユースケースを見てみましょう。「不要なコンテナイメージの自動削除」というシンプルな機能ですが、実はいろいろなシナリオでクラスタ管理者を助けてくれます。

- **CI/CD環境でのクリーンアップ**: ビルドやデプロイを繰り返すCI/CDパイプラインでは、新しいイメージが次々にノードにPullされ、古いイメージが溜まりがちです。Eraserを導入すれば、使われなくなった古いイメージを自動的に検出・削除してくれるので、クラスターのノードは常に軽快な状態を保てます。ディスクスペースを自動で解放してくれるので、「ノードのディスクがいつの間にか満杯！」なんて事態を防げます ([ Enhancing Container Security: The Complete Guide to Secure and Clean Kubernetes Clusters ️ - DEV Community](https://dev.to/hkhelil/enhancing-container-security-the-complete-guide-to-secure-and-clean-kubernetes-clusters-1ida#:~:text=Over%20time%2C%20nodes%20in%20AKS,are%20no%20longer%20in%20use))。

- **セキュリティとコンプライアンスの強化**: セキュリティポリシー上、脆弱性のあるイメージや社内で許可されていないイメージをクラスター上に残さないようにしたい場合があります。Eraserはイメージのスキャン機能（後述）によって**脆弱なイメージ**や**ポリシーに適合しないイメージ**を検出し、自動的に削除できます ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=,retained%20while%20others%20are%20deleted))。例えば、「一定期間以上更新されていない古いイメージは削除する」ポリシーや「社内プライベートレジストリ以外からPullされたイメージは削除する」といったルールを適用することで、クラスタ内のコンテナイメージを常にセキュアかつポリシー準拠な状態に保てます。

- **マルチテナント環境のメンテナンス**: 複数のチームやアプリケーションが混在するクラスターでは、各チームがデプロイ・削除を繰り返すうちに、誰も使っていないイメージが大量に残留することがあります。Eraserはクラスター全体で未使用イメージを一括クリーンアップしてくれるので、マルチテナント環境のガバナンスにも有効です。他チームの古いイメージが自分たちのノードリソースを圧迫する、といった心配も減ります。

- **リソース制約のある環境での利用**: エッジ環境や学習用途の小規模クラスターなど、ノードのリソース（特にディスク）が限られている場合にもEraserは有用です。例えば学生や個人で試すKubernetesクラスタでは、ストレージ容量が潤沢でないことも多いでしょう。Eraserが自動で定期的にお掃除してくれることで、限られたリソースを有効活用できます ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=,by%20reducing%20the%20storage%20requirements))。

このように、Eraserは**クラスターの衛生管理役**として様々な場面で活躍します。「ノードのディスクをスッキリ保ちたい」「古く危険なイメージを残したくない」といったケースでは導入を検討する価値大です。

## 4. Eraserの内部アーキテクチャ

Eraserが裏側でどのように動作しているのか、そのアーキテクチャをざっくり理解しておきましょう。中級者であれば、内部の仕組みも押さえておくとトラブルシューティングの際に役立ちます。

### コンポーネント概要

EraserはKubernetesのカスタムコントローラ（オペレーター）の一種で、以下の主要コンポーネントで構成されています:

- **Eraserコントローラ（コントローラマネージャ）**: `eraser-system` Namespaceで動作するデプロイメントです。Eraser専用のCRDリソース（後述のImageListやImageJob）を監視し、必要に応じてクリーンアップ用のジョブ（Pod）を各ノードにスケジューリングします。いわばEraser全体の司令塔です。

- **ImageList リソース（CRD）**: 削除すべきコンテナイメージの一覧を表すカスタムリソースです。`eraser.sh/v1alpha1` APIグループで定義されており、`ImageList`というKindを持ちます。手動で特定のイメージを削除したい場合、このImageListリソースに対象イメージ名を列挙して作成します。特殊な指定として `"*"`（アスタリスク）を使うと「非稼働の全イメージ」を意味し、一括削除が可能です ([Manual Removal | Eraser Docs](https://eraser-dev.github.io/eraser/docs/manual-removal#:~:text=cat%20,running%20images)) ([Manual Removal | Eraser Docs](https://eraser-dev.github.io/eraser/docs/manual-removal#:~:text=%3E%20%60ImageList%60%20is%20a%20cluster,images%20instead%20of%20individual%20images))。

- **ImageJob リソース（CRD）**: クリーンアップ作業の実行ジョブを表すリソースです。ImageListを作成した際や、自動スキャンのスケジュールが来た際にEraserコントローラによって生成されます。このImageJobに基づき、各ノードで実行されるEraser Podが作られます。

- **Eraser Pod（エージェント）**: 実際にノード上でイメージ削除を行うPodです。クリーンアップ対象の各ノードに1つずつスケジューリングされます。内部には最大で3つのコンテナが含まれており、それぞれ**Collector（収集）、Scanner（スキャン）、Remover（削除）**の役割を担います ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=Eraser%20will%20schedule%20eraser%20pods,that%20will%20run%20to%20completion))。各コンテナは以下のように協調動作します ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=The%20collector%20container%20sends%20the,will%20be%20automatically%20cleaned%20up)):
  - **Collectorコンテナ**: ノード上に存在する全てのコンテナイメージのリストを収集します。具体的にはCRI（Container Runtime Interface）を通じて`ListImages`や`ListContainers`といったAPIを呼び出し、そのノードにあるイメージ一覧や現在稼働中のコンテナ情報を取得します。これにより「非稼働（未使用）のイメージ」がどれかを洗い出します。
  - **Scannerコンテナ**: Collectorから受け取ったイメージ一覧に対し、セキュリティスキャンやポリシーチェックを実行します。デフォルトでは有名な脆弱性スキャナである**Trivy**が使われ、各イメージに既知の脆弱性がないかチェックされます ([Architecture | Eraser Docs](https://eraser-dev.github.io/eraser/docs/architecture#:~:text=Automated%20image%20removal%20runs%20on,running%20images%20in%20your%20cluster))。スキャン結果にもとづき、「**ポリシーに非準拠（non-compliant）なイメージ**」を判定します。例えば深刻な脆弱性を含むイメージや、組織で許可されていないレジストリ由来のイメージなどが該当します。
  - **Removerコンテナ**: Scannerによって「削除対象」とマークされたイメージを、ノードから実際に削除する役割です。CRIの`RemoveImage`APIを用いてイメージデータをクリーンアップします。ただし**現在稼働中のコンテナが使用しているイメージは削除しません**。Removerはあくまで「非稼働のイメージ」のみを対象にします ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=The%20collector%20container%20sends%20the,will%20be%20automatically%20cleaned%20up))。これにより、動いているPodへの影響は避けつつ、不要なデータだけを消去します。

Eraser Pod上のこれらのコンテナは**Jobのように完了するまで実行**され、全コンテナが処理を終えるとPod自体は**Completed（完了）状態**になります ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start))。各ノードのEraser Podが完了すると、それらは自動的にクリーンアップ（削除）されます ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=The%20collector%20container%20sends%20the,will%20be%20automatically%20cleaned%20up))。つまり、お掃除のために使ったPod自身も後始末され、後にリソースを残しません。

### 動作モード: 自動 vs 手動

Eraserには大きく**自動モード**と**手動モード**の2つの動作モードがあります ([Architecture | Eraser Docs](https://eraser-dev.github.io/eraser/docs/architecture#:~:text=At%20a%20high%20level%2C%20Eraser,of%20operation%3A%20manual%20and%20automated))。

- **自動モード（定期クリーンアップ）**: **一定間隔で自動的にイメージのスキャン＆クリーンアップを行うモード**です。インストール直後のデフォルト設定では24時間ごとに実行されます ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=After%20deploying%20Eraser%2C%20it%20will,h))。Eraserコントローラ内のスケジューラ（ImageCollector Controller）がタイマーに従ってImageJobを作成し、各ノードにEraser Podを起動します。先述のようにデフォルトでは**脆弱性スキャンを有効**にした状態で動作し、**脆弱だと判定された未使用イメージのみ**を削除します ([Architecture | Eraser Docs](https://eraser-dev.github.io/eraser/docs/architecture#:~:text=Automated%20image%20removal%20runs%20on,running%20images%20in%20your%20cluster))。もしスキャンを無効化した場合（後述の設定で可能です）、全ての未使用イメージをガベージコレクションする動きになります ([Architecture | Eraser Docs](https://eraser-dev.github.io/eraser/docs/architecture#:~:text=Automated%20image%20removal%20runs%20on,running%20images%20in%20your%20cluster))。自動モードでは基本的に人手を介さず、クラスターを**継続的にクリーンな状態**に維持してくれます ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=Once%20Eraser%20is%20installed%20and,removes%20them%20from%20the%20nodes))。

- **手動モード（オンデマンドクリーンアップ）**: 特定のタイミングで明示的にクリーンアップを走らせたい場合や、削除対象のイメージを自分で指定したい場合はこちらです。ユーザーが**ImageList**リソースを作成・適用することでトリガーします ([Manual Removal | Eraser Docs](https://eraser-dev.github.io/eraser/docs/manual-removal#:~:text=Creating%20an%20,given%20the%20list%20of%20images))。ImageListのspecに削除したいイメージのリスト（例: `"docker.io/library/alpine:3.7.3"` など）や、`"*"`（全未使用イメージ一括）を指定しておくと、Eraserコントローラがそれを検知して対応するImageJobを生成し、各ノードでクリーンアップPodを動かします ([Manual Removal | Eraser Docs](https://eraser-dev.github.io/eraser/docs/manual-removal#:~:text=%3E%20%60ImageList%60%20is%20a%20cluster,images%20instead%20of%20individual%20images))。手動モードではScannerコンテナの有無に関係なく、**指定されたイメージ**（もしくは全未使用イメージ）が対象となります。例えば緊急で「◯◯というイメージだけ削除したい」というときに便利です。

### 連携する仕組みと設定

Eraserはいくつか**設定可能なコンフィグ**や**Kubernetesの仕組み**との連携ポイントがあります。

- **ConfigMapによる設定**: Eraserの動作間隔やコンポーネント有効/無効は、`eraser-system` NamespaceにあるEraser用のConfigMapで管理されます。前述の**実行間隔（repeatInterval）**もその一つで、デフォルトは`24h`ですがこの値を変更すれば好きな周期で自動クリーンアップが走るようになります ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=After%20deploying%20Eraser%2C%20it%20will,h))。また**Scannerコンテナの有効/無効**も設定可能で、例えば`components.scanner.enabled=false`とすれば脆弱性スキャンをスキップして全未使用イメージを削除する**シンプルなGCモード**に切り替えられます ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=be%20automatically%20cleaned%20up))。

- **除外リスト（Exclude List）**: すべてのイメージを無差別に消すわけにはいかない場合もありますよね。例えば「この特定のレジストリのイメージは多少未使用でも残しておきたい」などのケースです。そのためにEraserは**除外対象**を指定する機能も備えています。`eraser-system` Namespaceに特定のラベル付きConfigMapを作成し、JSON形式で除外したいイメージパターンを列挙しておくことで、クリーンアップから除外できます ([Exclusion | Eraser Docs](https://eraser-dev.github.io/eraser/docs/exclusion#:~:text=Eraser%20can%20exclude%20registries%20,from%20its%20removal%20process))。例えば以下のようにConfigMapを作れば、`docker.io/library/*`（Docker Hubのlibrary配下全て）や特定のイメージタグを除外可能です ([Exclusion | Eraser Docs](https://eraser-dev.github.io/eraser/docs/exclusion#:~:text=Eraser%20can%20exclude%20registries%20,from%20its%20removal%20process))。

  ```json
  {
    "excluded": [
      "docker.io/library/*",
      "ghcr.io/eraser-dev/test:latest"
    ]
  }
  ```
  ```bash
  kubectl create configmap eraser-exclusion --from-file=excluded-images.json -n eraser-system
  kubectl label configmap eraser-exclusion eraser.sh/exclude.list=true -n eraser-system
  ```

  こうしておけば、除外リストにマッチするイメージはたとえ未使用でもEraserによって削除されなくなります。

- **ノード除外/対象指定**: クラスター内の一部ノードではイメージを消したくない、といった場合もあるでしょう。Eraserはv1.0.0以降、特定ノードをクリーンアップ対象から**含めたり除外したり**する設定もサポートしています ([Exclusion | Eraser Docs](https://eraser-dev.github.io/eraser/docs/exclusion#:~:text=Exempting%20Nodes%20from%20the%20Eraser,Pipeline))。これもConfigMap経由の設定で、「特定ノード名を除外」あるいは逆に「このリストのノードにのみ適用」という形で柔軟に指定できます ([Exclusion | Eraser Docs](https://eraser-dev.github.io/eraser/docs/exclusion#:~:text=Exempting%20Nodes%20from%20the%20Eraser,Pipeline))。たとえばノードラベルや名前を使って「デプロイ専用ノードは除外」等の運用も可能です。

内部アーキテクチャの話は少し専門的になりましたが、要するにEraserは**Kubernetesの拡張機能**として、独自のCRDとコントローラ、そしてノード上で動くエージェントPodたちによって構成されているということです。Collector・Scanner・Removerという3段構えで「収集→判定→削除」を行い、クラスターから不要イメージを一掃してくれる仕組みになっています。

## 5. 実践：Eraserの動作確認

それでは実際にEraserを動かしてみましょう！「百聞は一見にしかず」ということで、簡単なデモを通じてEraserの働きを確認してみます。ここでは手動で不要イメージを発生させて、それをEraserでクリーンアップする一連の流れを試します。実際に動かしてみましょう！

**ステップ1: 不要なイメージの発生**  
まずは意図的にノード上に未使用イメージを作ってみます。手っ取り早い方法として、短命なPodを起動してすぐ消すという手があります。例えばAlpine 3.7.3というイメージを使ったPodをデプロイし、すぐ終了させてみましょう（Alpine 3.7.3は脆弱性がある古いイメージなのでデモに最適です）。

```bash
# 脆弱性のある古いAlpineイメージを使ったPodを起動
kubectl run test-alpine --image=docker.io/library/alpine:3.7.3 --command -- sleep 5
```

上記コマンドで`test-alpine`というPodを起動します。このPodは5秒間スリープした後に終了します。5秒ほど待ってからPodの状態を確認すると、`Completed`になっているはずです。

```bash
$ kubectl get pod test-alpine
NAME           READY   STATUS      RESTARTS   AGE
test-alpine    0/1     Completed   0          10s
```

PodがCompletedあるいは削除済みであれば、**Alpine:3.7.3のイメージだけがノード上に残った状態**になっています。これが「未使用イメージがノードに残っている」状況です。

**ステップ2: Eraserで未使用イメージをクリーンアップ**  
次に、この残ったAlpineイメージをEraserに掃除してもらいましょう！Eraserコントローラが監視するImageListリソースを作成して、削除対象のイメージを指定します。先ほどのPodで使った`docker.io/library/alpine:3.7.3`を対象に指定してみます。

```bash
# 削除対象イメージのリストをCRDとして適用
cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1alpha1
kind: ImageList
metadata:
  name: imagelist                                # 名前は必ず "imagelist"
spec:
  images:
    - docker.io/library/alpine:3.7.3             # 削除したいイメージ
EOF
```

`ImageList`リソースを作成すると、Eraserのコントローラがそれを検知して内部で**ImageJob**を生成し、各ノードでEraser Podのデプロイが始まります ([Manual Removal | Eraser Docs](https://eraser-dev.github.io/eraser/docs/manual-removal#:~:text=%3E%20%60ImageList%60%20is%20a%20cluster,images%20instead%20of%20individual%20images))。数秒待ってからEraserのPodを確認してみましょう。

```bash
$ kubectl get pods -n eraser-system
NAME                                READY   STATUS      AGE
eraser-controller-manager-xxxxx     1/1     Running     5m
eraser-worker-node1-yyyyy           0/1     Completed   10s
eraser-worker-node2-zzzzz           0/1     Completed   10s
```

上記は2ノード（`worker-node1`と`worker-node2`）の例ですが、各ノード名が入ったEraser Podが**Completed（0/1 Completed）**となっているのが分かります。今回は手動モードでScannerコンテナを使わず1コンテナ（Remover）のみのPodが動いたため、各Podの`READY`列は`0/1`となっています ([Manual Removal | Eraser Docs](https://eraser-dev.github.io/eraser/docs/manual-removal#:~:text=%24%20kubectl%20get%20pods%20,0%2F1))（コンテナが完了するとPodもCompletedになるため）。この状態になれば、対象のAlpineイメージは各ノードから削除済みです。

**ステップ3: 削除結果の確認**  
では本当にイメージが消えたか確認してみましょう。確認方法はいくつかありますが、例えばノード上で直接コンテナランタイムのコマンドを実行してみます。Docker系なら`docker images`, containerdなら`ctr images list`などでイメージ一覧を見られます。ここではKind（containerdベース）のクラスタを想定して、先ほどイメージが存在したノードで`ctr`コマンドを実行してみた結果を示します。

```bash
# kind環境のノードコンテナ上での実行例（ノード名は適宜読み替えてください）
docker exec kind-worker ctr -n k8s.io images list | grep alpine
```

もしEraserが正しく機能していれば、上記コマンドで`docker.io/library/alpine:3.7.3`が表示されないはずです。つまりノード上からAlpine:3.7.3のエントリが消えていればOKです。加えて、EraserのImageListリソースにも実行結果が記録されています。`kubectl describe imagelist imagelist`でカスタムリソースの詳細を見ると、各ノードでの成功/失敗数やタイムスタンプが`Status`欄に更新されているはずです ([Manual Removal | Eraser Docs](https://eraser-dev.github.io/eraser/docs/manual-removal#:~:text=Status%3A%20Failed%3A%20%20%20,25T23%3A41%3A55Z))。成功ノード数が総ノード数と一致していれば全ノードでクリーンアップ成功です。

最後に、EraserコントローラのログやEraser Podのログにも動作の詳細が出力されています。興味があれば`kubectl logs -n eraser-system eraser-controller-manager-XXXXX`や各Completed Podのログを確認してみましょう。削除したイメージの名前などが出力されているので、「ちゃんと動いてるね」と安心できます。

## 6. まとめ

いかがでしたでしょうか？Eraserを使うことで、Kubernetesノード上に蓄積する不要なコンテナイメージを自動でクリーンアップし、**クラスターの健全性とセキュリティを向上**させられることがお分かりいただけたと思います。

**Eraserの利点**はたくさんあります。まず、人手によるノードメンテナンスを減らし、**自動化による安心感**を得られます ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=,custom%20scripts%20or%20plugins%20to))。「いつの間にかディスクがいっぱい」「古いイメージが放置されて脆弱性が…」といった事態を防ぐ保険になるでしょう。また、ポリシーベースで削除対象をコントロールできるため、クラスターごとのセキュリティポリシーや運用ルールに沿った柔軟な管理が可能です ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=on%20your%20cluster%27s%20needs.%20,process%20to%20your%20specific%20requirements))。加えて、削除のたびに詳細なログやメトリクスが残るので、あとから**監査やトレース**もでき、安心です ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=,activities%2C%20providing%20transparency%20and%20traceability))。

一方で導入にあたっての**注意点**もあります。Eraserは未使用イメージを消すので、例えば「すぐに再利用する予定のイメージ」まで消してしまう可能性があります。たとえばスケールダウンしたDeploymentのイメージが削除されると、次回スケールアップ時に再Pullが発生します。しかしこの点はトレードオフで、ディスク節約と引き換えに再Pullのオーバーヘッドが発生することになります。運用上問題ないか確認しつつ導入しましょう（必要に応じて特定イメージを除外リストに入れることもできます）。また、Eraser自身が定期的に各ノードでジョブを動かすため、**ごくわずかながらノード上でのリソース消費**（CPU/メモリや、イメージ削除時のストレージI/O）が発生します。通常は無視できる程度ですが、大規模環境ではスケジュール間隔を調整するなど配慮しても良いでしょう。

総合的に見て、Eraserは**CI/CDが活発な環境**や**長期稼働しているプロダクションクラスタ**、**セキュリティ重視の組織**で特に有用なツールです。これらのケースでは導入するメリットが大きいでしょう。一方、クラスターが小規模でイメージがほとんど変化しないような場合には、既存のKubernetesのガベージコレクション機能でも足りるかもしれません。しかし将来的にクラスターが成長したときのために、Eraserの存在を頭の片隅に入れておくといざという時役立つはずです。

以上、Kubernetesクラスタのお掃除屋さん「Eraser」の紹介でした。クラスター運用の裏方として、Eraserが皆さんの環境でも活躍してくれることを願っています。ぜひ試してみてくださいね！Eraserって便利ですよね！ 😄

**参考資料:**

- Eraser GitHub: *“Eraser helps Kubernetes admins remove a list of non-running images from all Kubernetes nodes in a cluster.” ([GitHub - eraser-dev/eraser:  Cleaning up images from Kubernetes nodes](https://github.com/eraser-dev/eraser#:~:text=Eraser%20helps%20Kubernetes%20admins%20remove,Kubernetes%20nodes%20in%20a%20cluster))】
- Microsoft Tech Community ブログ: *“Eraser…removing vulnerable or unused images, and ensuring your cluster runs smoothly.” ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=Eraser%20is%20an%20open,images%20run%20on%20your%20nodes))】
- Microsoft Tech Community ブログ: *“Unused or vulnerable images can introduce security risks… Redundant images consume storage space and affect node performance.” ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=,by%20reducing%20the%20storage%20requirements))】
- Microsoft Tech Community ブログ: *“Define custom policies to govern image removal, ensuring that images adhering to specific criteria are retained while others are deleted.” ([Clean Slate for your Kubernetes Nodes](https://techcommunity.microsoft.com/blog/educatordeveloperblog/eraser-clean-slate-for-your-kubernetes-nodes/3963789#:~:text=on%20your%20cluster%27s%20needs.%20,process%20to%20your%20specific%20requirements))】
- CNCF公式: *“Eraser uses vulnerability data to remove non-running images from all Kubernetes nodes in a cluster.” ([Eraser | CNCF](https://www.cncf.io/projects/eraser/#:~:text=Eraser%20uses%20vulnerability%20data%20to,Kubernetes%20nodes%20in%20a%20cluster))】
- Eraser ドキュメント: 自動クリーンアップのデフォルト動作（スキャンと間隔 ([Architecture | Eraser Docs](https://eraser-dev.github.io/eraser/docs/architecture#:~:text=Automated%20image%20removal%20runs%20on,running%20images%20in%20your%20cluster)) ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=After%20deploying%20Eraser%2C%20it%20will,h))】
- Eraser ドキュメント: Collector・Scanner・Remover各コンテナの役 ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=Eraser%20will%20schedule%20eraser%20pods,that%20will%20run%20to%20completion)) ([Quick Start | Eraser Docs](https://eraser-dev.github.io/eraser/docs/quick-start#:~:text=The%20collector%20container%20sends%20the,will%20be%20automatically%20cleaned%20up))】
- Eraser ドキュメント: ImageListリソースの使用 ([Manual Removal | Eraser Docs](https://eraser-dev.github.io/eraser/docs/manual-removal#:~:text=cat%20,running%20images)) ([Manual Removal | Eraser Docs](https://eraser-dev.github.io/eraser/docs/manual-removal#:~:text=%3E%20%60ImageList%60%20is%20a%20cluster,images%20instead%20of%20individual%20images))】