You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker buildx在AWS/EKS环境耗尽临时存储的问题求助

问题:EKS环境构建Docker镜像耗尽临时存储导致Pod被驱逐

在AWS EKS环境中构建约5GB的Docker镜像时失败,Pod因临时存储耗尽被驱逐,错误日志如下:

14:42:59  unable to retrieve container logs for containerd://51da8f0270e5ed3529ec0ef5cf9e60cafc109ddb4e2baf334185efaf3494491d
14:42:59  jenkins-xxxxxxxxxxx Pod just failed (Reason: Evicted, Message: The node was low on resource: ephemeral-storage. Container builder was using 126387512Ki, which exceeds its request of 0. Container jnlp was using 40Ki, which exceeds its request of 0. )

该构建任务迁移到EKS已近一年,此前无异常。本地构建时仅占用/var/lib/docker下10GB空间,但EKS中构建5GB镜像却占用150GB存储仍未完成。

原因分析

1. Dockerfile多阶段构建的中间层残留

当前Dockerfile包含多个构建阶段(ngcos-ubuntu、ngcos-python、ngcos-release-notes、ngcos-base等),多阶段构建最终仅保留目标镜像,但构建过程中所有中间阶段的镜像都会临时存储在节点上。尤其是ngcos-base阶段下载了两个Android NDK包(r21和r23c),每个NDK解压后大小约几十GB,叠加多个阶段的临时文件会导致存储占用急剧上升。

2. 构建缓存未及时清理

EKS中的Jenkins构建Pod未配置缓存清理策略,每次构建后残留的旧中间镜像、未使用的镜像层会持续占用临时存储,多次构建后逐步耗尽节点空间。

3. Docker-in-Docker(DinD)的存储放大效应

若构建使用DinD模式,Docker守护进程的存储目录(默认/var/lib/docker)会占用Pod临时存储。DinD不仅要存储镜像层,还要保存容器运行时的临时文件,加上镜像构建时的解压、编译等操作,会导致存储占用远大于最终镜像大小。而本地构建使用主机Docker守护进程,缓存和临时文件管理更高效。

4. Pod临时存储请求/限制缺失

错误日志显示容器的临时存储请求为0,EKS节点无法根据存储需求调度合适节点,也无法在存储不足时提前预警,最终导致Pod直接被驱逐。

解决方案

1. 优化Dockerfile减少中间存储占用

  • 合并RUN指令并清理临时文件:将独立的RUN命令合并,同时在每个指令末尾清理下载的压缩包、apt缓存等临时文件。例如ngcos-base中NDK下载步骤可优化为:
    RUN wget -nv -nc "https://dl.google.com/android/repository/${ANDROID_R_NDK_VERSION}-${ANDROID_NDK_ARCH}.zip" && \
        echo "${ANDROID_R_NDK_SHA256}  ${ANDROID_R_NDK_VERSION}-${ANDROID_NDK_ARCH}.zip" | sha256sum --check --strict - && \
        unzip -q -n "${ANDROID_R_NDK_VERSION}-${ANDROID_NDK_ARCH}.zip" && \
        echo "" > $ANDROID_NDK_HOME/${ANDROID_R_NDK_VERSION}/Android.mk && \
        rm -f "${ANDROID_R_NDK_VERSION}-${ANDROID_NDK_ARCH}.zip"
    
    RUN wget -nv -nc "https://dl.google.com/android/repository/${ANDROID_S_NDK_VERSION}-linux.zip" && \
        echo "${ANDROID_S_NDK_SHA256}  ${ANDROID_S_NDK_VERSION}-linux.zip" | sha256sum --check --strict - && \
        unzip -q -n "${ANDROID_S_NDK_VERSION}-linux.zip" && \
        echo "" > $ANDROID_NDK_HOME/${ANDROID_S_NDK_VERSION}/Android.mk && \
        rm -f "${ANDROID_S_NDK_VERSION}-linux.zip"
    
  • 指定构建目标:使用docker build --target仅构建所需的目标阶段,避免无用阶段占用存储。

2. 配置构建缓存清理策略

  • 构建前清理本地缓存:在Jenkins构建脚本中添加docker system prune -af命令,每次构建前清理无用镜像、容器和缓存层。
  • 使用远程缓存:将Docker构建缓存存储到S3等远程存储,减少节点本地缓存占用。例如使用buildx配合远程缓存:
    docker buildx create --use --name mybuilder
    docker buildx build --cache-to type=s3,region=us-east-1,bucket=my-cache-bucket --cache-from type=s3,region=us-east-1,bucket=my-cache-bucket -t my-image .
    

3. 优化DinD存储配置

  • 挂载独立临时存储卷:为DinD容器挂载emptyDir或EFS卷,避免占用节点根目录存储。在Jenkins Pod模板中配置:
    volumes:
      - name: docker-storage
        emptyDir:
          sizeLimit: 200Gi
    containers:
      - name: docker
        image: docker:dind
        volumeMounts:
          - name: docker-storage
            mountPath: /var/lib/docker
    
  • 替换为无守护进程构建工具:使用kaniko替代DinD,直接在容器中构建镜像,无需启动Docker守护进程,降低存储和资源消耗。

4. 配置Pod临时存储请求与限制

在Jenkins构建Pod配置中添加临时存储的请求和限制,让EKS调度到有足够存储的节点:

resources:
  requests:
    ephemeral-storage: 100Gi
  limits:
    ephemeral-storage: 200Gi

5. 定期清理节点临时存储

配置EKS节点的定时CronJob,定期清理/var/lib/containerd或/var/lib/docker目录下的无用文件,避免节点存储长期占用。

内容的提问来源于stack exchange,提问作者Hank Ratzesberger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 01:29:49