ARTICLE DETAIL

资讯详情

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

NFS与iSCSI选型指南:从文件级到块级,虚拟化存储不再纠结

NFS与iSCSI选型指南:从文件级到块级,虚拟化存储不再纠结 前阵子一个朋友问我想把宿主机上的一堆虚拟磁盘统一放到 TrueNAS 上到底走 NFS 还是 iSCSI他顺手甩过来几篇帖子有说 iSCSI 性能碾压 NFS 的也有说 NFS v4 之后性能根本不差的。我回他一句你先别急着选这俩本来就是两种不同层级的东西光看跑分定存储后面大概率要返工。NFS 和 iSCSI 是存储协议里最容易被人拿来对比、也最容易对比错的两个名字。很多教程只会告诉你一个走文件、一个走块但这句话放到真实环境里意味着什么往往没人展开讲。这篇文章我会从协议机制、网络开销、多主机共享、系统引导这几个维度把这些年我在 PVE、TrueNAS、Ubuntu 服务器上折腾的经验拆开聊最后再给一套可以直接参考的选型框架。无论你是刚接触存储的新手还是正在规划虚拟化集群的老手这篇应当能帮你少踩几个坑。1. NFS 和 iSCSI 的世界观差异文件级与块级不是性能之争1.1 两个协议各解决什么问题NFSNetwork File System是 SUN 在 1984 年提出来的核心目标是让不同操作系统之间共享目录树。客户端发起的是 open、read、write、mkdir 这类文件操作服务器端负责把文件路径解析成具体的磁盘位置再把数据返回给客户端。也就是说文件系统真正的工作是在服务器上完成的。iSCSIInternet Small Computer System Interface的思路完全不同。它就是把传统 SCSI 命令封装到 TCP/IP 包里通过网络送到存储设备。客户端操作系统看到的不是一个共享目录而是一块裸盘——它有自己的分区表、有自己的文件系统ext4、XFS、NTFS 都行甚至有自己的块设备名。你可以在上面跑 fdisk、mkfs、pvcreate操作方式和本地硬盘没有任何区别。这两种差异看起来只是抽象层级不同但后面所有关于性能、共享、兼容性的讨论几乎都由此派生。1.2 当你访问数据时它们各自做了什么我常用一个比喻来解释这两者的区别NFS 就像你在餐厅点菜你只和服务员说要一份红烧肉后厨怎么做、用哪个锅、放多少盐你完全不关心饭做好了直接端到你面前iSCSI 就像把整个厨房的食材送到你家里土豆是土豆、肉是肉炒成什么样、加什么调味全由你自己说了算。所以 nfs 挂载之后客户端用户能直接看到目录、文件、权限这些逻辑概念而 iSCSI 挂载之后客户端看到的是 /dev/sdb、/dev/sdc 这种设备节点能不能看到文件取决于你是否在它上面创建并挂载了文件系统。这个差异带来一个很关键的结果NFS 天生适合多台机器读同一批文件因为文件系统元数据集中在服务器端管理iSCSI 天生适合一台机器独立使用一块磁盘因为它把块设备语义完整地交给了客户端。1.3 一张表看清核心机制差异对比维度NFSiSCSI访问粒度文件级、目录级块级512B/4K 扇区文件系统位置服务端客户端多客户端共享天然支持文件锁由服务端管理不支持普通并发共享需要集群文件系统客户端看到的对象目录挂载点/dev/sdb 这类裸设备典型应用文件共享、虚拟机镜像目录、备份存储数据库数据盘、虚拟机系统盘、Windows 引导盘服务端复杂度较高需要处理路径、权限、锁相对低只要把 LUN 映射出去是否需要客户端额外组件Linux 内核内置 / Windows 有 NFS 客户端Linux 需要 open-iscsi / Windows 内置 iSCSI Initiator看完这个表你应该能意识到iSCSI 并不是NFS 的升级版NFS 也不是配置更简单的 iSCSI。它们根本是在解决两件不同的事只是恰好都可以跑在以太网上而已。2. 性能、延迟与 fio 实测为什么同一条 10GbE 网络下结果可能完全相反2.1 协议栈的开销差在哪里很多人测完 NFS 和 iSCSI 之后很困惑为什么同样是千兆网络iSCSI 的 4K 随机写往往更稳而 NFS 在大量小文件创建时那么吃力先看一条 NFS 读请求的路径客户端 VFS 收到 read() 调用后需要把路径解析成文件句柄然后构造一个 RPC 请求经过 XDR 编码后封装进 TCP到达服务端后服务端要通过文件句柄找到 inode、检查权限、执行实际的磁盘读再把数据编码返回。这一趟里元数据解析和RPC 编解码是跑不掉的消耗。iSCSI 的读请求路径则短不少客户端文件系统把一次读转换成若干个块 I/OSCSI 层生成 CDB 命令比如 READ(10)iSCSI 层把它封装进 TCP/IP 直接丢给存储端。存储端不关心你在读哪个文件的第几个字节它只处理LUN 上偏移多少、长度多少、把数据发回来。少了文件路径解析和 inode 查找协议开销自然低一些。NFS v4 以后引入了 COMPOUND 机制可以把多个操作合并到一个 RPC 里往返比如 LOOKUP、OPEN、READ 一起发大幅减少了原来 NFSv3 那种问一路目录才能打开文件的延迟。这也是为什么我强烈建议新环境一律用 NFSv4 而不是 v3。2.2 缓存是一个不能忽略的变量只比较协议栈还不够缓存层面的差异往往比协议本身对性能影响更大。NFS 在客户端有 page cache在服务端有文件系统缓存。如果后端用 TrueNAS那 ZFS 的 ARC 也会参与缓存。加上 NFS 服务端能看到你正在读哪个文件它就可以做很多预读和元数据优化。而 iSCSI 服务端看到的只是一串块偏移它不知道这些块属于哪个文件也没法判断是否适合预读——除非存储阵列本身有块层预取逻辑。所以会出现一个非常反直觉的现象在某些顺序读场景下NFS 反而可能比 iSCSI 快因为服务端 ZFS NFS 的预读策略会把后续数据主动填进 ARC。但在高并发随机小 IO 场景iSCSI 少了元数据开销延迟会更稳定。真实环境里不要拿别人测出来的数据来决定用谁因为你不知道对方的缓存配置、机械盘还是全闪、MTU 是否调了 9000。这些变量随便动一个结论就可能反过来。2.3 用 fio 测 NFS 和 iSCSI 的正确姿势fio 是大家最常用的存储性能测试工具但很多人在挂载 NFS 之后直接用默认参数去测测出来的数值往往失真严重。先给一组我常用的基础测试命令# 小文件随机 4K 读direct1 绕过客户端 page cache fio --namerandread --ioenginelibaio --iodepth32 --rwrandread \ --bs4k --size2G --numjobs4 --direct1 --runtime60 \ --directory/mnt/nfs_test --group_reporting # 大文件顺序写验证带宽上限 fio --nameseqwrite --ioenginelibaio --iodepth32 --rwwrite \ --bs128k --size4G --numjobs1 --direct1 --runtime60 \ --directory/mnt/nfs_test --group_reporting测 NFS 时有一个容易踩的坑libaio 引擎在 NFS 挂载点上不一定可用某些内核版本会直接报ioengine libaio failed。这时候要么改用pvsync2要么接受 buffered I/O 的影响。如果你确实想测网络文件系统真实可用性能可以保留direct0但加sync1测的是每次提交都等待落盘的效果。测 iSCSI 时更简单直接对块设备操作就行# 确认 iSCSI 已连接 lsblk -S | grep iscsi # 裸设备随机读 fio --namedev-randread --filename/dev/sdb --direct1 \ --rwrandread --bs4k --iodepth32 --numjobs4 --runtime60 --group_reporting要注意裸设备测试测的是网络传输 存储后端的极限不代表文件系统在上面跑应用的真实性能。如果你已经格式化成了 ext4 或 XFS最好挂载后再做文件级测试这样更贴近实际。2.4 我在实测中看到的典型特征基于同一台 TrueNAS、同一组机械盘 少量 SSD 缓存的测试我大致得出过这样的规律128K 顺序读写NFS 和 iSCSI 在千兆网络下差距很小通常都顶在 110MB/s 左右iSCSI 略高但高不到碾压。4K 随机读iSCSI 的平均延迟比 NFS 低 20%~30%但 NFS 在服务端缓存命中的情况下反而更好。大批量小文件创建/删除NFS 明显吃亏因为每个文件都要做若干次元数据操作锁的开销也会放大。同一条 10GbE 网络下两者的带宽上限都可以跑满瓶颈基本在存储后端而不是协议本身。所以我的建议是决定用 NFS 还是 iSCSI不要只盯着跑分。跑分的意义是验证你当前的拓扑、缓存和网络能否满足应用需要而不是在两套不同架构之间选冠军。3. 多主机共享场景一台 TrueNAS 同时接多台 PVENFS 和 iSCSI 谁更安全3.1 共享文件与共享块设备锁的语义完全不同多主机共享是 NFS 和 iSCSI 差距最大的地方。NFS 天然是共享协议多台客户端同时挂载同一个导出目录服务端负责处理并发和文件锁。你在客户端 A 上修改文件客户端 B 在很短的时间内就能看到变更取决于缓存和协议版本这是 NFS 的基本能力。iSCSI 天生是点对点的。默认情况下一个 LUN 映射给一台主机就是那块盘的唯一主人。如果你把同一个 LUN 映射给两台主机两台机器都能看到并写入这块盘但彼此之间没有任何协调机制它们会各自维护自己的文件系统缓存和块分配表。一旦两台机器同时写同一个区域文件系统结构损坏几乎是必然的。说直白点iSCSI 多主机共享就像把同一块物理硬盘同时接到两台电脑上两台电脑都觉得自己独占它。物理上可能没问题逻辑上很快会乱套。3.2 TrueNAS 允许多个 PVE 连接 iSCSI但别当成共享盘用很多人会在 TrueNAS 的 iSCSI Target 里看到 Initiator Group 配置允许一组 IP 地址连进来于是想当然地认为那我把两个 PVE 节点都加进来它们就能共享这个 iSCSI 盘了。这里一定要分清允许连接和允许并发共享。TrueNAS 的允许多个发起方连接主要面向 VMware 那种集群文件系统场景。VMware 的 VMFS 是专门的共享文件系统多台 ESXi 主机并发访问同一个 VMFS LUN 是有锁机制的。而 Proxmox VE 默认不是这样的——当你把 iSCSI LUN 加入 PVE 节点时节点会在 LUN 上创建 LVM 卷组然后划分出 LV 给虚拟机使用。LVM 本身没有集群锁两个节点同时对同一个 LUN 执行pvscan、vgchange、lvcreate就会开始互相踩踏。所以我的结论很明确如果只是单台 PVE 节点用 iSCSI LUN 存放本机 VM 磁盘完全没问题。如果想让多台 PVE 节点共享同一批虚拟机镜像并支持在线迁移优先用 NFS 导出目录所有节点挂同一个 NFS 路径。如果非要在多台 PVE 之间共享 iSCSI LUN需要在上层叠加集群文件系统如 OCFS2但这套复杂度不是一般用户该承受的。3.3 PVE 集群用 NFS 的锁与一致性问题既然提到 PVE 集群就多说几句 NFS 的锁问题。NFS 在 v3 时代用的是一个独立的锁协议Network Lock Manager锁状态由 lockd 和 statd 进程维护一旦客户端异常断开服务端容易出现 stale lock要等一段时间才能清除。这导致很多人在 NFS 上跑数据库或者虚拟机镜像时会遇到明明没人在用但文件锁还在的诡异情况。NFSv4 把锁协议合并到了主协议里基于租约lease自动回收过期锁。对 PVE 这种需要频繁加锁保护 VM 镜像的环境来说我强烈建议挂载时显式指定 NFSv4mount -t nfs4 -o vers4.2,hard,timeo600,retrans2 server:/export /mnt/storage为什么用 hard因为 PVE 虚拟机镜像对存储 I/O 的一致性要求极高soft 模式在网络抖动时直接返回 EIO很容易导致客户机文件系统损坏。宁可让虚拟机短暂卡住也不能让读写直接报错。另外NFS 上跑 qcow2 镜像时PVE 依赖文件锁保护同一块磁盘不被两个节点同时启动。如果你把挂载选项里的nolock加上去了等于告诉内核不要用任何锁这是非常危险的配置。3.4 NFS 版本选择对锁的影响如果你的客户端和服务器都支持 v4.2现代内核默认支持就不要再迁就旧系统去用 v3 了。v3 当年是兼容性最好的选择但放到今天v4 在性能、安全、锁语义上都有了明显提升尤其是多主机场景v4 的租约锁机制比 v3 的 NLM 可靠很多。TrueNAS 上导出 NFS 时可以在 Advanced Settings 里限制最小版本我会把最小版本设为 NFSv4分给 PVE 或 Ubuntu 客户端使用几乎没遇到过锁不释放的问题。4. 引导场景与操作系统兼容性NFS 无盘启动、Ubuntu 根文件系统、Windows 安装报错4.1 NFS 挂载根文件系统无盘启动的配置NFS 最强的场景之一是无盘启动。一台没有本地硬盘的主机通过 PXE 从网络加载内核再通过 NFS 挂载根文件系统完全从网络盘启动进入完整系统。很多开发板、瘦客户机、自动化测试集群都是这么干的。在 Ubuntu 上配置 NFS root 启动核心就三件事。第一服务端导出你要用的根目录。假设根文件系统在/srv/nfsroot/ubuntu修改/etc/exports/srv/nfsroot/ubuntu *(rw,sync,no_root_squash,no_subtree_check,no_wdelay)注意这里的no_root_squash因为客户端启动后要读写一些 root 权限才允许操作的文件如果不开很多系统初始化脚本会失败。第二客户端 initramfs 里要有网络和 NFS 模块。在 Ubuntu 客户端生成 initramfs 的这台机器上改/etc/initramfs-tools/initramfs.confMODULESnetboot BOOTnfs然后执行update-initramfs -u -k all重新生成 initramfs。第三启动时内核参数要指向服务端。在 GRUB 配置里增加root/dev/nfs nfsroot192.168.1.20:/srv/nfsroot/ubuntu,vers4,tcp ipdhcp rwroot/dev/nfs是让内核走 NFS root 的特殊标记nfsroot后面写服务端地址和导出路径。启动过程中客户端会通过 DHCP 拿到 IP随后挂载 NFS 作为根。这种模式我在自动化测试集群里经常用所有节点共享同一个只读系统镜像只要在一台机器上安装好系统丢到 NFS 共享目录其余几十台机器全部从这个镜像启动。管理成本极低而且因为根文件系统是只读的系统被跑坏了几秒钟就能重启恢复。4.2 为什么 Windows 无法安装到 NFS 分区网上流行过一个搜索词Windows 必须安装在格式化为 NFS 的分区Windows 无法安装到这个硬盘空间。很多人第一次看到是懵的。要解释这个得先搞清楚 Windows 安装程序到底能识别哪几类磁盘。本地磁盘SATA/NVMe/IDE通过 iSCSI 连接的网络磁盘通过 FC、SAS HBA 卡直通过来的磁盘这些都有个共同特征在 Windows 看来是块设备有扇区、有分区表、能写引导记录。NFS 挂载上来是什么是一个网络驱动器盘符比如 Z:。Windows 自带的 NFS 客户端只能做文件级读写它无法对 NFS 共享创建分区表也无法写 MBR/GPT更不可能在上面安装引导程序。所以 Windows 安装程序看到的所有磁盘列表里根本不会有 NFS 共享于是你尝试手动让它装到某个网络路径时它就弹出那句经典的Windows 无法安装到这个硬盘空间分区是一个 NFS 分区之类的报错。说句实话这个报错其实是把矛头指错了方向——不是分区分错而是 Windows 不支持 NFS 作为引导介质。如果你确实想把 Windows 装到网络存储上正确做法是用 iSCSI。流程也很简单Windows 安装程序启动后按 ShiftF10 打开命令行用内置的 iSCSI Initiator 连上目标存储把 LUN 变成系统可识别的一块磁盘然后回到安装界面刷新就能看到它了。命令行大概是iscsicli AddTargetPortal 192.168.1.20 iscsicli ListTargets iscsicli LoginTarget IQN如果你用的是带 iSCSI 网卡或软件发起方的批量部署环境也可以在安装前通过应答文件或 WDS 配置来加载 iSCSI 驱动。总之Windows 要走网络启动/网络系统盘别碰 NFS老老实实用 iSCSI。4.3 Ubuntu 客户端挂载 NFS 的细节日常使用里Ubuntu 挂载 NFS 是出现频率最高的事。很多人只执行一句mount -t nfs4但到了重启或网络抖动时才发现坑很多。先装客户端sudo apt install nfs-common手动挂载sudo mkdir -p /mnt/storage sudo mount -t nfs4 -o vers4.2,hard,timeo600,retrans2 192.168.1.20:/mnt/tank/storage /mnt/storage如果要写入/etc/fstab我推荐用_netdev和x-systemd.automount组合192.168.1.20:/mnt/tank/storage /mnt/storage nfs4 rw,_netdev,hard,timeo600,retrans2,x-systemd.automount,x-systemd.mount-timeout15 0 0_netdev的意思是这是一个网络设备不在网络就绪前挂载避免开机时因为 NFS 不可达而卡住。x-systemd.automount是把挂载推迟到有人真正访问该目录时才触发效果很好。排查维护时用nfsstat -m看当前挂载参数用mountstats查看每个挂载点的详细 RPC 统计能快速判断是不是网络重传太多导致延迟异常。5. 我的选型框架不要再用跑分定方案按照这六个维度去判断5.1 六个选型维度聊完协议细节和实战场景我把自己做选型时习惯过一遍的六个维度整理出来下次纠结 NFS 和 iSCSI 时直接对照着走。访问方式你需要的是一批文件还是一块独立磁盘文件共享、媒体资料库、容器镜像目录选 NFS 更自然数据库数据盘、VM 系统盘、裸设备分配选 iSCSI。多主机共享同一份数据会不会被多台服务器同时读写会就用 NFS不会且每台机器需要独占存储用 iSCSI 更稳。性能特征你的应用是大量顺序读、还是高并发随机 IO前者 NFS 的缓存优势能发挥后者 iSCSI 的延迟表现更可预测。客户端引导需求Windows 要网络引导、Linux 无盘启动无盘 Linux 可以选 NFSWindows 请优先 iSCSI。维护复杂度你是否能接受为 iSCSI 做多路径、LUN 映射权限、以及一 LUN 一主机的纪律如果不能NFS 的共享目录用起来模式显然更省心。备份与快照你的备份方案是文件级的 Rsync、Borg还是存储阵列级快照NFS 直接对目录做快照非常清晰iSCSI 快照往往针对整个 LUN粒度更粗但更底层。5.2 常见场景的推荐组合场景我更推荐理由家庭 NAS / 媒体服务器NFS多设备共享简单权限模型直观PVE 集群共享 VM 镜像目录NFS天然支持多节点文件共享配合 qcow2 锁够用VMware ESXi 共享存储iSCSIVMFS 是共享块文件系统iSCSI 配合很成熟Windows 系统网络启动iSCSIWindows 不支持 NFS 作为引导设备单台 Linux 数据库服务器iSCSI提供裸块设备便于数据库自行管理文件系统Ubuntu 无盘启动工作站NFS配置成本低一根网线即可启动5.3 几个我很想反复强调的实用小技巧先说网络。无论选哪个我都建议先跑一遍iperf3 -c storage_server_ip -t 30确认网络带宽和丢包率正常再谈存储协议。尤其是走 10GbE 网络时MTU 是否统一设置为 9000、网卡是否开启多队列对 NFS 和 iSCSI 的影响远大于协议本身的差异。再说缓存。如果你选 NFS一定要在服务端把存储系统的缓存配置好。TrueNAS 上就是尽量给 ZFS 分配更多 ARC 内存并考虑加一块 SSD 作为 L2ARC。如果你选 iSCSI注意客户端缓存也能救命Linux 上调整vm.dirty_ratio、vm.dirty_background_ratio对大批量顺序写会有明显效果。最后说测试。千万别拿默认参数跑一次 fio 就下结论。把direct、sync、iodepth、numjobs这几个变量都跑出交叉数据再结合你自己的应用负载才知道哪个协议在这个特定的网络、存储后端、操作系统组合下更舒服。我自己的使用倾向是小团队和家庭实验室能用 NFS 解决的问题我尽量用 NFS因为它好维护、好迁移、出问题是也容易定位——目录权限、导出选项、锁状态都比 iSCSI 更容易排错。但涉及数据库裸卷、Windows 引导这种需要块语义的场景我不会硬拿 NFS 去顶该上 iSCSI 就上 iSCSI。这两种协议从来不是谁代替谁的关系它们只是同一片数据中心的两种搬运方式。搞清楚你手里的东西是文件还是块搞清楚有多少人同时在碰它选型这事儿就已经做对了一半。剩下的一半无非是留足测试时间别让跑分煽动你。
返回列表