你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用映像清理器清理 Azure Kubernetes 服务 (AKS) 群集上的易受攻击的过时映像

通常使用管道在 Azure Kubernetes 服务 (AKS) 群集上生成和部署映像。 虽然非常适合创建映像,但此过程通常不考虑留下的过时映像,并且可能导致群集节点上的映像膨胀。 这些映像可能包含可能会导致安全问题的漏洞。 若要消除群集中的安全风险,可以清理这些未引用的映像。 手动清理映像可能会占用大量时间。 映像清理器可自动识别和移除映像,从而降低过期映像的风险,并减少清理映像所需的时间。

注意

映像清理器是一项基于擦除器的功能。 在 AKS 群集上,功能名称和属性名称是 Image Cleaner,而相关的映像清理器 Pod 的名称包含 Eraser

先决条件

  • Azure 订阅。 如果没有 Azure 订阅,可以创建一个免费帐户
  • Azure CLI 2.49.0 或更高版本。 运行 az --version 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI

限制

映像清理器尚不支持 Windows 节点池或 AKS 虚拟节点。

映像清理器的工作原理

启用映像清理器后,将有一个名为 eraser-controller-manager 部署到群集的控制器管理器 Pod。

显示 ImageCleaner 工作流的关系图。群集上运行的 ImageCleaner Pod 可以生成 ImageList,也可以提供手动输入。

使用映像清理器,可以在手动模式和自动模式以及以下配置选项之间进行选择:

配置选项

名称 说明 必须
--enable-image-cleaner 启用 AKS 群集的映像清理器功能 是,除非指定禁用
--disable-image-cleaner 禁用 AKS 群集的映像清理器功能 是,除非指定启用
--image-cleaner-interval-hours 此参数确定运行映像清理器使用的间隔时间(以小时为单位)。 Azure CLI 的默认值为一周,最小值为 24 小时,最大值为三个月。 Azure CLI 不需要,ARM 模板或其他客户端需要

自动模式

部署 eraser-controller-manager 后,系统将自动执行以下步骤:

  • 它会立即启动清理过程,并为每个节点创建 eraser-aks-xxxxx 辅助角色 Pod。
  • 每个辅助角色 Pod 中有三个容器:
    • collector,收集未使用的映像
    • trivy-scanner,利用 trivy 来扫描映像漏洞
    • remover,移除具有漏洞的未使用映像
  • 清理过程完成后,将删除辅助角色 Pod,并根据定义的 --image-cleaner-interval-hours 进行下一个计划的清理。

手动模式

你还可以通过定义 CRD 对象 ImageList 来手动触发清理。 这会触发 eraser-contoller-manager 为每个节点创建 eraser-aks-xxxxx 辅助角色 Pod 并完成手动移除过程。

注意

禁用映像清理器后,旧配置仍然存在。 这意味着,如果在未显式传递配置的情况下再次启用该功能,则会使用现有值而不是默认值。

在 AKS 群集上启用映像清理器

在新群集上启用映像清理器

  • 使用带有 --enable-image-cleaner 参数的 az aks create 命令在新 AKS 群集上启用映像清理器。

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

在现有群集上启用映像清理器

  • 使用 az aks update 命令在现有 AKS 群集上启用映像清理器。

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

更新新的群集或现有群集上的映像清理器间隔

  • 使用 --image-cleaner-interval-hours 参数更新新的或现有 AKS 群集上的映像清理器间隔。

    # 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
    

使用映像清理器手动删除映像

重要

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 分钟内删除。

映像排除列表

排除列表中指定的映像不会从群集中删除。 映像清理器支持系统和用户定义的排除列表。 不支持编辑系统排除列表。

检查系统排除列表

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

禁用映像清理器

  • 使用带有 --disable-image-cleaner 参数的 az aks update 命令在群集上禁用映像清理器。

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

FAQ

如何检查使用的是哪个版本的映像清理器?

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

除三维扫描程序之外,图像清理器是否支持其他漏洞扫描程序?

不是。

是否可以指定要清理的映像的漏洞级别?

错误。 默认的漏洞级别设置包括:

  • LOW
  • MEDIUM
  • HIGH
  • CRITICAL

你无法自定义默认设置。

如何通过图像清理器清理图像?

映像日志存储在 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 Monitor 加载项,并使用容器见解 Pod 日志表。 之后,系统将存储历史日志,因此你甚至可以在删除 eraser-aks-xxxxx 后查看这些日志。

  1. 确保群集上启用了 Azure Monitoring。 有关详细步骤,请参阅 在 AKS 群集上启用容器见解

  2. 使用 az aks show 命令获取 Log Analytics 资源 ID。

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

    在几分钟之后,该命令会返回有关解决方案的 JSON 格式的信息,包括工作区资源 ID:

    "addonProfiles": {
      "omsagent": {
        "config": {
          "logAnalyticsWorkspaceResourceID": "/subscriptions/<WorkspaceSubscription>/resourceGroups/<DefaultWorkspaceRG>/providers/Microsoft.OperationalInsights/workspaces/<defaultWorkspaceName>"
        },
        "enabled": true
      }
    }
    
  3. 在 Azure 门户中,搜索工作区资源 ID,然后选择“日志”。

  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. 选择“运行”。 任何已删除的图像日志都显示在结果区域中。