共计 4124 个字符,预计需要花费 11 分钟才能阅读完成。
导言:
GitLink 编程夏令营是在 CCF 中国计算机学会领导下,由 CCF 开源倒退委员会(CCF ODC)举办的面向全国高校学生的暑期编程流动。
这是去年(2022)的夏令营流动中,王瑞同学加入 Nydus 开源我的项目的总结,次要介绍了为 Nydus 反对镜像与文件系统一致性校验所做的相干工作。
Nydus 简介
Nydus 是 CNCF 孵化我的项目 Dragonfly 的子项目,它提供了容器镜像,代码包,数据分析按需加载的能力,无需期待整个数据下载实现便可开始服务。
Nydus 在生产环境曾经撑持了每日百万级别的减速镜像容器创立,在启动性能,镜像空间优化,网络带宽效率,端到端数据一致性等方面相比 OCIv1 格局有着微小劣势,并可扩大至例如 NPM 包懒加载等数据散发场景。
目前 Nydus 由蚂蚁团体,阿里云,字节跳动联合开发,Containerd,Podman 社区承受了 Nydus 运行时作为其社区子项目,也是 KataContainers 以及 Linux v5.19 内核态原生反对的镜像减速计划。
Nydus 架构及原理
OCI 容器镜像是以后容器镜像的实现规范。它采纳了分层的设计,每个镜像可蕴含多个镜像层。新层蕴含的是在旧层的根底上,新减少或者批改的文件或者被删除的文件。这种设计形式比较简单,不过也有着肯定的缺点。如须要镜像层全副重叠后能力看到整个文件系统的视图,但不是所有数据都会被读取; 同时可能曾经删除或者被批改旧层中的文件,然而仍须要残缺地下载和解压旧层; 文件元数据批改导致整个镜像层被从新存储等。Nydus 兼容目前的 OCI 生态,旨在通过细粒度的数据宰割、去重和按需加载机制减速容器 的启动和散发,同时升高资源的耗费。
Nydus 的整体架构如下图所示。它能够通过 FUSE 给 runc 容器提供运行时的按需加载能力,也能够通过 virtiofs 承载 FUSE 协定,给 Kata Containers 等基于 VM 的容器运行时提供按需加载的能力。它能够从容器 Registry,OSS,NAS,Dragonfly supernode 等多个镜像源拉取镜像,同时外部会有本地的缓存减速容器的创立。
在用户空间文件系统,Nydus 采纳了数据和元数据拆散的设计思维,元数据的批改不会导致整个镜像层的更新。原先的镜像层只存储文件的数据局部,同时数据被分块存储。拉取镜像是不须要拉取整层,只须要拉取所需文件对应的数据块即可。这也使得层与层之间,镜像与镜像之间共享数据块更加容易。上图展现了 Nydus 数据和元数据的存储格局。其中元数据以 merkle tree 的模式存储在 bootstrap 中,蕴含了容器启动所须要的信息。数据以 1MB 分块存储,不同镜像能够共享同一数据块。
Nydus 镜像校验意义及流程
Nydus 镜像在构建实现后,因为网络、磁盘等故障或者镜像被歹意批改,无奈保障容器启动前镜像是非法的,所以须要对镜像的格局进行校验。以后的校验应用 nydusify 工具。次要分为三个局部:
- 对 Nydus 镜像的 bootstrap 进行校验,会通过 BootstrapRule 调用 nydus-image 二进制文件。nydus-image 首先查看 bootstrap 的 SuperBlock 格局是否正确,而后会从根结点开始依照文件系统层级构造查看文件或者目录的 inode 是否非法或被批改。
- 对镜像的 manifest 进行校验,会通过 ManifestRule 测验 Nydus 的 manifest 是否非法,ImageConfig 是否与原始 OCI 镜像统一等。
- 对镜像进行文件系统校验,会通过 FilesystemRule 别离挂载原始 OCI 镜像和 Nydus 镜像,而后进行校验。对于原始镜像,会应用 docker pull 拉取镜像,而后指定 lowerdir 和 upperdir,通过 OverlayFS 挂载 Rootfs;对于 Nydus 镜像,会应用 Nydusd 挂载。挂载实现后,会别离遍历两个目录,比拟元数据和数据是否统一。
目前 Nydus 的校验形式仍有肯定的限度,如元数据查看不齐全,须要 docker 拉取镜像等。该我的项目旨在加强 nydusify 和 nydus-image 的校验性能,使校验更加易用和全面。
文件系统校验计划
该我的项目以后分为以下三局部:
- 以后 nydusify check 在利用 FilesystemRule 进行校验时,对于文件元数据只查看文件门路、大小、模式和权限位以及 xattrs 是否和原始镜像统一,同时对文件数据用 blake3 计算失去哈希值并进行比拟。然而因为校验内容不残缺,可能会呈现元数据不统一校验通过的状况。故对该构造体增加 dev、rdev、symlink、project id、uid、gid、nlink、ctime 等字段,实现对文件元数据更全面的查看。
- 以后 nydusify check 在利用 FilesystemRule 进行校验时,须要手动指定 source 和 Backend Type, Backend Config 能力胜利利用 Nydusd 挂载并进行文件系统校验,在校验数据时,也会再次查看 Backend Type 是否指定。在大多数状况下,Backend Type 为 Registry,Backend Config 能够通过查看 Registry 的 config 文件获取相干信息,如 http.addr 字段获取地址,auth 字段获取认证信息等获取。因此用户在很多状况下并不需要手动输出上述参数。该工作旨在简化该命令,实现 Backend Type,Backend Config 的主动推断,使得用户更不便地进行校验。
(3) 以后 nydusify check 在利用 FilesystemRule 进行校验时,须要用户装置 docker,因为要应用 docker pull 命令拉取镜像。在没有 docker 的环境下,无奈实现校验。能够批改该局部代码,手动下载、解压镜像,并应用 OverlayFS 挂载,从而去除对 docker 的依赖。
文件系统校验实现细节
减少校验字段
该局部的实现较为简单。首先在原 Node 构造体减少 rdev, symlink, uid, gid, mtime 等字段。
而后在遍历文件系统时,应用 Readlink 获取文件的软链接,通过 Lstat 零碎调用获取 文件更具体的元数据信息(rdev, uid, gid, mtime 等),从而在进行比拟时减少对上述字段的校验。值得注意的是 dev 不同是失常的,nlink 因为 OverlayFS 的问题无奈进行校验。此外,还须要批改异样错误信息,从而遇到不统一时可能打印残缺的文件元数据信息。
简化校验参数
该局部须要实现 Backend Type 和 Backend Config 的主动推断,即如果镜像存储在 registry 中,用户无需指定上述两个参数即可实现校验。
首先,咱们须要增加上述构造体,即镜像源为 Registry 时的 Backend Config。对于 FilesystemRule 构造体,还需增加 Target 和 TargetInsecure 字段,用于填充 Backend Config。
在挂载 Nydus 镜像时,咱们须要正确填充 Nydusd 的 config,其中便蕴含 Backend Config 和 Backend Type。因而咱们对用户传入的参数进行判断,如果用户没有传入 Backend Type,那么咱们默认镜像源为 registry,如果没有传入 Backend Config,那么咱们通过 target 提取 host 和 repo,而后读取 docker 的 config 获取 auth 相干的信息,最初生成 Backend Config。
除此之外,因为咱们目前的测试代码中不波及用户鉴权,所以额定增加了 testBasicAuth 测试样例,用于测验在用户不指定 Backend Config 时,咱们是否可能正确提供 鉴权信息。在测试样例中,咱们模仿生成了用户名、明码和 docker config,并正确设置了环境变量。启动 docker 时,额定指定 REGISTRY_AUTH_HTPASSWD_PATH,REGISTRY_AUTH 等用于鉴权。
实现无需 docker 拉取镜像
以后拉取原始镜像时,咱们须要当时装置 docker,而后通过 docker pull 指令拉取。咱们能够手动的拉取每个镜像层,而后解压、挂载,从而去除对 docker 的依赖。
首先咱们须要在 FilesystemRule 构造体中增加 SourceParsed, SourcePath, SourceRemote 等字段,指定原始镜像的相干信息和存储门路。在拉取原始镜像时,咱们通过 SourceParsed 获取到镜像层的信息,而后多线程下载每个镜像层并解压。
因为镜像的存储门路是当时确定的,同时咱们也能够获取到每个镜像层的信息,所以在挂载镜像时,咱们不须要运行 docker inspect 命令获取镜像的分层信息,能够间接拼接每一层的门路,应用 OverlayFS 进行挂载。
后续发现 OverlayFS 挂载单层镜像时存在肯定的问题,因此上述代码进行了肯定水平 的批改和重构。
播种与瞻望
这个我的项目的代码量不是很大,然而我从中学习到了很多。首先通过浏览代码和跟踪调试,我理解了 Nydus 的设计思维和镜像的生成及校验的流程。在实现我的项目的过程中,我对 go 语言的应用更加纯熟,对于容器镜像的分层存储格局及拉取、挂载的流程有了更加 细化的意识。通过解决测试过程中遇到的各种问题,我发现问题、定位问题、解决问题的能力也有了肯定的晋升。心愿之后有机会能够持续参加到 Nydus 我的项目之中,为开源贡献力量。
作者有话说
哈喽大家好,我是王瑞,本科毕业于北京邮电大学计算机科学与技术业余,现就读于多伦多大学,从事日志压缩相干钻研。本科时曾在字节跳动公司实习,参加过自动化运维平台、存储系统内存治理相干的开发工作。也曾在 VMware 公司实习,为开源数据库 GreenPlum 奉献过代码。因为对云原生比拟感兴趣,所以非常高兴能够参加到 Nydus 这个我的项目。感激严松老师在过程中提供的领导和帮忙。
Nydus Star 一下✨:
github.com/dragonflyos…
本周举荐浏览
Nydus 镜像扫描减速
Nydus 镜像减速插件迁入 Containerd 旗下
Nydus | 容器镜像根底
Dragonfly 和 Nydus Mirror 模式集成实际