随着业务规模的不断扩大和数据访问需求的日益增长,现有的文件共享服务面临着诸多挑战,如性能瓶颈、扩展性不足等问题。为了有效解决这些问题,我们考虑引入NFS-Ganesha作为新一代的高性能网络文件系统解决方案。
NFS-Ganesha是一款基于用户空间的高性能网络文件系统服务器,它支持多种存储后端,并且能够提供高吞吐量、低延迟的数据访问能力。通过采用NFS-Ganesha,不仅可以显著提升文件系统的性能表现,还能增强系统的可扩展性和可靠性,满足未来业务发展的需求。
本报告旨在全面评估NFS-Ganesha组件引入的可能性及其对现有系统的影响。我们将从技术架构、性能、安全性等多个维度进行深入探讨,并结合实际应用场景提出具体的实施方案和技术建议。此外,还将对比分析其他可能的技术方案,以确保最终选择的最佳实践能够最大程度地满足业务需求,同时兼顾成本效益和技术可行性。
NFS-Ganesha是一个运行在用户空间的NFS文件服务器,能够处理多个版本的NFS协议(如NFSv3、NFSv4、NFSv4.1等)。NFS-Ganesha 是一个功能强大且灵活的开源文件系统,适用于各种存储需求和应用场景,从传统的文件共享到现代的容器化和云原生环境。
NFS-Ganesha每个模块负责不同的任务和目标,例如缓存管理模块只负责管理内存中的数据。
其核心架构包括多个独立的模块,如RPCSEC_GSS模块用于数据传输,Memory Manager模块负责内存管理。
提供前端访问多协议支持。支持NFSv2、NFSv3、NFSv4、NFSv4.1以及pNFS和9p.2000L协议。可以同时支持所有这些协议,提供灵活的兼容性。
当我们在现有的NFS应用中遇到问题时,NFS-Ganesha作为一个高性能的网络文件系统服务器,能够有效地解决许多常见的挑战。下面是从NFS应用中遇到的问题角度出发,给出了NFS-Ganesha解决问题的信息:
传统的NFS服务器可能会遇到性能瓶颈,尤其是在高并发访问场景下。
NFS-Ganesha为用户提供了如下特性,解决或者改善了上述问题:
随着业务的增长,单一NFS服务器难以满足大规模数据访问的需求。
NFS-Ganesha为用户提供了如下特性,解决或者改善了上述问题:
传统NFS服务器可能存在安全漏洞,容易遭受攻击。
NFS-Ganesha为用户提供了如下特性,解决或者改善了上述问题:
单点故障可能导致服务中断,影响业务连续性。
NFS-Ganesha为用户提供了如下特性,解决或者改善了上述问题:
传统NFS服务器的管理和维护工作较为繁琐。
NFS-Ganesha为用户提供了如下特性,解决或者改善了上述问题:
不同版本的NFS客户端之间可能存在兼容性问题。
NFS-Ganesha为用户提供了如下特性,解决或者改善了上述问题:
通过上述解决方案,NFS-Ganesha不仅能够解决现有NFS应用中遇到的各种问题,还能够提供更高效、更安全、更易于管理的服务。这对于构建稳定可靠的大规模分布式存储系统来说是非常重要的。
NFS-Ganesha 是一个基于模块的用户空间文件服务器,支持 NFSv3、v4、v4.1 和 pNFS 协议,并且可以运行在大多数 UNIX/Linux 系统上。其架构设计使得它能够通过文件系统抽象层(FSAL)将后端存储机制抽象成一个统一的 API,从而提供给客户端访问。
模块化设计:NFS-Ganesha 是一个基于模块的程序,每个模块负责不同的任务和目标。例如:
用户空间运行:NFS-Ganesha 在用户地址空间中运行,而不是作为操作系统内核的一部分。
内存管理是开发 Ganesha 时比较大的问题,因为大多数 Ganesha 架构中的所有模块都必须执行动态内存分配。 例如,管理 NFS 请求的线程可能需要分配用于存储所请求结果的缓冲器。 如果使用常规的 LibC malloc / free 调用,则存在内存碎片的风险,因为某些模块将分配大的缓冲区,而其他模块将使用较小的缓冲区。 这可能导致程序使用的部分内存被交换到磁盘,性能会迅速下降的情况。
因此 Ganesha 有一个自己的内存管理器,来给各个线程分配需要的内存。内存管理器使用了 Buddy Malloc algorithm,和内核使用的内存分配是一样的。内存分配器中调用了 madvise 来管束 Linux 内存管理器不要移动相关页。其会向 Linux 申请一大块内存来保持高性能表现。
管理 CPU 相比较内存会简单一些。Ganesha 使用了大量的线程,可能在同一时间会有几十个线程在并行工作。开发团队在这里用到了很多 POSIX 调用来管理线程,让 Linux 调度进程单独处理每一个线程,使得负载可以覆盖到所有的 CPU。
开发团队也考虑了死锁情况,虽然引入互斥锁可以用来防止资源访问冲突,但是如果大量线程因此陷入死锁状态,会大大降低性能。因此开发团队采用了读写锁,但是由于读写锁可能因系统而异,因此又开发了一个库来完成读写锁的转换。
当一个线程池中同时存在太多线程时,这个线程池会成为性能瓶颈。为了解决这个问题, Ganesha 给每一个线程分配了单独的资源,这样也要求每个线程自己处理垃圾回收,并且定期重新组合它的资源。同时 ”dispatcher thread” 提供了一些机制来防止太多线程在同一时间执行垃圾回收;在缓存层中垃圾回收被分成好几个步骤,每个步骤由单独代理处理。经过生产环境实测,这种设计时得当的。
关联寻找功能在 Ganesha 被大量使用,比如我们想通过对象的父节点和名称来寻找对象元数据等类似行为是很经常的,因此为了保证 Ganesha 整体的高性能,关联寻找功能必须非常高效。
为了达到这个目的,开发团队采用了红黑树,它会在 add/update 操作后自动冲平衡。由于单棵红黑树会引发进程调用冲突(多个进程同时 add/update,引发同时重平衡),如果加读写锁在红黑树上,又会引发性能瓶颈。因此开发团队设计了红黑树数组来解决了这个问题,降低了两个线程同时访问一个红黑树的概率,从而避免了访问冲突。
运行 Ganesha 需要很多线程同时工作,因此设计一个大型的线程守护程序在设计之初尤为重要,线程分为以下不同类型:
在上文中提到,Ganesha 使用了大片内存用于建立元数据和数据缓存。我们先从元数据缓存开始讲起。metadata cache 存放在 Cache Inode Layer( MDCache Layer )层 。每个实例对应一个命名空间中的实例(文件,符号链接,目录)。这些 Cache Inode Layer 中的实例对应一个 FSAL 中的对象,把从 FSAL 中读取到的对象结构映射在内存中。
Cache Inode Layer 将元数据与对应 FSAL 对象 handle 放入哈希表中,用来关联条目。初版的 Ganesha 采用 ’write through’ 缓存策略来做元数据缓存。实例的属性会在一定的时间(可定义)后过期,过期后该实例将会在内存中删除。每个线程有一个 LRU(Least Recently Used) 列表,每个缓存实例只能存在于 1 个线程的 LRU 中,如果某个线程获得了某个实例,将会要求原线程在 LRU 列表中释放对应条目。
每个线程需要自己负责垃圾回收,当垃圾回收开始时,线程将从 LRU 列表上最旧的条目开始执行。 然后使用特定的垃圾策略来决定是否保存或清除条目。由于元数据缓存应该非常大(高达数百万条目),因此占满分配内存的 90%(高位)之前不会发生垃圾回收。 Ganesha 尽可能多得将 FSAL 对象放入缓存的‘树型拓扑’中,其中节点代表目录,叶子可代表文件和符号链接;叶子的垃圾回收要早于节点,当节点中没有叶子时才会做垃圾回收。
File Content Cache 数据缓存并不是独立于与 Inode Cache,一个对象的元数据缓存和数据缓存会一一对应(数据缓存是元数据缓存的‘子缓存’),从而避免了缓存不统一的情况。文件内容会被缓存至本地文件系统的专用目录中,一个数据缓存实例会对应 2 个文件:索引文件和数据文件。数据文件等同于被缓存的文件。索引文件中包含了元数据信息,其中包含了对重要的 FSAL handle。索引文件主要用于重建数据缓存,当服务器端崩溃后没有干净地清掉缓存时,FSAL handle 会读取索引文件中的信息来重建元数据缓存,并将其指向数据文件,用以重建数据缓存实例。
当缓存不足时,worker thread 会查看 LRU 列表中很久未被打开的实例,然后开始做元数据缓存回收。当元数据缓存回收开始时,数据缓存的垃圾回收也会同时进行:在回收文件缓存实例时,元数据缓存会问询数据缓存是否认识该文件实例,如果不认识则代表该数据缓存已经无效,则元数据回收正常进行,并完成实例缓存回收;如果认识,对应的文件缓存以及数据缓存均会被回收,随后对应的元数据缓存也会被回收。这样保证了一个数据缓存有效的实例不会被回收。
这种方式很符合 Ganesha 的架构设计:worker 线程可以同时管理元数据缓存和数据缓存,两者一直保持一致。Ganesha 在小文件的数据缓存上采用 ’write back’ 策略,如果文件很大的话则会直接读取,而不经过缓存;
FSAL 是相当重要的模块。FSAL 本身给 Inode Cache 和 File Content Cache 提供了通用接口,收到请求后会调用具体的 FSAL(FSAL_SNMP, FSAL_RGW 等)。FSAL 中的对象对应一个 FSAL handle。由于 FSAL 的语义设计与 NFSv4 很相似,因此开发和可以自己编写新的 FSAL API 来适配 Ganesha。Ganehsa 软件包还提供了 FSAL 源代码模板。
客户端请求:当 NFS 客户端发起一个请求时,它会通过 NFS 协议与 NFS-Ganesha 服务器进行通信。
FSAL 调用:NFS-Ganesha 使用 FSAL 将请求转发到相应的后端存储机制。例如,如果后端是 Ceph,则 NFS-Ganesha 会将请求传递给 Ceph 并获取响应。
数据处理和返回:后端存储机制处理请求并返回结果,NFS-Ganesha 将这些结果封装成 NFS 协议所需的格式并返回给客户端。
缓存机制:为了提高性能,NFS-Ganesha 可以使用写通过策略来缓存元数据。实例的属性会在一定时间后过期,过期后该实例将会在内存中删除。
如下图所示:
NFS-Ganesha 可以通过外部动态提供程序(External动态提供程序)在 Kubernetes 中使用。例如,nfs-ganesha-server-and-external-provisioner 是一个针对 Kubernetes 1.14+ 版本的动态存储提供商,可以快速而轻松地部署几乎在任何地方都能工作的共享存储解决方案。
基于 eBPF 的性能分析与故障诊断工具 eNFSanalyzer 能够通过内核模块实现对 NFS 请求的快速回复,这种方法具有低开销、低侵害、高性能等优势,并支持被广泛使用的 NFS-Ganesha。此外,kNFS 提供了对 NFS-Ganesha 的内核增强功能,旨在提供更高性能和更安全的网络文件系统。
NFS-Ganesha 还可以与其他分布式存储系统如 GlusterFS 结合使用,进行文件服务迁移和重构。此外,它也可以作为 Ceph 对象网关的接口,为应用提供 POSIX 文件系统接口到 Ceph 对象存储。
传统NFS服务在容器化环境中部署较为复杂,需要额外的配置和管理。
NFS-Ganesha天生支持容器化部署,可以轻松集成到Kubernetes等云原生平台中。通过使用外部动态提供器(如kubernetes-sigs/nfs-subdir-external-provisioner),可以实现自动化的存储资源管理。此外,NFS-Ganesha还可以与云服务商提供的存储服务结合使用,进一步提升云原生环境下的存储解决方案。
从云原生角度来看,NFS-Ganesha相较于传统NFS服务具有显著的优势。它在用户态运行,具有更好的可移植性和灵活性;支持高可用性和多种存储后端;性能优异且资源利用率高;天然支持容器化和云原生环境;并且具有良好的可扩展性和灵活性。因此,在云原生架构下,NFS-Ganesha是一个更优的选择。
传统NFS服务的性能可以通过调整参数、使用高速网络、合理规划文件系统等方式进行优化。例如,服务器端可以设置noatime和修改tcp_slot_table_entries参数,客户端可以调整timeo。然而,传统NFS在处理小文件时性能较差,尤其是在网络延迟较高的情况下。
NFS-Ganesha则提供了更高的灵活性和可扩展性,支持NFSv2、NFSv3和NFSv4协议,并在许多大型高性能计算(HPC)环境中得到广泛应用。NFS-Ganesha通过模块化设计,每个模块负责各自的任务和目标,保证了后期扩展的便捷性。
传统NFS在处理小文件时性能较差,尤其是在网络延迟较高的情况下。然而,通过优化配置和使用高速网络,可以显著提升其性能。
NFS-Ganesha在处理小文件时表现出显著的速度提升,尤其是在网络延迟较低的情况下。例如,在1KB大小的文件上,vNFS比基准快19倍(读取)和5倍(写入)。这表明NFS-Ganesha在处理小文件时具有显著的性能优势。
NFS-Ganesha提供了高可用性和故障恢复能力,能够在节点故障时无缝切换到另一个节点,确保服务的连续性。例如,在高可用性环境中,如果一个NFS-Ganesha服务器故障,客户端可以无缝连接到另一个NFS-Ganesha服务器。
传统NFS服务在高可用性方面相对较弱,通常需要手动干预和配置复杂的故障恢复机制。
NFS-Ganesha支持多种存储后端,如CephFS,并通过文件系统抽象层(FSAL)实现与不同存储系统的集成。此外,NFS-Ganesha还支持文件追加和服务器端复制等协议扩展。
传统NFS服务主要支持NFSv4协议,并且在协议扩展方面相对有限。
名称 | NFS-Ganesha | 备注 |
---|---|---|
开源协议 | 未公布协议 | |
部署方式 | 全平台(裸金属、容器、K8s) | |
支持语言 | 所有具有网络访问能力的语言 | |
扩展性 | 支持 | |
安全性 | 支持 | |
管理复杂性 | 支持 | |
兼容性 | 支持 | |
协议 | 多协议 | |
运行日志 | 有 | |
高可用 | 支持 | |
分布式 | 支持 |
NFS-Ganaesha是云原生环境下nfs应用生态的适应性发展项目。对于应用广泛的nfs服务,提供了云原生环境下的解决方案。云原生环境对应用提出的分布式,高可用,扩展性和安全性等方面一系列新问题,NFS-Ganaesha都能够提供解决方案,从而为用户提供更好的适应云原生环境的存储服务。