Nydus使用案例: 解决容器镜像用满disk空间问题

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 本文与实习生@河上共同撰写。问题背景在容器生态的生产实践中,有一个不起眼但令人头痛的问题是,节点(baremetal or ECS vm)上用于存放容器相关内容的目录常常用满了整个 disk,导致了对业务的影响。问题分析通常情况下,容器相关的目录主要指 /var/lib/docker 或者/var/lib/containerd,其中最为消耗 disk空间的是容器镜像的targz 格式laye

本文与实习生@河上共同撰写。

问题背景

在容器生态的生产实践中,有一个不起眼但令人头痛的问题是,节点(baremetal or ECS vm)上用于存放容器相关内容的目录常常用满了整个 disk,导致了对业务的影响。

问题分析

通常情况下,容器相关的目录主要指 /var/lib/docker 或者/var/lib/containerd,其中最为消耗 disk空间的是容器镜像的targz 格式layer文件以及targz解压后的snapshots目录。 我们知道容器 layer 的设计初衷之一是为了复用公共的 layer ,在不同镜像之间共享相同的数据,那么在用满disk 空间的情况下,我们首先需要确认,是不是所有公共的数据都被共享了? 实践出真知,下面是干货。 为了方便说明,这里用常用的应用版本迭代场景,以AI模型训练应用为基础,设计了以下两个镜像来观察现象:

镜像

介绍

tensorflow-linux:2.90-5.17

OCI 镜像,tensorflow:2.90 加 Linux-5.17.3 源码用于模拟数据集,size 为619.3 MiB

tensorflow-linux:2.91-5.17

OCI 镜像,tensorflow:2.91 加 Linux-5.17.3 源码用于模拟数据集,size 为619.8 MiB

  •  OCIv1 镜像

After pulling 2.90-5.17: 3.3GB After pulling 2.90-5.17 and 2.91-5.17: 6.2GB

  • 容器镜像layer 分析

通过分析容器的 config中的 build history,可以发现,虽然image manifest 的history 中的操作除了 tensorflow 版本号其它全部相同,但从第 2 层layer开始,2.90 和 2.91 的 layer hash 有了差异,所以结果显示disk 空间是线性增长的。 通常我们认为相邻的小版本差距会较小,所以在这种情况下,对于layer共享的预期是很高的,但实际上,docker build 会因为build环境,timestamp 不同等原因产生“相同数据,layer hash不同”的情况,给用户反直觉的结果。 这背后的原因是 OCIv1 镜像选择了 layer 的设计,但只要有1 个 bit 不同,整个 layer 的 hash 就会改变,导致不能复用。 所以用户在构建镜像时需要特别注意地去避免环境等各种因素对整个build 产生影响,显然这是负担,那么有没有办法去掉这个负担呢?

解决方法

这里给出的答案是使用Nydus。

Nydus 将容器镜像从文件系统层面分成一个元数据bootstrap对象文件和若干个数据blob 对象文件

Nydus在数据 blob部分的设计中引入了chunk,实现了 chunk级别的镜像数据去重。即,容器的每一个文件都由一个或若干chunks组成(chunk size <= 1MB), 而每一个chunk在镜像中只会保存一次。

回到上面我们遇到的问题,镜像之间的相同文件本来应该复用,但因为layer hash 不同,做不到复用。如果将文件分为 chunk,去重对比的粒度从 layer变为了 chunk,那么镜像之间的相同文件就可以做到复用。

综上,Nydus既提供了分层的设计,保持着镜像间层级去重能力,也基于Chunk level deduplication提供了在不同镜像之间低成本的data去重能力。

Nydus测试结果

测试准备

为了对比,这里使用与上面相同的 tensorflow-linux 镜像,将它们转换为 Nydus 镜像之后,进行相同的实验。

注:因为 Nydus 是按需加载,我们需要运行一个“遍历全读”的workload 来加载所有数据,用来演示disk空间的变化情况。

镜像

