Image Cleaner を使用して Azure Kubernetes Service (AKS) クラスターで脆弱な古いイメージをクリーンアップする

適用対象: ✔️ AKS 自動 ✔️ AKS Standard

パイプラインを使用して Azure Kubernetes Service (AKS) クラスターでイメージをビルドしてデプロイするのが一般的です。 このプロセスはイメージの作成には適していますが、残された古いイメージを考慮していないことが多く、クラスター ノードでイメージが肥大化することがあります。 これらのイメージには脆弱性が含まれている可能性があり、セキュリティの問題が発生する可能性があります。 クラスターのセキュリティ リスクを削除するには、これらの参照されていないイメージをクリーンします。 手動で画像をクリーニングすると、時間がかかる場合があります。 Image Cleaner は、イメージの自動識別と削除を実行します。これにより、古いイメージのリスクが軽減され、イメージをクリーンするのに必要な時間が短縮されます。

AKS 自動は、ほとんどの AKS ワークロードに推奨される運用環境対応の既定値です。 Image Cleaner は、既定で脆弱性のある未使用のイメージを削除できるように、AKS 自動クラスターで事前構成されています。

AKS Standard クラスターでは、Image Cleaner は省略可能であり、明示的に有効にします。

AKS Automatic の詳細については、「Azure Kubernetes Service (AKS) Automatic とは」をご覧ください。

Image Cleaner は Eraser に基づいた機能です。 AKS では、機能名とプロパティ名が Image Cleanerされ、関連する Image Cleaner ポッドの名前には Eraserが含まれます。

AKS の自動動作と AKS 標準動作

前提条件

  • Azure サブスクリプション。 Azure サブスクリプションをお持ちでない場合は、無料のアカウントを作成できます。
  • Azure CLI を使用して AKS Standard を構成する場合は、Azure CLI バージョン 2.49.0 以降が必要です。 バージョンを確認するには az --version を実行します。 インストールまたはアップグレードする必要がある場合は、Azure CLI のインストールに関するページを参照してください。

制限事項

Image Clearner では、Windows ノード プールまたは AKS 仮想ノードはまだサポートされていません。

Image Cleaner のしくみ

クラスターで Image Cleaner をアクティブにすると、 eraser-controller-managerという名前のコントローラー マネージャー ポッドがデプロイされます。

Image Cleaner のワークフローを示した図のスクリーンショット。ImageList は、クラスターで実行されている Image Cleaner ポッドで生成できます。手動で入力することもできます。

Image Cleaner では、自動クリーンアップ モードと手動クリーンアップ モードがサポートされています。

AKS Standard の構成オプション

Azure CLIを使用して AKS Standard でイメージ クリーナーを構成する場合は、次のオプションを使用します。

名前 説明 必須
--enable-image-cleaner AKS クラスターのイメージ クリーナーを有効にする はい(disable を指定しない限り)
--disable-image-cleaner AKS クラスターのイメージ クリーナーを無効にする はい (有効にするを指定しない場合)
--image-cleaner-interval-hours スケジュールされた実行の間隔 (時間単位)。 Azure CLI の既定値は 1 週間です。 最小値は 24 時間です。 最大値は 3 か月です。 Azure CLIには必要ありません。ARM テンプレートまたはその他のクライアントに必要です

イメージ クリーナーを無効にし、後で明示的に構成を渡さずに再度有効にした場合、前の構成値が再利用されます。

自動モード

eraser-controller-managerをデプロイすると、Image Cleaner によって自動的に次のアクションが実行されます。

  • クリーンアップを開始し、各ノード eraser-aks-xxxxx ワーカー ポッドを作成します。
  • コレクター コンテナーを使用して、未使用のイメージを収集します。
  • trivy スキャナー コンテナーを使用して、trivy で脆弱性をスキャンします。
  • リムーバー コンテナーを使用して、脆弱性のある未使用のイメージを削除します。
  • 完了後にワーカー ポッドを削除します。
  • --image-cleaner-interval-hoursに従って次のクリーンアップをスケジュールします。

手動モード

CRD オブジェクト ImageList を定義することで、クリーンアップを手動でトリガーすることができます。 これにより、eraser-contoller-manager がトリガーされて各ノードに eraser-aks-xxxxx ワーカー ポッドが作成され、手動削除プロセスが完了します。

Image Cleaner を無効にした後も、古い構成はそのまま残ります。 つまり、構成を明示的に渡さずに機能を再度有効にすると、既定値ではなく既存の値が使用されます。

AKS Automatic と AKS Standard でイメージ クリーナーを使用する

