当前位置: 首页 > Linux

开箱即用!首创Linux内核原生支持,让你的容器体验飞起来!-龙力科技

时间:2023-04-06 19:44:14 Linux

文/阿里云内核存储团队,龙力社区高性能存储技术SIG成员容器化是近年来devops界的一个流行趋势。通过业务容器化,我们将创建一个完全打包、自包含的计算环境,使软件开发人员能够更快地创建和部署他们的应用程序。但是长期以来,由于镜像格式的限制,容器启动镜像的加载非常缓慢。相关背景详见《容器技术之ContainerImage》。为了加快容器的启动速度,我们可以将优化后的容器镜像与P2P网络等技术相结合,从而有效减少容器部署和启动的时间,保证容器的持续稳定运行。“为了让容器应用管理更快更安全,Dragonfly发布了Nydus容器镜像加速服务”。除了启动速度,镜像分层、去重、压缩、按需加载等核心特性在容器镜像领域也尤为重要。但因为没有原生文件系统支持,所以大多选择了用户态方案,Nydus一开始也是这样做的。随着方案和需求的不断演进,用户态方案遇到了越来越多的挑战,比如与原生文件系统性能差距较大,高密度场景下资源开销大等。原因主要是图片格式解析和按需加载是在用户态实现的,会带来大量的内核态/用户态通信开销。所以看来,如果解决了启动速度,这些核心功能的研发就会有很大的挑战,也有点不知所措。那么有没有可能双管齐下呢?为此,龙蜥社区进行了大胆的尝试。我们设计并实现了兼容内核原生EROFS文件系统的RAFSv6格式,希望能将容器镜像方案下沉到内核态。同时,为了一劳永逸,我们也尝试将此方案推入内核主线,造福更多人。最终,随着Linux内核大佬的挑战和我们的不断完善,erofsoverfscache按需加载技术终于被纳入5.19内核(见文末链接)。至此,Nydus镜像服务的下一代容器镜像分发方案逐渐清晰。这也是Linux主线内核原生支持的第一个开箱即用的容器镜像分发方案。容器镜像的高密度、高性能、高可用、易用性不再是问题!作者还给自己加了一条鸡腿,哈哈!本文将从Nydus架构回顾、RAFSv6镜像格式和EROFSoverFscache按需加载技术三个角度介绍该技术的演进,并通过对比数据展示当前方案的优秀性能。希望大家能尽快享受到像坐飞机一样的容器启动体验!一、Nydus架构回顾总之,Nydus镜像加速服务优化了现有的OCIv1容器镜像架构,设计了RAFS(RegistryAccelerationFileSystem)磁盘格式,最终以文件系统容器镜像格式呈现镜像加速的实现.容器镜像的基本要求本质上就是提供容器的根目录(rootfs),可以是文件系统承载,也可以是归档格式,当然也可以在文件系统的基础上重新创建。Matryoshka(例如,由自定义块格式承载),但必不可少的载体是目录树,它体现为文件接口。我们先来看一下OCIv1标准镜像。OCIv1格式是一种基于DockerImageManifestVersion2Schema2格式的镜像格式规范。它由清单、镜像索引(可选)、一系列容器镜像层和配置文件组成。具体可以参考相关文档,本文不再赘述。OCI镜像本质上是一种以层为基本单位的镜像格式。每一层以tgz归档格式存储文件级diff数据,如下图:由于tgz的限制,OCIv1存在一些先天的问题,比如不能按需加载,去重粒度较粗层,哈希值可变各层等。而一些“二次元套娃”方案(如基于自定义块格式的容器镜像方案)也存在一些理论上的设计缺陷。比如容器镜像最终体现为目录树,那么就需要相应的文件系统来承载(比如ext4),这样整个链接就是“自定义块格式+用户态块设备+文件系统”,相对于文件系统解决方案,环节更长更复杂,端到端的稳定性不可控;由于块格式不感知上层文件系统,无法区分文件系统的元数据和数据并分别处理(如压缩);无法实现基于文件的安全扫描、热点分析、运行时拦截等图像分析功能;对于多个“二次元娃娃”容器镜像,不修改blob内容是不可能直接合并成一个大镜像的,同样也不可能修改blob内容在过滤部分文件形成子镜像的情况下,这个是文件系统解决方案的天然能力。我们实现的Nydus是一个基于文件系统的容器镜像存储方案。其中,容器镜像文件系统的数据(blobs)和元数据(bootstrap)是分离的,使得原始镜像层只存储文件的数据部分。并将文件分成chunk,每一层blob存储对应的chunk数据;因为使用了chunk粒度,这就细化了去重粒度,chunk级别的去重可以让数据在layer和mirrors之间共享。更容易和更容易实现按需加载。由于元数据是分离合并到一处的,访问元数据不需要拉取对应的blob数据,拉取的数据量小很多,I/O效率更高。NydusRAFS镜像格式如下图所示:2.RAFSv6镜像格式2.1RAFS镜像格式演进在引入RAFSv6格式之前,Nydus使用完全用户态的镜像格式,通过FUSE或virtiofs接口提供服务.但是,用户态文件系统方案在设计上存在以下缺陷:大量的系统调用开销不容忽视,例如深度为1的随机小I/O访问;当容器镜像中有大量文件时,频繁的文件操作会产生大量的fuse请求,导致内核态/用户态上下文频繁切换,造成性能瓶颈;在非FSDAX场景下,从用户态到内核态的buffercopy会消耗CPU;在FSDAX(virtiofsasinterface)场景下,大量小文件会占用DAX窗口资源,存在潜在的性能抖动;频繁切换访问小文件也会产生大量的DAX映射设置开销。这些问题是用户态文件系统方案的天然局限性造成的,如果将容器镜像格式的实现降级为内核态,原则上可以解决上述问题。因此,我们引入了RAFSv6镜像格式,一种依赖内核EROFS文件系统,在内核态实现的容器镜像格式。2.2EROFS文件系统介绍EROFS文件系统从Linux4.19内核开始就存在于Linux主线中。ETC)。userland工具erofs-utils也存在于这些发行版和OINLinux系统定义列表中,社区比较活跃。EROFS文件系统具有以下特点:原生的本地只读块文件系统,适用于各种场景,磁盘格式有最小I/O单元定义;页大小块对齐的未压缩元数据;通过Tail-packinginline技术有效节省空间,同时保持高访问性能;数据以块为单位寻址(mmapI/O友好,无I/O后处理);随机访问友好的磁盘目录格式;核心盘格式非常简单,易于增加payload,可扩展性更好;支持DIRECTI/O访问,支持块设备、FSDAX等后端;同时,EROFS预留了一个引导扇区,用于支持bootloader自启动等需求。2.3RAFSv6镜像格式过去一年,阿里云内核团队对EROFS文件系统进行了一系列的改进和增强,扩展了其在云原生环境中的使用场景,使其适应了容器镜像的需求存储系统,并最终将其呈现为在内核态中实现的容器镜像格式RAFSv6。除了将图片格式下沉到内核态之外,RAFSv6还对图片格式进行了一系列的优化,比如块对齐、更精简的元数据等等。新的RAFSv6图片格式如下:改进后的Nydus图片服务架构如下图所示,增加了对(EROFSbased)RAFSv6图片格式的支持:3.EROFSoverFscache按需加载技术erofsoverfscache是阿里云核心团队为Nydus研发的下一代容器镜像按需加载技术,也是Linux内核原生的镜像按需加载特性。它在5.19版本中被合并到Linux内核主线中。并且被Linux内核权威媒体LWN.net集成到5.19合并窗口高亮功能中(链接见文末):在此之前,几乎所有现有的按需加载在行业是用户模式解决方案。用户态方案涉及频繁的内核态/用户态上下文切换和内核态/用户态之间的内存复制,导致性能瓶颈。当容器镜像全部下载到本地后,这个问题尤为突出。此时,容器运行中涉及的文件访问,仍然会落入用户态的服务进程中。实际上,我们可以解耦按需加载1)缓存管理和2)在缓存未命中时通过各种渠道(如网络)获取数据。缓存管理可以潜入内核态执行,这样当本地镜像就绪时,可以避免内核态/用户态上下文切换。而这也正是erofs相对于fscache技术的价值所在。3.1方案原理fscache/cachefiles(以下统称fscache)是Linux系统中比较成熟的文件缓存方案,广泛应用于网络文件系统(如NFS、Ceph等)。我们对其进行了增强和扩展,以支持本地文件系统(如erofs)的按需加载特性。在这个方案中,fscache接管了缓存管理的工作。此时容器访问容器镜像时,fscache会检查当前请求的数据是否已经被缓存,如果缓存命中(cachehit),则直接从缓存文件中读取数据。整个进程处于内核态,不会落入用户态。否则(cachemiss)需要通知用户态的Nydusd进程处理访问请求。此时容器进程会陷入休眠等待状态;Nydusd通过网络从远端获取数据,通过fscache将数据写入对应的缓存文件。然后通知之前处于睡眠等待状态的进程已经处理完请求;然后容器进程可以从缓存文件中读取数据。3.2方案优点如上所述,当所有图片数据都下载到本地后,用户态方案会导致访问文件的进程频繁陷入用户态,涉及到内核态和用户态之间的内存拷贝。但是在erofsoverfscache下,就不会再困在用户态,这样按需加载才是真正的“按需”,这样在下载的场景下几乎可以不损失性能和稳定性预先加载容器镜像,最终实现了1)按需加载和2)预先下载容器镜像两种场景下真正统一无损的解决方案。具体来说,erofsoverfscache与用户模式解决方案相比具有以下优势。3.2.1异步预取容器创建后,当容器进程还没有触发按需加载(cachemiss)时,用户态的Nydusd可以开始从网络下载数据并写入缓存文件,然后当容器访问的文件位置恰好在预取范围内时,会触发缓存命中,直接从缓存文件中读取数据,不会落入用户态。用户模式解决方案无法实现此优化。3.2.2网络IO优化当触发按需加载(cachemiss)时,Nydusd可以一次从网络下载比当前实际请求的数据量更多的数据,并将下载的数据写入缓存文件。例如,容器访问4K数据触发缓存未命中,而Nydusd实际上一次下载1MB的数据,以减少单位文件大小的网络传输延迟。之后,当容器访问下一个1MB的数据时,它不需要进入用户状态。用户态的方案无法实现这个优化,因为即使触发了cachemiss,用户态的服务进程也实现了这个优化。由于用户态方案实现的缓存管理是在用户态下进行的,所以下一次容器访问都在读放大范围内。在访问文件数据时,还需要陷入用户态,检查当前访问的数据是否已经被缓存。3.2.3更好的性能当所有的图片数据都已经下载到本地后(即不考虑按需加载的影响),erofs的性能明显优于fscache的用户态方案,与原生文件系统的性能,从而达到与原生容器镜像解决方案(未实现按需加载)类似的性能。以下是几种工作负载下的性能测试数据[1]。read/randreadIO下面是fileread/randreadbufferIO的性能对比[2]:“native”表示测试文件直接位于本地ext4文件系统“loop”表示测试文件位于erofs镜像,通过loop设备的DIRECTIO方式挂载erofs镜像“fscache”表示测试文件位于erofs镜像中,通过erofsoverfscache方案挂载erofs镜像“fuse”表示挂载测试文件位于fuse文件系统[3],“performance”一栏为各模式基于原生ext4文件系统的性能,对比其他模式下的性能,可以看出fscache模式下的read/randread与loop模式基本相同,优于fuse模式;但是与原生ext4文件系统的性能还有一定的差距,我们正在进一步分析和优化,理论上该方案可以达到原生文件系统的水平。文件元数据操作测试通过对大量小文件进行去皮[4]来测试文件元数据操作的性能。可以看出,erofs格式的容器镜像元数据性能甚至优于原生的ext4文件系统,这是erofs特殊的文件系统格式造成的。由于erofs是只读文件系统,它的所有元数据都可以紧密排列在一起,而ext4是可写文件系统,它的元数据分散在多个BG(blockgroup)中。典型工作负载测试测试Linux源代码编译[5]在典型工作负载下的性能。可以看出,fscache模式下的Linux编译加载性能与loop模式和nativeext4文件系统基本一致,优于fuse模式。3.2.4高密部署由于erofsoverfscache方案是基于文件的,即每个容器镜像在fscache下表现为一个缓存文件,自然支持高密部署场景。例如,一个典型的node.js容器镜像在该方案下对应~20个缓存文件,那么在部署了数百个容器的机器上,只需要维护数千个缓存文件。3.2.5故障恢复和热升级当所有镜像文件都下载到本地后,对镜像中文件的访问不再需要用户态服务进程的介入,用户态服务进程有更充裕的时间窗口来进行实现故障恢复和热升级。升级功能。在这种场景下,不再需要用户态进程,从而达到与原生容器镜像方案类似的稳定性能(无需实现按需加载)。3.2.6容器镜像统一方案Nydus凭借RAFSv6镜像格式和erofsoverfscache按需加载技术,在runc和rund这两种容器场景下作为容器镜像统一分发方案均适用。此外,更重要的是,erofsoverfscache是??在1)按需加载和2)提前下载容器镜像两种场景下真正统一无损的解决方案。一方面,它实现了按需加载的特性。容器启动时,不需要将所有容器镜像下载到本地,从而帮助极致的容器启动速度。另一方面完美兼容容器镜像已经下载到本地的场景,不再在文件访问时频繁陷入用户态,实现与原生容器镜像方案近乎无损兼容(未实现按需加载)性能和稳定性能。4.展望与致谢后续我们会不断迭代完善erofsoverfscache方案,比如不同容器间的镜像复用、FSDAX支持、性能优化等。另外,目前erofsoverfscache的方案已经集成到Linux5.19主线中,未来我们也会在OpenAnolis(5.10和4.19内核)中实现这个方案,让DragonLizard内核开箱即用.欢迎届时使用。最后,感谢所有在程序开发过程中给予我们支持和帮助的个人和团队。感谢字节跳动和快手对程序的大力支持,包括但不限于社区支持、测试、代码贡献等,欢迎有兴趣者加入龙蜥社区SIG钉钉群(搜索群号:34264214)和Nydus镜像服务钉钉群(群号:34971767)进行交流,让我们共同打造更好的容器镜像生态。[1]测试环境ECSecs.i2ne.4xlarge(16vCPU,128GiBMem),localNVMedisk[2]测试命令"fio-ioengine=psync-bs=4k-direct=0-rw=[read|randread]-numjobs=1"[3]使用passthrough作为fuse守护进程,例如"passthrough_hp"[4]测试"tar-cf/dev/null"命令的执行时间[5]测试"timemake-j16执行时间相关的链接地址”命令可以在2022年5月27日的同一帖子中查看龙蜥蜴公众号(OpenAnolisDragonLizard)。-超过-