分享方式:


使用 ImageCleaner 清除 Azure Kubernetes Service (AKS) 叢集上易受攻擊的過時映像

通常我們會使用管線在 Azure Kubernetes Service (AKS) 叢集上建置和部署映像。 雖然非常適合用來建立映像,但此程序通常不會考慮留下的過時映像,而這可能會導致叢集節點上的映像高載。 這些映像可能包含弱點,這可能會造成安全性問題。 若要消除叢集中的安全性風險,您可以清除這些未參考的映像。 手動清除映像可能需要大量時間。 Image Cleaner 會執行自動映像識別和移除,以降低過時映像的風險,並減少清除映像所需的時間。

注意

Image Cleaner 是以 Eraser 為基礎的功能。 在 AKS 叢集上,功能名稱和屬性名稱是 Image Cleaner,而相關的 ImageCleaner Pod 名稱則包含 Eraser

必要條件

  • Azure 訂用帳戶。 如果您沒有 Azure 訂用帳戶,您可以建立免費帳戶
  • Azure CLI 2.49.0 版或更新版本。 執行 az --version 來尋找您的版本。 如果您需要安裝或升級,請參閱安裝 Azure CLI

限制

Image Cleaner 尚未支援 Windows 節點集區或 AKS 虛擬節點。

Image Cleaner 的運作方式

啟用 Image Cleaner 之後,將會有名為 eraser-controller-manager 的控制器管理員 Pod 部署至您的叢集。

顯示 ImageCleaner 工作流程的圖表螢幕擷取畫面。在叢集上執行的 ImageCleaner Pod 可產生 ImageList,或提供手動輸入。

使用 Image Cleaner,您可以選擇手動和自動模式和下列設定選項:

設定選項

名稱 描述 必要
--enable-image-cleaner 啟用 AKS 叢集的 Image Cleaner 功能 是,除非指定停用
--disable-image-cleaner 停用 AKS 叢集的 Image Cleaner 功能 是,除非指定啟用
--image-cleaner-interval-hours 此參數會決定 ImageCleaner 將用來執行的間隔時間 (時數)。 Azure CLI 的預設值為一週,最小值為 24 小時,最大值為三個月。 Azure CLI 不需要、ARM 範本或其他用戶端的必要項目

自動模式

部署 eraser-controller-manager 之後,會自動採取下列步驟:

  • 這會立即啟動清除工具,並為每個節點建立 eraser-aks-xxxxx 背景工作角色 Pod。
  • 每個背景工作角色 Pod 中有三個容器:
    • 收集器,這會收集未使用的映像。
    • Trivy 掃描器,這會利用 Trivy 掃描映像弱點。
    • 移除器,這會移除有弱點但未使用的映像。
  • 清除流程完成之後,就會刪除背景工作角色 Pod,而下一個排程的清除作業會根據 您定義的 --image-cleaner-interval-hours 進行。

手動模式

您可以藉由定義 CRD 物件 ImageList 手動觸發清除。 這會觸發 eraser-contoller-manager ,為每個節點建立 eraser-aks-xxxxx 背景工作Pod,並完成手動移除程式。

注意

停用 Image Cleaner 之後,舊設定仍存在。 這表示如果您再次啟用此功能而未明確傳遞設定,則會使用現有的值,而不是預設值。

在您的 AKS 叢集上啟用 Image Cleaner

在新叢集上啟用 Image Cleaner

  • 使用 az aks create 命令搭配 --enable-image-cleaner 參數,在新的 AKS 叢集上啟用 Image Cleaner。

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

在現有叢集上啟用 Image Cleaner

  • 使用 az aks update 命令在現有的 AKS 叢集上啟用 Image Cleaner。

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

更新新叢集或現有叢集上的 Image Cleaner 間隔

  • 使用 --image-cleaner-interval-hours 參數更新新或現有 AKS 叢集上的 Image Cleaner 間隔。

    # 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 手動移除映像

重要

name 必須設定為 imagelist

  • 使用下列 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
    

手動清除是一次性作業,只有在建立新的 imagelist 或變更現有的 imagelist 時才會觸發。 刪除映像之後,將不會自動刪除 imagelist

如果您需要觸發另一次手動清除,您必須建立新的 imagelist 或變更現有的映像。 如果您要再次移除同一個映像,您必須建立新的 imagelist

刪除現有的 ImageList 並建立新的 ImageList

  1. 使用 kubectl delete 命令移除舊的 imagelist

    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

  • 使用 kubectl edit 命令修改現有的 imagelist

    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 Pod 會在工作完成後的 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. 使用下列 kubectl createkubectl label 命令,使用範例 JSON 檔案建立 configmap

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

停用 Image Cleaner

  • 使用 az aks update 命令搭配 --disable-image-cleaner 參數停用叢集上的 Image Cleaner。

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

常見問題集

如何檢查 Image Cleaner 使用哪個版本?

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

除了 Trivy 掃描器之外,Image Cleaner 是否支援其他弱點掃描器?

否。

我可以指定要清除映像的弱點層級嗎?

否。 弱點層級的預設設定包括:

  • LOW+
  • MEDIUM+
  • HIGH,以及
  • CRITICAL

您無法自訂預設設定。

如何檢閱 Image Cleaner 已清除的映像?

映射記錄會儲存在 eraser-aks-xxxxx 背景工作Pod中。 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 Pod 會在工作完成後的 10 分鐘內刪除。 您可以遵循下列步驟來啟用 Azure 監視器附加元件,並使用容器深入解析 Pod 記錄資料表。 此後,系統會儲存歷程記錄,即使已刪除 eraser-aks-xxxxx,您也可以檢閱記錄檔。

  1. 確定叢集上已啟用 Azure 監視。 如需詳細步驟,請參閱在 AKS 叢集上啟用容器深入解析

  2. 使用 az aks show 命令取得 Log Analytics 資源識別碼。

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

    幾分鐘後,命令會傳回解決方案的 JSON 格式資訊,包括工作區資源識別碼:

    "addonProfiles": {
      "omsagent": {
        "config": {
          "logAnalyticsWorkspaceResourceID": "/subscriptions/<WorkspaceSubscription>/resourceGroups/<DefaultWorkspaceRG>/providers/Microsoft.OperationalInsights/workspaces/<defaultWorkspaceName>"
        },
        "enabled": true
      }
    }
    
  3. 在 Azure 入口網站中,搜尋工作區資源識別碼,然後選取 [記錄]

  4. 將下列查詢複製到資料表,並將 name 取代為 eraser-aks-xxxxx (背景工作角色 Pod 名稱):

    let startTimestamp = ago(1h);
    KubePodInventory
    | where TimeGenerated > startTimestamp
    | project ContainerID, PodName=Name, Namespace
    | where PodName contains "name" and Namespace startswith "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
    
  5. 選取執行。 任何已刪除的映像記錄會出現在 [結果] 區域中。