AKS Automatic

Image Cleaner は AKS 自動クラスターで事前構成されています。これは、ほとんどの AKS ワークロードで推奨される運用環境対応の既定値です。 別の有効化コマンドを実行する必要はありません。

AKS 自動クラスターを作成するには、「 AKS 自動クラスターの作成」を参照してください。

この記事の手動クリーンアップと監視のガイダンスは、対象を絞った修復または運用確認が必要な場合に使用します。

AKS Standard: 新しいクラスターで有効にする

az aks create コマンドと --enable-image-cleaner パラメーターを使用して、新しい AKS Standard クラスターで Image Cleaner を有効にします。

az aks create \
    --resource-group myResourceGroup \
    --name myManagedCluster \
    --enable-image-cleaner \
    --generate-ssh-keys

AKS Standard: 既存のクラスターで有効にする

az aks update コマンドを使用して、既存の AKS Standard クラスターで Image Cleaner を有効にします。

az aks update \
  --resource-group myResourceGroup \
  --name myManagedCluster \
  --enable-image-cleaner

AKS Standard: 新規または既存のクラスターでの更新間隔

--image-cleaner-interval-hours パラメーターを使用して、新規または既存の AKS Standard クラスターのイメージ クリーナー間隔を更新します。

# Create a new cluster with specifying the interval
az aks create \
    --resource-group myResourceGroup \
    --name myManagedCluster \
    --enable-image-cleaner \
    --image-cleaner-interval-hours 48 \
    --generate-ssh-keys

# Update the interval on an existing cluster
az aks update \
    --resource-group myResourceGroup \
    --name myManagedCluster \
    --enable-image-cleaner \
    --image-cleaner-interval-hours 48

Image Cleaner を使用して画像を手動で削除する

重要

nameimagelist に設定する必要があります。

次の kubectl apply コマンドを使って、イメージを手動で削除します。 この例では、docker.io/library/alpine:3.7.3 イメージが使われていない場合は削除します。

cat <<EOF | kubectl apply -f -
apiVersion: eraser.sh/v1
kind: ImageList
metadata:
  name: imagelist
spec:
  images:
    - docker.io/library/alpine:3.7.3
EOF

手動クリーンアップは 1 回限りの操作であり、新しい imagelist が作成されるか、既存の imagelist に変更が加えられた場合にのみトリガーされます。 イメージが削除された後、imagelist は自動的には削除されません。

別の手動クリーンアップをトリガーする必要がある場合は、新しい imagelist を作成するか、既存のものを変更する必要があります。 同じイメージを再度削除する場合は、新しい imagelist を作成する必要があります。

既存の ImageList を削除し、新しいものを作成する

  1. imagelist コマンドを使って古い kubectl delete を削除します。

    kubectl delete ImageList imagelist
    
  2. 同じイメージ名で新しい imagelist を作成します。 次の例では、前の例と同じイメージを使います。

    cat <<EOF | kubectl apply -f -
    apiVersion: eraser.sh/v1
    kind: ImageList
    metadata:
      name: imagelist
    spec:
      images:
        - docker.io/library/alpine:3.7.3
    EOF
    

既存の ImageList を変更する

imagelist コマンドを使って既存の kubectl edit を変更します。

kubectl edit ImageList imagelist

# Add a new image to the list
apiVersion: eraser.sh/v1
kind: ImageList
metadata:
  name: imagelist
spec:
  images:
      docker.io/library/python:alpine3.18

手動モードを使う場合、eraser-aks-xxxxx ポッドは作業完了後 10 分以内に削除されます。

画像除外リスト

除外リストで指定されたイメージは、クラスターから削除されません。 Image Cleaner では、システムとユーザー定義の除外リストがサポートされます。 システム除外リストの編集はサポートされていません。

システム除外リストを確認する

次の kubectl get のコマンドを使用して、システム除外リストを確認します。

kubectl get -n kube-system configmap eraser-system-exclusion -o yaml

ユーザー定義の除外リストを作成する

  1. 除外されたイメージを含むサンプル JSON ファイルを作成します。

    cat > sample.json <<EOF
    {"excluded": ["excluded-image-name"]}
    EOF
    
  2. 次の configmap コマンドと kubectl create コマンドを使用して、サンプル JSON ファイルを使用して kubectl label を作成します。

    kubectl create configmap excluded --from-file=sample.json --namespace=kube-system
    kubectl label configmap excluded eraser.sh/exclude.list=true -n kube-system
    

AKS Standard でイメージ クリーナーを無効にする