介绍

tensorflow-linux:2.90-5.17-nydus

Ndyus 镜像,tensorflow:2.90 加 Linux-5.17.3 源码用于模拟数据集。

作为 base image, 用作其他 Nydus image 的 chunk dictionary。

tensorflow-linux:2.91-5.17-nydus-without-dict

Ndyus 镜像,tensorflow:2.91 加 Linux-5.17.3 源码用于模拟数据集。

转换过程中不指定任何 chunk dictionary。

tensorflow-linux:2.91-5.17-nydus

Ndyus 镜像,tensorflow:2.91 加 Linux-5.17.3 源码用于模拟数据集。

转换过程中指定 tensorflow-linux:2.90-5.17-nydus 作为 chunk dictionary。

测试结果

  •  Nydus镜像间不做 chunk 去重

 

After running 2.90-5.17-nydus: 1310656KB

After running 2.90-5.17-nydus and 2.91-5.17-nydus-without-dict: 2568884KB

  • Nydus镜像间做 chunk去重

After running 2.90-5.17-nydus: 1310656KB

After running 2.90-5.17-nydus and 2.91-5.17-nydus: 1339596KB

结果说明与分析

  • 现象
  1. 当disable chunk 去重时,disk 空间占用翻倍
  2. 当 enable chunk 去重时,disk 空间占用基本没变化

  • 结论
  1. tensorflow-linux:2.90  和  tensorflow-linux:2.91  的内容基本相同。
  2. 相比 layer 去重效果,chunk 去重效率好很多,达到了近似block 级别的去重极限。
  3. 在数据全部加载的情况下,在占用disk空间方面,Nydus 镜像是OCIv1 镜像的40%。

  • 分析
  1. tensorflow 的 2 个版本实际内容差别不大,所以当以chunk 粒度对比时,镜像 tensorflow-2.91  可以复用镜像 tensorflow-2.90  的内容。
  2. OCIv1 镜像下载之后,占用 disk 空间的部分不仅有 targz 的 blob 文件,还有解压后的 snapshots。而Nydus 的 targz 部分只包含元数据bootstrap,数据的 blob没有对应的 targz,全部是通过网络按需拉取的。

Nydus相关

Nydus 已经开源在 github Nydus上,文中所有实验与测试均使用 Nydus master branch制作。 https://github.com/dragonflyoss/image-service

Nydus 的最新进展是

  1. 袋鼠安全沙箱的容器rootfs存储方案从 virtiofs 升级到了 Nydus,解决了之前线上遇到的文件描述符相关的稳定性问题,同时提升读I/O性能75%,cpu消耗降低 55%,内存节省 30%。
  2. 基于Linux 5.19 erofs + fscache提供数据加速能力,其特点之一是最大程度上避免了用户态和内核态之间的数据copy带来的性能损耗。
  3. 字节跳动加入Nydus社区共建开源生态。

近期,我们会在将龙蜥社区中集成Nydus 能力,提供开箱即用的数据加速服务。

Reference

  • 5分钟!带你吐槽容器镜像中那些让人一言难尽的事情

  • Nydus 镜像加速之内核演进之路

     

