CephFS NFS网关高可用实战:基于NFS-Ganesha与RADOS的架构详解 📅 发布时间:2026/9/20 17:59:22 👁 浏览次数: CephFS 进了生产之后真正让我头疼的往往不是大文件跑不满带宽而是“怎么让老系统挂上来”。数据中心里总有一些设备只认 NFS一些中间件又拒绝安装 ceph-fuse于是 NFS 网关就成了 CephFS 面向旧生态的那扇门。我前后在测试环境和生产环境里搭过多次 NFS-Ganesha 与 RADOS 集群深度整合的高可用 NFS 网关这里面真正难的不是把 ganesha 跑起来而是切换时状态怎么恢复。本文把这套架构的选型理由、部署步骤、故障切换细节和排查经验一次讲透适合正在给 CephFS 加 NFS 出口、或者已经在用单点 Ganesha 想升级成高可用的运维同学。1. 为什么 NFS 网关必须单独做Ganesha 的选型理由1.1 CephFS 客户端接入方式的天然短板CephFS 本身是带 POSIX 语义的分布式文件系统客户端接入方式主要有两种内核态的ceph模块和用户态的ceph-fuse。听起来都不复杂但落到生产现场就完全不是一回事。很多老旧的 BI 工具、视频采集设备、大数据平台的 Hive 外部分区表只认标准 NFS 协议还有一些安全要求严格的业务网段根本不允许你往主机上装额外的客户端内核模块。最直接的替代方案是把 CephFS 挂到一台 Linux 服务器上再用内核 NFS server 导出给下游但这个方案问题很多。第一个问题是 IO 路径变长性能损耗明显。数据从 NFS 客户端到内核 NFS server再落到本地 VFS再进入 Ceph 内核模块最后才到 RADOS中间每一层都有锁和缓存故障定位时根本说不清瓶颈出在哪个环节。第二个问题是双份缓存的一致性。内核 NFS server 和 Ceph 内核模块各自维护 page cache一旦多个客户端同时读写同一批文件缓存失效处理稍微有偏差就会出现数据可见性问题。第三个问题才是最致命的内核 NFS server 是内核态实现的状态全都留在本机内存里把它的配置和锁定状态搬到另一台机器上几乎不可能也就是说这种方案天然做不了高可用。1.2 NFS-Ganesha 为什么适合当网关层NFS-Ganesha 从设计上就不是“把本地目录 export 出去”的普通 NFS 服务。它提供了一套文件系统抽象层也就是常说的 FSAL每一类后端对应一个 FSAL 实现。对接 CephFS 时FSAL 直接通过 libcephfs 和 Ceph 集群通信中间少了本地挂载这一层的二次转发。因为没有本地 VFS 介入Ganesha 节点的角色就变得很轻它更像一个协议转换器把 NFS 请求翻译成 CephFS 操作自己不需要保存太多业务状态。更重要的一点Ganesha 是用户态进程。日志可以一套一套地出线程数可以在配置里调崩溃之后 restart 的成本极低也不需要重启内核。你在生产里做内核 NFS server 的故障演练时一般不敢轻易 kill 内核线程但是 Ganesha 节点我通常直接systemctl restart nfs-ganesha做切换演练心理压力小很多。锁和导出配置的共享能力才是它做高可用的核心。Ganesha 可以把导出配置、NFSv4 锁恢复所需的恢复记录放到 RADOS 对象里多个 Ganesha 节点读同一份状态任何一个节点接管 VIP 后都能看到完整的配置和锁记录。这一点是内核 NFS server 完全做不到的也是我最终选择 NFS-Ganesha 的决定性理由。1.3 高可用的本质是状态管理不是 VIP 漂移很多同事一听高可用第一反应就是 Keepalived 配一个 VIP。这个思路在 TCP 长连接类服务上问题不大但在 NFS 上远远不够。NFSv4 是有状态协议客户端挂载时拿到 clientid打开文件、持有锁的行为都由服务器记录。如果只是把 VIP 从 A 节点切到 B 节点而 B 节点对客户端之前的锁一无所知客户端重连之后要么锁丢失要么出现锁冲突业务那边马上就会报“文件被占用”“写不进去”。所以真正的高可用设计要让多个 Ganesha 节点共享三样东西第一是 export 配置确保所有节点导出的路径、权限完全一致第二是恢复记录也就是客户端的 clientid 和锁记录第三是访问 CephFS 的身份凭据不能只在某一台机器上配置 keyring。RADOS 集群在这套架构里承担的就是状态底座的角色VIP 只是把客户端流量引到某个还活着的网关上。理解了这一层后面看配置和切换脚本就不会跑偏。2. 架构设计与组件拆分RADOS 在 NFS 高可用里的角色2.1 三层拓扑客户端、网关层、Ceph 集群我的生产环境里NFS 网关高可用架构分成三层职责非常清晰。最上层是客户端通过一个虚拟 IP 访问 NFS 服务客户端不需要知道后面到底有几台 Ganesha。中间层是网关层一般跑两到三个 Ganesha 实例每个实例安装相同版本的 ganesha 和 ceph 客户端库节点之间用 Keepalived 做 VIP 漂移或者在前端叠一层负载均衡器。最底层是 Ceph 集群CephFS 负责业务文件读写同时还要有一个独立的 RADOS 池专门存放 Ganesha 的配置和恢复状态。网关层和 Ceph 集群之间的通路是 libcephfs不是普通的 mount。Ganesha 进程起来之后它通过 Ceph 的认证信息连接 MON然后访问 MDS 和 OSD。MDS 负责目录和文件元数据OSD 负责真正的数据对象。这里有一个细节网关节点本身不需要把 CephFS 挂载到本地目录mount 那一步只是用来做验证或者给管理员手工操作不是 Ganesha 运行的依赖。这种分层的好处是故障域清晰。客户端挂载的 VIP 不是绑定在某一个物理主机上的Keepalived 会把 VIP 切到健康节点Ganesha 实例与 RADOS 状态池之间的连接是持久的只要 Ceph 不整体不可用任何一个 Ganesha 拉起之后都能恢复服务。我见过有人把 Ganesha 直接跑在 MON 节点或者 MDS 节点上这种省机器的方式风险很高因为 NFS 网关打满网络带宽时会直接影响 Ceph 的监控面和数据面。2.2 状态池选型必须单独的 replicated 池Ganesha 的配置、export 对象、恢复记录都属于高频率小 IO这种模型和 EC 池并不匹配。我给 NFS 高可用单独创建一个 replicated 池生产环境副本数设为 3不对它开 EC。原因是 EC 池在对象较小、需要做并发锁操作时延迟偏高而且很多锁语义对 EC 支持并不友好。NFS 网关本身对磁盘容量的要求很低它存的是元数据级别的东西用副本方式多消耗的磁盘空间完全可以接受。创建池的命令很简单但 pool 的名字最好一眼能看出用途比如nfs-ganesha-poolceph osd pool create nfs-ganesha-pool 128 128 replicated ceph osd pool application enable nfs-ganesha-pool nfspg_num 这里我给的是 128具体数值要根据 OSD 数量和集群规模调整一般每个 OSD 分摊 50 到 100 个 PG 比较常见。重点是别把 Ganesha 状态池和 CephFS 数据池混用也不要塞进 CephFS 的元数据池。我之前图省事把 Ganesha 的 export 对象直接放进 cephfs_data 池结果一次大并发读写把 OSD 负载打上去之后NFS 网关的配置读取也跟着变慢故障恢复时反而花了更长时间。2.3 多活还是主备两种高可用模式怎么选Ganesha 网关的高可用有两种常见组织方式。第一种是 Active/Active 多活多个 Ganesha 实例都对外提供服务客户端在多个入口之间做负载均衡。这种方式吞吐能力好但对状态共享要求很高NFSv4 的恢复记录必须实时同步到所有节点任何节点加入或退出都要处理老客户端的会话迁移版本兼容性问题一旦出现就非常难查。第二种是 Active/Passive 主备VIP 同时只落在其中一个节点上备节点上的 Ganesha 进程保持运行但不接收客户端流量。主节点故障后 VIP 漂移到备节点备节点因为一直和 RADOS 状态池保持同步接管时不需要从零开始建状态。生产环境我更推荐先用主备模式尤其当你的客户端数量不多、单个网关性能已经够用的时候主备模式架构简单、维护成本低、切换后的行为也容易预测。模式资源利用率故障切换体验实施复杂度适合场景Active/Active高多节点同时干活客户端可能遇到会话切换依赖 LB 和版本兼容高需要仔细验证状态共享大规模、高并发必须多出口Active/Passive中备节点闲置但保持热备VIP 漂移后 NFSv4 可自动恢复低Keepalived 即可完成中小规模、单入口足够、追求省心如果你后续想从主备平滑扩容到多活唯一的前提就是 export 和恢复记录都放在 RADOS 里不要改成本地文件。这也是我在整篇文章里反复强调的一点。3. 核心配置与部署实操从零搭一套 CephFS NFS 网关3.1 准备好 CephFS 和 NFS 专用池部署前先确认 Ceph 集群健康ceph -s里不能有大量恢复中的 PG。CephFS 不存在的话需要先创建数据池和元数据池再创建文件系统ceph osd pool create cephfs_data 256 256 replicated ceph osd pool create cephfs_metadata 32 32 replicated ceph fs new cephfs cephfs_metadata cephfs_data ceph fs status cephfs元数据池的 pg_num 不需要太大副本数建议 3最好放在延迟低的那批 OSD 上。数据池的 pg_num 要结合文件数量和容量预估NFS 网关后面的目录如果异常多PG 数和 MDS 缓存也要同步规划。接着创建 NFS 状态池并给 Ganesha 准备一个专用的 Ceph 认证账号。如果使用 cephadm 管理NFS 集群创建时通常会替你处理一部分认证逻辑但你仍然要明白最小权限的原则。手工部署时我习惯用一个叫client.ganesha的账号权限只授予它必须访问的池和 MDS 路径不给整个集群的管理权限ceph auth get-or-create client.ganesha \ mon allow r \ osd allow rw poolnfs-ganesha-pool, allow rw poolcephfs_data, allow rw poolcephfs_metadata \ mds allow *密钥放到每个 Ganesha 节点的/etc/ceph/ceph.client.ganesha.keyring里文件权限设为 600。这一步最容易踩坑很多人直接用client.adminkeyring权限是够大但一旦 keyring 泄露整个集群都有风险生产上不建议这么干。3.2 使用 cephadm 创建 NFS 集群并导出路径在 cephadm 环境里NFS 集群的创建可以走声明式编排。先创建 NFS 服务再指定它运行在哪些节点上。下面的命令把 NFS 网关调度到node-a和node-b两个节点状态池用刚才建的nfs-ganesha-poolceph orch apply nfs nfs-gwy nfs-ganesha-pool --placementnode-a node-b ceph nfs cluster info nfs-gwy如果你的 Ceph 版本较老不支持在ceph orch apply nfs里直接带 pool就先执行ceph nfs cluster create nfs-gwy nfs-ganesha-pool再用ceph orch apply nfs修正 placement。Ceph 的 NFS 服务在近几个版本里命令格式有过调整动手前先跑一下ceph nfs cluster --help和ceph orch apply nfs --help看当前版本支持的参数。NFS 集群创建后下一步是创建 export。假设 CephFS 里有一个业务目录/apps希望客户端通过虚拟路径/nfs-apps访问执行ceph nfs export create cephfs nfs-gwy /apps \ --pseudo-path /nfs-apps \ --access-type RW \ --squash no_root_squash这里的Path是 CephFS 内部的路径Pseudo是客户端在 NFS 挂载点上看到的路径二者可以不一致。no_root_squash意味着客户端 root 用户写入后保留 root 身份如果你不希望 NFS 客户端拥有过高权限可以改成root_squash。创建完成后用ceph nfs export ls nfs-gwy -v查看导出详情重点看 Pseudo、Path、Access Type 和 Squash 是否和预期一致。3.3 手工部署时 Ganesha 的关键配置没有 cephadm 的旧环境或者你想完全掌控进程行为可以走传统包安装在 Ubuntu 上安装nfs-ganesha和nfs-ganesha-cephCentOS 上对应nfs-ganesha-ceph包。安装完后主配置文件是/etc/ganesha/ganesha.conf。手工模式下我强烈建议在配置中使用RADOS_KV段让 Ganesha 从 RADOS 加载 export 和恢复状态而不是把所有 export 写在本地文件里。典型配置如下NFS_CORE_PARAM { Pseudo_FS_Enable true; NFS_Protocols 4; Enable_NLM false; } NFSV4 { Grace_Period 90; } RADOS_KV { Pool nfs-ganesha-pool; NodeId gwy-node-a; User_Id ganesha; Secret_Access_Key xxxxx; } EXPORT { Export_Id 100; Path /apps; Pseudo /nfs-apps; Access_Type RW; Squash No_root_squash; Protocols 4; Transports TCP; FSAL { Name CEPH; User_Id ganesha; Security_Label false; } }NodeId每个节点必须不同这是 Ganesha 辨别恢复信息来源的身份标识。Enable_NLM false是我个人的强制项NLM 是 NFSv3 时代的锁协议在高可用切换时非常容易造成锁状态混乱干脆禁掉只保留 NFSv4 的锁机制。如果你在配置里写 RADOS_KV同时又手写了本地 EXPORT两个来源的导出对象可能冲突建议二选一要么全部交给 RADOS 管理要么全部写在本地文件。生产上我推荐前者。3.4 客户端挂载与基础验证网关配置完成、VIP 还在测试阶段的时候可以用临时 IP 先验证单节点导出是否正常mount -t nfs4 -o hard,timeo600,retrans2,nfsvers4.1,rsize1048576,wsize1048576 \ 10.0.0.11:/nfs-apps /mnt/apps挂载成功后在目录里写入一个大文件再从另一台客户端读出来做 md5 对比。紧接着测试权限用 root 写、用普通用户写观察文件属主和权限位是否符合预期。不要急着切 VIP单节点验证通过是走向高可用的前提。还要检查一个细节客户端的timeo和retrans参数。高可用切换过程往往有几十秒的中断如果timeo太短客户端会频繁报NFS server not responding如果太长切换完成后恢复感知又太慢。我一般把timeo设在 600retrans设在 2既能容忍切换也不会让客户端长时间傻等。4. 高可用切换的完整落地Keepalived、VIP 与 NFSv4 锁恢复4.1 动手配 Keepalived 之前先把这三个问题想清楚很多人配 Keepalived 只关心 VIP 能不能漂移很少去想漂移之后会发生什么。做 NFS 网关的高可用我建议先把下面三个问题想清楚。第一同一个 VIP 绝对不能在两个节点上同时出现。历史上我在测试环境里用默认配置启动两个state MASTER的节点结果 ARP 表震荡客户端一会儿连 A 一会儿连 BNFS 会话反复重建业务侧出现大量Stale file handle。正确做法是把两个节点都配成BACKUP用priority区分主备用nopreempt控制回切行为。第二新接管节点必须能访问同一份 export 和恢复记录。如果 export 配置只存在主节点的本地文件里VIP 切过去之后新节点导出的路径和你预期完全不同客户端挂载点看起来还在但看到的文件目录已经变了。只有把 export 和恢复记录放到 RADOS 状态池才能保证切换前后客户端看到的是同一个命名空间。第三NFSv4 锁恢复需要给客户端留窗口。Ganesha 启动或者接管时会有 grace period客户端在这段时间内重新声明自己之前持有的锁服务端确认后恢复状态。这个窗口不能设太短否则客户端来不及 reclaim业务进程会认为锁丢失。为了给恢复留足时间我通常把 Grace_Period 配到 90 秒不能想当然地设成 10 秒。# 提前确认两件事 ceph nfs export ls nfs-gwy -v ceph nfs cluster info nfs-gwy4.2 Keepalived 配置实例和健康检查脚本下面是我在双节点主备模式下实际使用的 Keepalived 配置。主节点node-a的 priority 设 110备节点node-b设 100状态都写成BACKUP依靠 priority 选主。VRRP 组播在跨交换机场景下可能丢包所以我用unicast_peer显式指定对端 IP这样更可控global_defs { router_id LVS_NFS } vrrp_script chk_ganesha { script /usr/local/bin/check_nfs_gateway.sh interval 2 fall 3 rise 2 } vrrp_instance VI_NFS { state BACKUP interface eth0 virtual_router_id 51 priority 110 advert_int 1 unicast_src_ip 10.0.0.11 unicast_peer { 10.0.0.12 } virtual_ipaddress { 10.0.0.100/24 dev eth0 } track_script { chk_ganesha } notify_master /usr/local/bin/nfs-gwy-on-master.sh }健康检查脚本要同时检查本机服务和 RADOS 状态池的连通性。只检查 2049 端口是不够的主节点的 Ganesha 进程可能还活着但 Ceph 认证已经失效或者 NFS 状态池已经不可写这时候 VIP 继续留在它手上没有意义。我的脚本是这样写的#!/bin/bash /usr/sbin/ss -ltn | grep -q :2049 || exit 1 /usr/bin/timeout 5 /usr/bin/ceph nfs cluster info nfs-gwy /dev/null 21 || exit 1 exit 0notify_master脚本里只需要做一件事确认本机 Ganesha 正在服务并把 export 重新加载一次。不要在里面做太复杂的操作Keepalived 在状态切换瞬间会调用它脚本卡住会影响 VRRP 状态机。备节点不需要在notify_backup里强行停 ganesha保持进程运行反而能在接管时快速响应因为它是 warm 状态。4.3 NFSv4 锁恢复的原理和要注意的细节VIP 切换后客户端旧 TCP 连接断开新连接落到备节点上。这时候备节点的 Ganesha 可能已经运行了一段时间但它没有处理过这个客户端的锁所以它会在 grace period 内等待客户端 reclaim。客户端在硬挂载模式下会持续重试发送 OPEN、LOCK 等请求时带上原 clientidGanesha 从 RADOS 恢复记录里核对这个 clientid 之前的状态成功后把锁重新绑定到新节点。所以这个机制能不能跑通取决于两个前提一个是恢复记录确实写到了共享的 RADOS 池而不是停留在某个节点的内存里另一个是客户端始终只走 NFSv4 协议。如果客户端用 NFSv3 挂载锁协议变成 NLM它没有完整的 clientid 恢复流程故障切换后的锁状态基本靠猜很容易出问题。这也是为什么我坚持在 ganesha 配置里Enable_NLM false并在客户端 mount 参数里强制nfsvers4.1。切换演练里我会做两件事。第一件事在主节点执行systemctl stop nfs-ganesha观察 VIP 是否在 10 秒内漂移到备节点。第二件事在客户端持续写文件统计中断时间和最终是否恢复写入。正常情况下硬挂载在切换过程会有几十秒的NFS server not responding提示但文件流会自动恢复也就是出现短暂暂停而不是挂死。如果超过两分钟还没恢复优先看备节点的 Ganesha 日志多半是锁 reclaim 超时或者 RADOS 状态池不可写。4.4 回切操作不要抢跑主节点恢复后Keepalived 默认会根据 priority 把 VIP 抢回。这个行为在 NFS 场景下需要谨慎不是越早回切越好。主节点重启后它上面的 Ganesha 需要重新连接 RADOS、加载 export、进入 grace period如果它刚起来就把 VIP 从备节点手上抢走客户端又要经历一次会话迁移等于在已经很脆弱的时间窗口里人为制造了一次故障。我的做法是把 Keepalived 配置里加上nopreempt回切改为人工操作确认主节点 Ganesha 日志正常、ceph nfs cluster info能正常返回再手动降低备节点的 priority 或者执行 notify 脚本把 VIP 平滑切回。回切完成后同样要在客户端观察一次文件写入确认没有出现锁相关报错。生产环境的 NFS 网关切换宁可多等五分钟也不要抢回节点时造成第二次中断。5. 常见问题排查与性能调优实战5.1 高可用故障速查表我在多个环境里踩过的坑基本集中在 export 配置、锁恢复、认证三个方向。下面这个表是我贴在自己运维手册里的速查内容遇到问题时先对着表过一遍能省下大量抓包时间。现象可能原因处理方式客户端挂载报No such file or directoryPseudo 路径和 Path 不匹配或 export 未同步到 RADOS用ceph nfs export ls nfs-gwy -v检查导出重新创建 export客户端挂载报Operation not permittedSquash 策略过严或 CephFS 目录 ACL 拒绝调整squash参数检查 CephFS 目录属主和权限切换后客户端长时间NFS server not respondingVIP 未漂移、健康检查脚本误判、grace period 不足看 Keepalived 日志手动执行健康脚本调大 Grace_Period切换后锁冲突或文件被占用启用了 NLM或客户端以 NFSv3 挂载配置里Enable_NLMfalse客户端强制nfsvers4.1Ganesha 启动报 RADOS 连接失败keyring 权限不足、pool 不存在、NodeId 冲突检查 Ceph 认证、pool 名称、NodeId 唯一性export 配置在节点间不一致本地文件和 RADOS_KV 混用统一改为 RADOS 管理 export删除本地 EXPORT 块备用节点 Ganesha 内存暴涨线程数配置过高或缓存设置过大降低 worker 线程限制 FSAL 缓存大小5.2 切换之后 NFS 写性能下降怎么办故障切换后如果业务恢复了但写性能明显不如切换前先别急着怀疑硬件。最常见的原因是备节点 Ganesha 从 RADOS 恢复记录重新建立状态进程的 cache 是冷启动客户端需要重新缓存目录项和 inode前几分钟的元数据请求会明显偏高。这个现象通常会自行恢复但如果在切换后半小时依然慢就要检查备节点是否和 Ceph 集群之间有额外的网络跳数或者网卡带宽是否被打满。另一个容易被忽略的点是客户端 TCP 连接重建。旧连接断开后客户端会用原来的 mount 参数重新建立连接如果你在 mount 时没有指定nconnect或者rsize/wsize客户端可能会用默认值rwsize 掉到 64KB 甚至更小。我一般会在 mount 参数里固定rsize1048576,wsize1048576避免切换后因为参数丢失导致吞吐下降。还需要检查 Ganesha 的日志级别。生产环境我会把 DEBUG 日志关掉只保留 INFO 和 WARN。曾经有一次排障我在备节点上开着 DEBUG 跑了大半天结果切换后 Ganesha 写日志就把大量 CPU 吃掉了NFS 转发能力直接打了五折。日志很好用但生产环境要让日志让步于性能。5.3 Ceph 侧和 Ganesha 侧的性能关键点NFS 网关的性能并不只取决于 Ganesha 这一层CephFS 本身的表现同样重要。我使用多台 MDS 节点时会先把max_mds从 1 提高到 2并保证足够的 standby MDS 在集群空闲时等待接管。元数据操作密集的 NFS 工作负载MDS 的 CPU 和内存比 OSD 网络更早成为瓶颈这个现象在我这边的生产环境出现得很明显。Ganesha 侧的调优我主要看三个方向。第一个是 worker 线程数CephFS 网关的并发深度通常和文件数量、客户端数量相关线程数设太小会导致请求排队设太大又会抢占 CPU 资源建议从 8 开始压测逐步往上加。第二个是 socket 缓冲区NFS 大 IO 转发非常依赖网络吞吐系统层面的rmem_max/wmem_max要调大。第三个是 RPC 收发包队列Ganesha 有没有专门的NFS_Max_Threads参数取决于版本配置前先grep -ri max_threads看一下当前版本实际支持的参数名不要照抄网上旧教程。Ceph 侧另一个需要关注的是 pool 的 PG 分布。如果 NFS 网关状态池所在的 OSD 同时还承担了 CephFS 的高负载业务状态读写会出现周期性延迟。我最终给 NFS 状态池划分了独立的 OSD 节点虽然看起来浪费了一点硬件但换来了故障切换时恢复记录读写的确定性。对于高可用系统状态读写的延迟比吞吐更值得优化。# 快速查看 Ganesha 当前运行线程数 pidof nfs-ganesha cat /proc/$(pidof nfs-ganesha | awk {print $1})/status | grep Threads5.4 经验复盘改造后的两点血泪教训第一次做高可用的版本我把 export 直接写在各节点本地/etc/ganesha/ganesha.conf里。当时做切换演练主节点挂掉后 VIP 确实飘过去了但备节点导出的路径和主节点完全不同客户端挂载点目录结构变了业务进程写文件全部失败。后来把所有 export 挪到 RADOS 里管再演练三次每次结果都一致这才算是真正的高可用。第二点教训是关于 fencing 的。做高可用的人很容易想到把故障节点强制隔离直接kill掉或者让节点重启HDFS NameNode 那套思路在 NFS 场景下并不适用。NFS 网关的恢复依赖客户端主动 reclaim强制把另一个节点杀掉并不能加快状态迁移反而可能让恢复记录处的锁状态更乱。Keepalived 的健康检查已经能识别半死节点没必要再叠加暴力隔离逻辑把精力放在状态一致性上更有效。今天这套架构里真正值钱的地方不是 VIP 怎么飘而是把配置、锁恢复、认证三样东西全部收敛到 RADOS 集群之后NFS 网关节点变成了真正可替换的无状态入口。