az aks update パラメーターを指定して --disable-image-cleaner コマンドを使用して、AKS Standard クラスターで Image Cleaner を無効にします。

az aks update \
  --resource-group myResourceGroup \
  --name myManagedCluster \
  --disable-image-cleaner

よく寄せられる質問 (FAQ)

AKS 自動でイメージ クリーナーは既定で有効になっていますか?

Yes. イメージ クリーナーは、AKS 自動クラスターで事前構成されています。

AKS Automatic で Image Cleaner の有効化コマンドを実行する必要がありますか?

いいえ。 AKS Standard の有効化コマンドを使用します。

イメージ クリーナーが使っているバージョンを確認するにはどうすればよいですか?

kubectl describe configmap -n kube-system eraser-manager-config | grep tag -C 3

Image Cleaner では、trivy スキャナー以外の脆弱性スキャナーもサポートされていますか?

いいえ。

イメージをクリーンアップする脆弱性レベルを指定できますか?

いいえ。 脆弱性レベルの既定の設定は次のとおりです。

  • LOW,
  • MEDIUM,
  • HIGH、および
  • CRITICAL

既定の設定をカスタマイズすることはできません。

Image Cleaner によってクリーンアップされたイメージを確認する方法は?

イメージ ログは、eraser-aks-xxxxx ワーカー ポッドに格納されます。 eraser-aks-xxxxx が有効な場合、次のコマンドを実行して削除ログを表示できます。

kubectl logs -n kube-system <worker-pod-name> -c collector
kubectl logs -n kube-system <worker-pod-name> -c trivy-scanner
kubectl logs -n kube-system <worker-pod-name> -c remover

eraser-aks-xxxxx ポッドは作業完了後 10 分以内に削除されます。 以下の手順に従って、Azure Monitor アドオンを有効にし、コンテナーの分析情報ポッド ログ テーブルを使用できます。 その後、履歴ログが保存され、eraser-aks-xxxxx が削除されてもそれらを確認できます。

  1. クラスターでAzure Monitorが有効になっていることを確認します。 詳細な手順については、「AKS クラスターの Container Insights を有効にする」を参照してください。

  2. 既定では、 kube-system 名前空間で実行されているコンテナーのログは収集されません。 構成マップのkube-systemからexclude_namespaces名前空間を削除し、構成マップを適用してこれらのログの収集を有効にします。 詳細については、「Container insights データ収集の構成」を参照してください。

  3. az aks show コマンドを使用して Log Analytics リソース ID を取得します。

      az aks show --resource-group myResourceGroup --name myManagedCluster
    

    数分後、コマンドによって、ワークスペース リソース ID を含むソリューションに関する情報が JSON 形式で返されます:

    "addonProfiles": {
      "omsagent": {
        "config": {
          "logAnalyticsWorkspaceResourceID": "/subscriptions/<WorkspaceSubscription>/resourceGroups/<DefaultWorkspaceRG>/providers/Microsoft.OperationalInsights/workspaces/<defaultWorkspaceName>"
        },
        "enabled": true
      }
    }
    
  4. Azure ポータルで、ワークスペース リソース ID を検索し、[ログ] を選択します

  5. 次のいずれかのクエリをコピーし、クエリ ウィンドウに貼り付けます。

    • クラスターで ContainerLogV2 スキーマを使用している場合は、次のクエリを使用します。 ContainerLogをまだ使用している場合は、ContainerLogV2 にアップグレードします。

      ContainerLogV2
      | where PodName startswith "eraser-aks-" and PodNamespace == "kube-system"
      | project TimeGenerated, PodName, LogMessage, LogSource
      
    • ContainerLogを引き続き使用する場合は、代わりに次のクエリを使用します。

      let startTimestamp = ago(1h);
      KubePodInventory
      | where TimeGenerated > startTimestamp
      | project ContainerID, PodName=Name, Namespace
      | where PodName startswith "eraser-aks-" and Namespace == "kube-system"
      | distinct ContainerID, PodName
      | join
      (
          ContainerLog
          | where TimeGenerated > startTimestamp
      )
      on ContainerID
      // at this point before the next pipe, columns from both tables are available to be "projected". Due to both
      // tables having a "Name" column, we assign an alias as PodName to one column which we actually want
      | project TimeGenerated, PodName, LogEntry, LogEntrySource
      | summarize by TimeGenerated, LogEntry
      | order by TimeGenerated desc
       ```
      
      
  6. [実行] を選択します。 削除されたイメージのログは、[結果] 領域に表示されます。