相关实践学习
通过容器镜像仓库与容器服务快速部署spring-hello应用
本教程主要讲述如何将本地Java代码程序上传并在云端以容器化的构建、传输和运行。
Kubernetes极速入门
Kubernetes(K8S)是Google在2014年发布的一个开源项目,用于自动化容器化应用程序的部署、扩展和管理。Kubernetes通常结合docker容器工作,并且整合多个运行着docker容器的主机集群。 本课程从Kubernetes的简介、功能、架构,集群的概念、工具及部署等各个方面进行了详细的讲解及展示,通过对本课程的学习,可以对Kubernetes有一个较为全面的认识,并初步掌握Kubernetes相关的安装部署及使用技巧。本课程由黑马程序员提供。 &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
13天前
|
存储 数据库 Docker
正确删除容器和镜像的方式
【10月更文挑战第24天】本文介绍了在Docker中如何正确删除容器和镜像,包括停止容器、删除已停止容器、删除未被使用的镜像以及注意事项,如数据备份、依赖关系检查和权限问题。其他容器管理工具的操作类似,但命令和语法可能不同。
|
3月前
|
存储 安全 Ubuntu
Docker 镜像与 Docker 容器的区别
【8月更文挑战第27天】
255 5
|
3月前
|
运维 Ubuntu Shell
掌握Docker容器的创建:从镜像到实例
【8月更文挑战第27天】
494 4
|
3月前
|
存储 Ubuntu 应用服务中间件
在Docker中,怎么快速查看本地的镜像和容器?
在Docker中,怎么快速查看本地的镜像和容器?
|
3月前
|
缓存 开发者 Docker
Dockerfile是Docker容器化过程中的核心组件,它允许开发者以一种可重复、可移植的方式自动化地构建Docker镜像
【8月更文挑战第19天】Dockerfile是构建Docker镜像的脚本文件,含一系列指令定义镜像构建步骤。每条大写指令后跟至少一个参数,按序执行,每执行一条指令即生成新的镜像层。常用指令包括:FROM指定基础镜像;RUN执行构建命令;EXPOSE开放端口;CMD指定容器启动行为等。优化策略涉及减少镜像层数、选择轻量基础镜像、利用缓存及清理冗余文件。示例:基于Python应用的Dockerfile包括设置工作目录、复制文件、安装依赖等步骤。掌握Dockerfile有助于高效自动化构建镜像,加速应用部署。
34 1
|
4月前
|
Shell Linux Docker
docker常用命令大全(基础、镜像、容器、数据卷)
这些命令仅仅是 Docker 命令行工具的冰山一角,但对于日常操作来说已经非常全面。通过熟练地使用这些基础命令,用户可以有效地管理 Docker 的镜像、容器、数据卷和网络。随着用户对 Docker 的深入使用,更高级的命令和选项将会变得必需,但上面列出的命令已经为用户提供了一个坚实的起点。对于初学者来说,理解和掌握这些常用命令是深入学习 Docker 的基础。
409 5
docker常用命令大全(基础、镜像、容器、数据卷)
|
3月前
|
机器学习/深度学习 人工智能 安全
产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
阿里云 AI 容器镜像有开箱即用、生态丰富、性能优化、安全合规和服务支持五大优势。
|
3月前
|
运维 Ubuntu Shell
Docker命令宝典:解锁容器化技术的无限可能,从镜像管理到容器操作,全面解析与实战指南!
【8月更文挑战第3天】Docker简化了应用的部署与运行,掌握其基本命令对开发者和运维人员至关重要。通过`docker images`可查看本地镜像;使用`docker pull`拉取如最新版Ubuntu镜像;`docker rmi`用于删除不再需要的镜像。运行容器可通过`docker run`命令,结合`-it`等选项提供交互式环境。`docker ps`显示运行中的容器,加上`-a`则列出所有容器。`docker stop`和`docker start`分别用于停止和重启容器,而`docker rm`则删除容器。
75 5
|
4月前
|
Shell 应用服务中间件 nginx
docker 服务,镜像,容器命令总结
docker 服务,镜像,容器命令总结
161 4
|
4月前
|
运维 Ubuntu Docker
Docker镜像和容器使用
【7月更文挑战第2天】Docker 概要:Docker 镜像是只读模板,包含运行应用的环境和代码,像蓝图一样。构建镜像可通过基于现有镜像(如 Ubuntu)安装软件后提交,或使用 Dockerfile 定义构建过程。Docker 容器是镜像的运行时实例,`docker run` 命令可创建并运行容器。常用容器操作包括启动/停止、状态检查和交互式进入。通过端口映射,容器服务可从主机访问,促进应用部署和管理的便捷性。
128 3

相关产品

  • 容器镜像服务