【容器】设备上没有剩余空间的错误排查处理

2025-04-01T18:35:40+08:00 | 7分钟阅读 | 更新于 2025-04-01T18:35:40+08:00

Macro Zhao

【容器】设备上没有剩余空间的错误排查处理

推荐超级课程:

设备上没有剩余空间是一个相对知名的错误,可以发生在运行基于Linux的程序的环境中。如果存储位置已满,就会发生这种情况,错误表明该位置不再有空间来写入/存储更多数据。这本身并不是Azure容器应用特有的,但由于两个核心原因,这里可能会出现这个问题:

  1. 镜像大小

  2. 容器向容器文件系统写入大量文件(例如缓存、大文件、大量文件等)。重要的是写入本地文件系统,而不是挂载的Azure文件卷。使用Azure文件持久化的卷将数据存储在文件共享中。写入本地容器文件系统的数据存储在主机上存储层的共享位置。这通常被称为容器的“薄可写层”。

    • 另一方面,如果使用临时卷 ,您也可能看到类似的设备上没有剩余空间问题,不同之处在于,由于达到存储限制,Pod将被驱逐。正如上述链接所示,卷大小取决于分配给容器的cpu

上述情况可以发生在作业和容器应用上

可用的配置文件类型可以在这里 找到。以下是不同配置文件的磁盘空间示例,您可以使用df -h查看

(消费型)

消费型磁盘空间

(d4)

d4磁盘空间

随着SKU大小的增加,磁盘空间也会增加。


在存储方面,overlay 在满时会导致这个问题。注意,完全预期 overlay 上已经有一些使用量,无论镜像大小如何。由于这个位置是主机上的挂载点,因此无法直接访问。

发现这些错误

您可以在日志流、Azure Monitor 或 Log Analytics 中找到这些错误。有关容器应用的日志选项,请查看 Azure Container Apps 中的日志存储和监控选项

在 Azure Monitor 中,它将在 ContainerAppSystemLogs 表中。对于 Log Analytics,它将在 ContainerAppSystemLogs_CL 表中。

这可能在镜像拉取过程中直接显示 - 另一方面可能是在容器创建时,如果在容器创建时磁盘空间已满,将显示此消息。

无论哪种情况,它看起来都会像下面这样:

OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting \"/some/path" to rootfs at \"/somepath\": mkdir /mnt/to/somepath: no space left on device: unknown"}

或者简单地说:

no space left on device: unknown

镜像大小

最大镜像大小在 这里 中指出。

最大镜像大小:

  • 消费型工作负载配置文件支持每个应用或作业副本的容器镜像总大小达到 8GB。

  • 专用工作负载配置文件支持更大的容器镜像。 因为专用工作负载配置文件可以运行多个应用或作业,所以多个容器镜像共享可用的磁盘空间。实际支持的镜像大小根据其他应用和作业消耗的资源而变化。

上述原因在于消费型和工负载配置文件之间的托管机制差异。

由于 工作负载配置文件 可以被视为更典型的“节点”基于方法,其中使用配置文件的所有Pods/副本将在这些节点上调度,这就是上面提到的 多个容器镜像共享可用磁盘空间 的概念来源。

最佳实践(总的来说):

  • 尽可能使用更小的镜像。这可能意味着使用 alpineslim 基于的镜像分发版本,而不是完整的分发版如 :ubuntu:debian 等。检查您的基础镜像是否支持更小的变体标签。

    • 一个需要注意的是,像 Alpine 这样的较小变体将使用 apk 包管理器(因此,如果从另一个分发版切换,您可能需要更新您的 Dockerfile 和其他 .sh 脚本)- 最重要的是 - 某些工具可能默认不可用/未安装,因为其理念是保持小型化。- 此外,Alpine 使用 musl 作为 C 标准库,而不是其他发行版中常见的 glibc。这可能不会影响大多数应用程序,但应该牢记。特别是如果应用程序依赖于共享库或底层 C 绑定。
  • 使用多阶段镜像。更多信息请参见 多阶段构建 。多阶段构建可以通过仅从之前的构建中复制所需内容到当前构建的上下文中,并丢弃其余内容来节省大量空间,而不是创建一个大的构建。例如:

    
    FROM maven:3.9.0-eclipse-temurin as build
    
    WORKDIR /usr/src/app
    
    COPY . /usr/src/app
    
    
    
    RUN mvn -f /usr/src/app/pom.xml clean package -DskipTests
    
    
    
    FROM eclipse-temurin:17.0.14_7-jre
    
    WORKDIR /usr/src/app
    
    
    
    COPY --from=build /usr/src/app/target/probes-0.0.1-SNAPSHOT.jar probes-0.0.1-SNAPSHOT.jar
    
    COPY --from=build /usr/src/app/init_container.sh init_container.sh 
    
    COPY --from=build /usr/src/app/certs /usr/src/app/certs
    
    • 这个构建使用 Maven 构建上述 Java 应用程序以生成一个 .jar 文件,我们只将这个文件和其他一些文件复制到当前的运行时构建中。

    • 这样可以节省空间,因为不需要在镜像中包含 Maven 及其所有其他依赖项作为依赖本身。

  • 使用 .dockerignore(或您容器管理工具的等效文件)。可以将其视为类似于 .gitignore,但用于放入镜像的文件。在某些情况下,这可以减少许多文件并节省整体镜像大小。参见 .dockerignore 文件 。如果使用 Podman,请使用 .containerignore

  • 考虑仅使用运行时环境而不是完整的开发工具包(SDKs)。如果不需要完整的 SDKs(或 JDKs)- 考虑使用仅运行时环境等效物。对于 Java,这通常是包含 jre 标签的镜像,对于 .NET,这是名称中仅包含 aspnet:some.version 的镜像 - 请参见这里 了解相关解释

  • 如果遇到这个问题,并且您想检查镜像大小,请查看未压缩的镜像大小,而不是压缩大小。当拉取层时,存储在注册表中的压缩镜像的层会被下载并解压缩,因此这个大小才是重要的。要有效检查镜像大小,请将其拉取到您的本地机器(如果尚不存在)并运行以下命令:

    • docker inspect -f "{{ .Size }}" someimage:sometag - 这会输出未压缩的大小(以字节为单位)

    • docker inspect -f "{{ .Size }}" someimage:sometag | numfmt --to=si - 这会以人类可读的格式输出未压缩的大小- docker image ls someimage:sometag

