十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

NFS与iSCSI选型指南:文件级与块级存储的核心差异与实践

NFS与iSCSI选型指南:文件级与块级存储的核心差异与实践 经常有人问我做虚拟化、搭NAS、给服务器扩展存储到底选NFS还是iSCSI这个问题我在不同项目里被反复问到过。其实两种协议都不是新东西NFS出身于UNIX网络文件共享iSCSI本质上是把SCSI命令搬到IP网络上。它们解决的问题有重叠但使用模型完全不同。我不打算照抄技术手册而是结合我这些年折腾存储的实际经验把NFS和iSCSI的底层逻辑、性能差异、部署细节、踩坑记录一次讲清楚。这篇文章适合正在做虚拟化存储选型、搭NAS、或者准备给服务器扩展存储的人不管是新手还是老手都能找到可以直接用的东西。1. 底层概念是选型的根文件级与块级存储到底差在哪里1.1 NFS是共享目录服务端文件系统说了算NFSNetwork File System本质上是把远程目录挂到本地客户端访问的是一个目录树具体文件读写、元数据管理、权限校验都由服务端文件系统完成。以Linux客户端为例mount一个NFS共享后你看到的是远程文件系统暴露出来的一个“视图”底层可能是ZFS、XFS、ext4或者Btrfs。客户端本身不用关心服务端用什么盘、怎么分区所有细节都被隐藏了。这样设计的好处很明显多个客户端同时挂同一个目录天然可行服务端做快照、备份、配额都方便。坏处也有就是所有元数据和锁操作都在服务端处理一旦目录里小文件特别多服务端CPU和内存开销会明显上涨。我之前遇到过一个项目客户端通过NFS跑一个包含几十万个小文件的构建任务服务端CPU直接被打到100%而这个负载如果是本地磁盘根本不会有这么高的CPU消耗。1.2 iSCSI是远程硬盘客户端自己建文件系统iSCSI把SCSI命令封装在TCP/IP包里让客户端看到一块“远程硬盘”。和NFS最大的区别是服务端提供的是经过target导出的块设备客户端拿到这个块设备后还要自己分区、格式化ext4、XFS、NTFS都行、挂载使用。这样做的好处在于客户端的文件系统就是本地的缓存、锁、事务都在客户端本地完成行为更像一块本地硬盘。数据库这类对IO语义要求高的应用跑在iSCSI上更容易控制数据落盘方式。缺点是一个块设备默认只能被一个客户端以读写方式使用多个客户端同时挂载同一块盘必须依赖集群文件系统OCFS2、GFS2或者虚拟化平台的共享文件系统VMFS否则数据损坏是迟早的事。很多刚接触iSCSI的人在这里栽过跟头以为像NFS那样多台机器同时挂载就行结果数据直接废掉。1.3 一表看懂两者的核心差异对比维度NFSiSCSI数据单位文件块服务端职责管理文件系统提供裸块设备客户端角色远程目录使用者远程磁盘使用者多客户端共享天然支持需要集群文件系统快照能力依赖服务端文件系统依赖存储端或LVM网络依赖非常高非常高典型场景文件共享、虚拟机镜像、容器RWX虚拟机磁盘、数据库、裸设备备份这个表格看下来其实两种协议不是同一个维度的东西。NFS解决的是“文件共享”问题iSCSI解决的是“远程磁盘”问题。选哪个核心取决于你希望存储层为你做什么。2. 性能对比别只看带宽延迟和锁才是关键2.1 延迟模型一次读取要路过多少关口NFS读一个文件客户端要发起RPC请求服务端处理文件系统调用返回数据再经过网络回传。iSCSI读数据时客户端本地文件系统先解析逻辑地址再把块级读请求封装成SCSI CDB发到target经过网络回传后由存储端响应数据块。看起来NFS多了一道“服务端文件系统”的关口但现代NFS服务端有page cache和目录项缓存命中缓存后的延迟并不高。在万兆网络下两者的顺序读性能基本都能跑满网卡真正的差别常常出现在随机小IO和并发写入上。NFS对大量小文件的随机读性能受服务端文件系统元数据操作能力限制而iSCSI则更多取决于target后端存储的真实IOPS能力。我实测过一个场景同一台TrueNAS机器用fio跑4K随机读NFS共享大约能到2万IOPSiSCSI LUN跑同样的负载能到3万IOPS以上。差距来自客户端cache策略和协议栈开销但这种差距在业务层面是否能感知取决于你的应用到底有多敏感。2.2 写路径和锁机制NFS的sync与iSCSI的排他性NFS的写路径受挂载参数影响很大。默认async模式下服务端先把数据写进内存缓存就返回ACK性能好但掉电丢数据的风险高如果使用sync模式每个写请求都要真正落盘才返回性能下降明显。在线业务场景我一般都建议在exports里明确写sync而不是依赖默认值。iSCSI的数据写路径更多取决于存储端target的缓存策略和底层盘性能客户端看到的是正常的块设备语义因此在数据库场景里更容易判断数据到底在不在物理盘上。锁机制方面NFSv4提供了租约锁能在多客户端场景下维护文件一致性。iSCSI则本身不具备文件锁概念因为它在块设备层根本不认识文件。多个iSCSI客户端要共享数据必须在文件系统层解决比如用OCFS2或GFS2。如果你只是想要多个服务器共享一个文件目录做协同那选NFS能省掉一大堆会议成本。2.3 网络硬件瓶颈万兆、巨型帧和多路径不管NFS还是iSCSI网络都会成为瓶颈。建议至少使用万兆网卡同时开启巨型帧MTU 9000来减少包数量、降低CPU开销。iSCSI可以通过多路径MPIO实现冗余和负载均衡NFS虽然也能用bonding聚合链路但故障切换粒度和机制不一样。一个容易忽略的点是网卡队列。单块万兆网卡如果只有单队列高并发IO时CPU软中断消耗会非常严重。建议用支持RSS多队列的网卡配合irqbalance做中断绑核。交换机也要注意缓冲大小存储流量突发严重小缓冲交换机很容易丢包丢包在存储协议里往往表现为延迟飙升而不是直接断开。我在一个项目里把交换机从低端千兆换成带大缓冲的万兆交换机后NFS的4K随机写性能提升了接近50%就是因为丢包率从千分之几降到了零。3. 从零部署把两种协议在真实环境里跑起来3.1 NFS服务端与客户端快速配置以Ubuntu为例服务端安装nfs-kernel-server后编辑/etc/exports文件/data 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)字段解释rw表示读写sync表示同步写no_subtree_check可以减少目录变更时的检查开销no_root_squash允许客户端root保留权限但这个选项生产环境慎用等同于把服务端root权限开放给指定网段的客户端。导出配置用exportfs -rav生效用showmount -e查看已导出列表。客户端挂载命令mount -t nfs 192.168.1.10:/data /mnt/data如果希望重启自动挂载写入/etc/fstab时建议加上_netdev参数192.168.1.10:/data /mnt/data nfs rw,sync,hard,intr,noatime,_netdev 0 0_netdev的意思是这个挂载依赖网络系统启动时会在网络就绪后再挂载避免启动阶段卡死。实际操作中NFS挂载选项里hard和soft的取舍值得一提。hard挂载遇到服务端不可达时会一直等待可能造成客户端进程卡顿soft挂载超时会返回IO错误应用层如果处理不当容易产生数据不一致。我个人的建议生产环境用hardintr允许中断等待但不要轻易用soft。timeo参数可以调整超时时间默认600秒太大可以改成50左右。3.2 iSCSI Target与Initiator配置Linux服务端创建iSCSI target最常用的工具是targetcli整个过程交互式操作。假设你有块空闲磁盘/dev/sdb要导出targetcli cd /backstores/block create namedisk01 dev/dev/sdb cd /iscsi create iqn.2024-01.local.target:data cd iqn.2024-01.local.target:data/tpg1 luns create /backstores/block/disk01 acls create iqn.2024-01.local.client:initiator这段配置创建了一个名为disk01的backstore把它绑定到target端点的LUN0然后设置了ACL只允许IQN为iqn.2024-01.local.client:initiator的客户端访问。客户端安装open-iscsi后iscsiadm -m discovery -t st -p 192.168.1.10 iscsiadm -m node -T iqn.2024-01.local.target:data -p 192.168.1.10 -l登录成功后fdisk -l能看到一个没有分区的新磁盘。之后的过程跟本地盘一样分区、格式化、挂载mkfs.xfs /dev/sdb mount /dev/sdb /mnt/dataCHAP认证在生产环境必须开启否则任何人只要发现你的target IP和IQN就能直接连接磁盘。配置CHAP时在targetcli里设置userid和password客户端iscsiadm节点配置里对应填上CHAP用户名密码即可。3.3 多路径配置MPIO是iSCSI的加分项当服务器和目标存储之间有两条以上物理链路时iSCSI建议配置多路径MPIO。Linux下使用multipath-tools安装完成后配置/etc/multipath.conf使能后通过multipath -ll可以看到聚合后的设备路径通常显示为/dev/mapper/mpatha。多路径的意义不仅是聚合带宽更关键的是链路故障时的无缝切换不会中断正在进行的IO。NFS也可以做类似的事一般通过bonding实现链路聚合。但要注意bonding和MPIO的故障切换逻辑不同bonding在主备模式下切换需要网卡驱动干预MPIO则是在SCSI层通过路径检测自动切换对上层应用更透明。如果对存储链路可靠性要求很高建议iSCSI走MPIONFS则可以考虑在bonding之上再做一层网卡团队。3.4 fio测速的正确姿势别让缓存骗了你很多人说在NFS上跑fio得到的数据“看起来很美”其实是缓存命中导致的结果。要测出真实磁盘性能fio参数设置有几个关键点必须先说清楚。第一必须加direct1跳过客户端文件系统的page cache第二写测试要加fdatasync1确保每次IO都真正落盘第三读测试不要只用单线程建议用numjobs4、iodepth16这样的并发模型模拟真实业务第四NFS场景还要注意服务端缓存测试前最好先写一个大文件然后drop_caches清掉服务端page cache。iSCSI测试同理本机文件系统的缓存也会影响结果。我常用的对比测试命令参考fio -namerandwrite -ioenginelibaio -direct1 -bs4k -numjobs4 -iodepth16 -rwrandwrite -size4G -group_reporting -fdatasync1同样的参数在NFS共享目录和iSCSI挂载点上分别跑一次得到的数据才具备可比性。4. 场景选型虚拟化、数据库、容器到底该怎么选4.1 虚拟化平台NFS和iSCSI在VMware/PVE中的表现ESXi和PVE都原生支持NFS和iSCSI。NFS做虚拟机存储最大的好处是共享和备份简单虚拟机的vmdk/qcow2文件直接放在一个目录里存储端用ZFS做快照非常方便。PVE环境里把NFS存储挂上去之后备份、快照、迁移都变得很顺手。iSCSI做虚拟机存储时每个虚拟机可以独占一个LUN也可以多个虚拟机共享一个VMFS/NTFS分区。iSCSI的锁语义更清晰在VMware环境使用VMFS时多台ESXi同时访问同一个LUN没有问题因为VMFS本身就是集群文件系统。但在PVE场景下如果多个PVE节点同时连接同一个iSCSI LUN直接使用ext4/XFS存储几个节点同时读写就会出问题。这里要专门说说TrueNAS iSCSI允许多个PVE节点连接的坑。iSCSI Target端可以把同一个LUN授权给多个initiator从配置层面完全允许但这不代表安全。多个PVE节点同时读写同一个块设备会导致文件系统元数据撕裂轻则文件损坏重则整盘报废。正确做法有两个方向一是用OCFS2/GFS2集群文件系统二是在LUN上放PVE的虚拟机镜像但所有节点通过NFS共享目录。从运维简化程度来看小规模环境用NFS配合ZFS快照真的省心很多。4.2 数据库场景iSCSI更稳但NFS也不是不能用数据库对IO延迟和事务一致性非常敏感。生产库建议放本地盘或iSCSI块设备因为数据库可以在控制层面精确控制fsync刷盘行为存储端的行为更接近本地块存储。iSCSI提供了标准的块设备接口数据库工具可以直接识别和监控存储状态。NFS下跑数据库不是不行但需要额外处理锁和缓存一致性问题而且网络抖动对数据库的影响会被放大。很多数据库版本的官方文档会明确提示不建议把数据文件放网络文件系统。我见过有人为了省事把MySQL生产库放到NFS上结果一个突发的网络高延迟导致主从切换异常恢复花了一整晚。如果场景是报表库、分析库、测试环境数据丢了可以重建那么NFS的简单共享和弹性扩展反而是优势。比如离线分析任务需要多个节点同时读取同一份样本数据用NFS就非常合适。4.3 容器与Kuberneteslocalpath、NFS与iSCSI的三国演义K8s存储选型里localpath是单节点本地目录速度快但数据不跨节点共享NFS是常见的ReadWriteMany方案适合多个Pod同时读写共享文件iSCSI通过CSI插件可以给Pod提供块设备但通常是ReadWriteOnce意味着同一时刻只有一个节点能挂载。localpath和NFS的取舍本质上就是“速度优先”还是“共享优先”的权衡。如果你跑的是有状态应用但不需要跨节点共享数据用localpath就够如果多个工作负载需要访问同一份数据比如媒体处理流水线、协同编辑服务NFS是几乎最省事的方案。iSCSI在K8s里更多用于数据库容器比如PostgreSQL StatefulSet挂一块iSCSI块设备读延迟明显比NFS稳定但要牺牲共享能力。我个人的习惯容器里的小文件读写密集场景优先考虑localpath或云盘需要多节点读写的用NFS数据库类的再考虑iSCSI或Ceph RBD。5. 踩坑实录与排查技巧5.1 Windows安装报错为什么提示“必须安装在格式化为NFS的分区”不少人在给Windows机器安装系统时遇到这个提示Windows无法安装到这个硬盘空间分区是一个NFS格式。这里有个常见的误解。NFS是网络文件系统Windows安装程序根本不可能把系统装在网络共享上。出现这种提示通常是因为安装过程被某种网络启动或iSCSI引导环境误导或者安装程序识别到的是一个网络磁盘而不是本地物理盘。解决办法是先确认安装目标确实是本地物理盘、虚拟机的虚拟磁盘或者通过iSCSI启动器呈现的裸设备。如果要通过iSCSI安装Windows需要在BIOS/UEFI启用iSCSI启动器或者在安装介质加载阶段按ShiftF10打开命令行用iscsicli命令手动连接目标。还有一个更简单的路子不用网络存储做系统盘把系统装到本地盘数据盘再挂网络存储这样能避开一大堆麻烦。5.2 TrueNAS多个PVE节点连接同一个iSCSI LUN导致文件系统损坏这个坑我踩过也帮别人排查过。现象是多个PVE节点都连接了同一个iSCSI LUN刚开始几天一切正常某天突然某个节点报错文件系统挂载失败或者数据目录出现损坏。根因就是iSCSI不提供多写者的文件系统层保护多个节点同时写同一个块设备最终必然损坏。如果你确实需要多个PVE节点访问同一份数据我建议的优先级是第一选NFS让NAS负责并发第二选集群文件系统OCFS2/GFS2但这要求所有节点都安装对应工具运维门槛较高第三用PVE原生支持的Ceph RBD或者GlusterFS它们底层就是分布式存储天然支持多节点并发。千万不要因为iSCSI配置简单就硬上数据安全永远是第一位的。5.3 NFS挂载慢、断连和权限常见问题速查根据我自己的经验NFS的问题大多集中在权限、协议和超时三类。症状可能原因解决办法Permission deniedexports权限和客户端uid/gid不匹配检查exports选项必要时开启no_root_squash或映射uid重启后挂载失败网络未就绪时尝试挂载fstab加_netdev连接卡死无响应hard挂载遇到服务端不可达改用softtimeo或hardintrStale file handle服务端导出目录被删除重建客户端重新挂载Ubuntu NFSv4协议版本兼容问题服务端只支持NFSv3手动指定vers3Ubuntu系统默认使用NFSv4如果服务端是较旧的NFSv3实现可以在mount参数里加vers3。排查NFS问题常用的命令有showmount -e、exportfs -v、mount -v、dmesg和nfsstat。遇到挂载失败先看dmesg很多核心错误信息都在内核日志里。5.4 fio测试结果波动大的原因与复现技巧fio在NFS和iSCSI上测试结果波动大原因基本集中在几个方向网络设备中断处理不均匀、服务端缓存策略不一致、测试参数设置没有排除缓存干扰、并发模型没有模拟真实负载。要做到可复现建议这样操作同一组fio参数在两种协议上分别跑每次测试前清空客户端和服务端缓存跑三次取中位数同时用sysstat记录iowait和网络队列深度确认瓶颈到底在磁盘还是网络。如果网络队列丢包明显调整MTU和网卡队列参数后重新测试。这样得到的结果才真正能指导选型。最后说点体会存储选型从来不是单纯的技术参数对比而是对数据访问模式、共享需求、可靠性和运维能力的综合权衡。NFS和iSCSI各有一套成熟的使用场景NFS赢在共享简单iSCSI赢在块设备语义完整。我在实际项目里的体会是小环境越来越倾向NFS配合ZFS快照大环境更多是iSCSI搭配集群文件系统或者直接上分布式存储。没有绝对的对错只有适不适合。如果你正在犹豫建议先把负载类型列清楚再做一次标准的fio实测让数据帮你做决定。踩过几次坑之后你会慢慢形成自己的选型直觉。
返回列表