以下是使用此命令在本地镜像上的一些示例:


$ docker inspect -f "{{ .Size }}" pythonfastapi:large

12155661241



$ docker image ls pythonfastapi:large

REPOSITORY      TAG       IMAGE ID       CREATED      SIZE

pythonfastapi   large     ab7065c19777   6天前        12.2GB



$ docker inspect -f "{{ .Size }}" pythonfastapi:large | numfmt --to=si

13G

有时,您可能不得不依赖第三方镜像,其中您无法控制镜像大小。这也可能适用于主要专注于AI/ML的某些镜像,它们天生具有大型库。如果没有更瘦小/更小的标签可以利用,那么考虑使用工作负载配置文件并使用更大的SKU大小。

运行时

这指的是概述部分中关于容器在运行时创建文件的第二点。

如果应用程序生成大量缓存(并且持续添加到其中),或者本质上任何其他操作,随着时间推移,在写入本地文件系统时创建大量文件,那么如果文件数量在一段时间内显著消耗存储空间,它们就可能在运行时遇到这个问题。

另一个场景是使用容器应用作业和可能将其管道写入大量数据的CI/CD运行器时,可能会发生设备上没有剩余空间的情况。

这些问题可能更难调查,因为如果容器重新启动,写入磁盘的内容现在将被丢弃。然而,在遇到这个问题之前(并且知道这是应用程序的问题),您可以进入控制台 ,它连接到容器中的shell,并可以使用以下命令:

  • df -h

  • find - 您可以使用类似find / -type f -exec du -Sh {} + | sort -rh | head -n 5的命令 - 其中/是您想要列出顶部n目录大小的目录

  • du - 例如du -a /tmp | sort -n -r | head -n 5 - 其中/tmp是您想要列出顶部n目录大小的目录

  • ls -lrtah - 其中h显示人类可读的文件大小格式

如果您想列出超过前5的目录,将5替换为n - 例如,-n 100

或者,混合使用其他命令来查找当前磁盘空间使用情况以及哪个目录可能消耗最多的存储空间。这可以以更多适应您用例/需求的不同方式完成。

注意:上述方法不适用于作业,因为无法访问控制台

如果不能这样做,那么在更本地或受控的环境中测试这一点(例如,在Linux VM上,但不在容器内,以便文件持久化到VM磁盘)并进行应用程序调查将需要了解写入磁盘的内容是什么导致这个问题。除了从您的容器中识别出占用磁盘空间的文件/目录本身外,以下操作也可以进行:

  • 使用工作负载配置文件,而不是按需消费,并在需要时使用更高规格的SKU。

  • 如果这些文件本身与缓存无关,并且不打算被丢弃,那么考虑通过存储卷使用AzureFiles来存储这些数据。注意,在这种情况下,不建议使用AzureFiles来存储临时文件。

  • 如果这些文件与缓存相关的——而且是临时文件——考虑实现某种清理机制,在x时间间隔或目录文件大小达到一定程度时进行清理。

    • 注意,这将意味着首先已知生成如此大量文件的核心原因/位置。

所有上述内容也适用于使用临时卷 ,尽管错误可能不是设备上没有剩余空间,而可能是如下所示的内容,这些内容也可以在系统日志中找到:

  • 容器somecontainer超出了其本地临时存储限制"[some_size]"。

  • Pod的本地临时存储使用量超过了容器的总限制[some_size]。

© 2011 - 2025 Macro Zhao的分享站

关于我

如遇到加载502错误,请尝试刷新😄

Hi,欢迎访问 Macro Zhao 的博客。Macro Zhao(或 Macro)是我在互联网上经常使用的名字。

我是一个热衷于技术探索和分享的IT工程师,在这里我会记录分享一些关于技术、工作和生活上的事情。

我的CSDN博客:
https://macro-zhao.blog.csdn.net/

欢迎你通过评论或者邮件与我交流。
Mail Me

推荐好玩(You'll Like)
  • AI 动·画
    • 这是一款有趣·免费的能让您画的画中的角色动起来的AI工具。
    • 支持几十种动作生成。
我的项目(My Projects)
  • 爱学习网

  • 小乙日语App

    • 这是一个帮助日语学习者学习日语的App。
      (当然初衷也是为了自用😄)
    • 界面干净,简洁,漂亮!
    • 其中包含 N1 + N2 的全部单词和语法。
    • 不需注册,更不需要订阅!完全免费!
  • 小乙日文阅读器

    • 词汇不够?照样能读日语名著!
    • 越读积累越多,积跬步致千里!
    • 哪里不会点哪里!妈妈再也不担心我读不了原版读物了!
赞助我(Sponsor Me)

如果你喜欢我的作品或者发现它们对你有所帮助,可以考虑给我买一杯咖啡 ☕️。这将激励我在未来创作和分享更多的项目和技术。🦾

👉 请我喝一杯咖啡

If you like my works or find them helpful, please consider buying me a cup of coffee ☕️. It inspires me to create and share more projects in the future. 🦾

👉 Buy me a coffee