有时候真正搞懂一个技术问题,往往是从一个让人抓狂的报错开始的。
最近逛技术社区的时候,看到有位朋友在折腾 Windows 安装,报错信息大概是“windows 无法安装到这个硬盘空间,分区是一个 NFS 分区”。他原本想着,既然 iSCSI 能通过网络把远端存储变成“本地磁盘”来装系统,那 NFS 是不是也能这么干?结果直接被安装程序拦在门外。这个场景特别典型,也特别好地引出了存储领域一个绕不开的核心问题:NFS 和 iSCSI 到底差在哪儿?文件级共享和块级共享的根本区别是什么?什么时候该选谁?
这篇文章不打算给你念协议标准,也不打算堆一堆术语装高深。我会从实际使用场景切入,把这两种协议的底层逻辑、搭建过程、性能边界、以及那些文档里不会写的“坑”都摊开来聊一遍。无论你是刚入行的运维、只有一台 NAS 的个人玩家,还是在给虚拟化平台选型存储的工程师,这篇内容应该能帮你少走不少弯路。
1. 内容整体设计与思路拆解
1.1 先搞清楚你要解决的是“共享文件”还是“共享硬盘”
我见过太多人一上来就问“NFS 和 iSCSI 哪个快”,这个提问方式本身就说明还没有理清需求。这两者根本不是同一个层次的东西,强行对比性能意义不大。用一个生活化的类比来解释:
NFS 像是网盘/共享文件夹。你在电脑上访问它,看到的是一个目录,里面是一个个文件。你可以新建 Word 文档、删掉某个视频,但你碰不到“这块盘的分区表”或者“文件系统的格式化”。所有底层操作,都是服务器端替你完成的。
iSCSI 像是给你一根很长的 SATA 线,把你家硬盘接到别人家电脑上。你的操作系统看到的是一块“裸盘”(准确说是 LUN),你需要自己给这块盘分区、格式化、分配盘符。操作系统认为这块盘就是一块本地物理硬盘,完全不知道数据通过网线绕了一圈。
这个区别直接决定了它们能干什么、不能干什么。最典型的例子就是文章开头那个报错:Windows 安装程序必须把一个操作系统引导到“块设备”上,因为它要在磁盘最前面的扇区写引导记录。NFS 是文件协议,操作系统根本没有把它识别成磁盘的抽象层,所以安装程序直接拒绝。而 iSCSI 在系统眼里就是货真价实的 SCSI 磁盘,Windows 完全可以装在 iSCSI 目标盘上——实际上很多无盘工作站、 SAN 启动就是这么干的。
所以做技术选型之前,先问自己一个问题:你需要的是一堆文件,还是一个能承载操作系统的磁盘?这个问题回答清楚了,选型方向就错不了。
1.2 一句话概括两种协议的本质差异
如果一定要用一句话说清楚,我倾向于这样总结:
NFS 是“远程文件系统”,解决的是“多台机器如何共享同一份文件数据”的问题;iSCSI 是“远程块设备”,解决的是“如何把远端存储当成本地硬盘用”的问题。
从这个定义出发,两种协议的应用场景天然不同:
| 维度 | NFS | iSCSI |
|---|---|---|
| 共享粒度 | 文件级 | 块级 |
| 操作系统感知 | 看到一个挂载点/目录 | 看到一块未初始化的磁盘 |
| 是否可格式化 | 不能,格式化操作由服务端完成 | 可以,由发起端自由分区、格式化 |
| 是否可作启动盘 | 不能作为 Windows 系统盘 | 可以启动操作系统 |
| 典型使用场景 | NAS 共享、虚拟机磁盘文件存储、HPC 家目录共享 | 数据库裸设备、虚拟化数据存储、远程启动 |
后面所有的对比、实操、坑点,都会围绕这个表格展开。
2. 核心细节解析与实操要点
2.1 NFS 的运作机制与配置要点
NFS(Network File System)诞生于几十年前,经过 NFSv3、NFSv4 的迭代,到今天依然是 Linux/Unix 世界里最通用的文件共享协议。它的核心思路是通过 RPC 调用,让客户端像访问本地目录一样访问远端目录。服务端把某个目录通过/etc/exports文件导出,客户端用 mount 命令挂载,完事儿。
NFS 最大的优势是运维模型简单、共享语义强。比如你在家组了一台 NAS,想给客厅的电视、书房的工作站、卧室的笔记本共享电影和文档,用 NFS 是最省心的方案。服务端把家目录/home直接 export 出去,客户端统一挂载到/mnt/home,用户登到任何一台机器上看到的 home 目录都是一模一样的。这种“用户无感漫游”体验,是块级协议很难给的——如果你用 iSCSI,两块机器同时挂载同一块裸盘,分分钟就会遇到文件系统损坏的问题,因为没有任何协同机制。
配置 NFS 时最容易踩的坑,一个是权限,一个是锁定,一个是端口防火墙。
权限问题:NFS 在 v3 时代默认使用 AUTH_SYS(也就是基于 UID/GID 的认证),它要求所有客户端的用户 UID 必须保持一致。比如服务端有个用户的 UID 是 1001,客户端另一个用户名也用 UID 1001,那这两个用户实际上就是“同一个人”,哪怕用户名完全不同。这是一个经常让人困惑的点。
文件锁:NFSv3 本身不带锁管理,需要额外开启 rpc.statd 和 rpc.lockd 服务,否则某些数据库程序或者频繁读写小文件的场景会报 lock 错误。NFSv4 在这方面要完善很多,所以新项目建议直接用 NFSv4。
端口防火墙:NFSv3 除了 2049 端口,还会动态开启一堆 rpc 相关端口(比如 rpc.mountd 的端口是随机分配的),你得在防火墙上把这些端口一并放行,这常常让新手抓狂。NFSv4 通常只固定用 2049 端口,配置起来清爽很多。所以我的建议一贯是:新环境能用 NFSv4 就别用 v3。
NFS 的简单之处在于,它的挂载命令和一个普通本地挂载几乎没区别:
mount -t nfs 192.168.1.100:/volume1/media /mnt/media就这么一条命令,目录就共享过来了。配合 fstab 或者 autofs,可以实现开机自动挂载。这也是为什么 NAS 厂商和超算中心特别钟爱 NFS:简单、透明、直接可用。
2.2 iSCSI 的运作机制与关键概念
iSCSI(Internet Small Computer System Interface)从名字就能看出来,它的本质是在 TCP/IP 网络上传输 SCSI 协议。SCSI 是传统企业级磁盘和服务器之间通信的老牌协议,iSCSI 做的事情就是把这个“老运输队长”请到以太网这张“高速公路”上来跑。
整个体系里有几个名词你一定会遇到,先把它们记牢:
- Initiator(发起端):主动发起存储请求的一方,一般就是需要加盘的服务器、台式机、工作站。
- Target(目标端):对外提供存储资源的一方,可以是存储阵列、NAS 设备、也可以是随便一台 Linux 服务器跑个 target 软件。
- IQN(iSCSI Qualified Name):全宇宙唯一的设备标识,通常长这样:
iqn.2024-01.com.example:storage-lun1。不要被它吓到,它就是一个规范化的名字,用来在网络上唯一定位 initiator 和 target。 - LUN(Logical Unit Number):target 上开放出来的一块逻辑磁盘,可以理解成一个“虚拟的硬盘”。
iSCSI 的工作流程大概是:在 target 端把一块物理磁盘或文件(可以理解为“把一个镜像文件当作磁盘”)通过 target 软件暴露出去,然后在 initiator 端“发现”这个 target,登录,之后 initiator 的操作系统就会多出来一块全新的、什么都没格式化的“硬盘”。在 Windows 里你需要去“磁盘管理”里把它初始化、分区、格式化;在 Linux 里你要用fdisk或者parted去分区,然后格式化挂载。
这种“裸盘”体验正是 iSCSI 最核心的竞争力。虚拟机要建集群文件系统(比如 VMware 的 VMFS、微软的 CSVFS),它要求参与共享的所有主机都能直接操作底层块设备。这时候 NFS 反而不好使了——因为 VMFS 这种集群文件系统必须直接跑在裸设备上。而 iSCSI 提供的这种 LUN 正好满足需求。
配置一个 iSCSI 连接并不复杂,以 Linux initiator 为例:
# 安装 initiator 软件 apt install open-iscsi # 发现 target iscsiadm -m discovery -t sendtargets -p 192.168.1.200 # 登录 target iscsiadm -m node -T iqn.2024-01.com.example:storage-lun1 -p 192.168.1.200 --login登录成功后,你会看到系统里多出一个/dev/sdX设备,然后就可以像正常磁盘一样去分区、格式化了。
2.3 同为存储,性能表现为什么截然不同
很多人关心的一个核心问题是:同样走网络、同样走 TCP/IP,NFS 和 iSCSI 在性能上到底有没有差异?
坦诚讲,在几乎没有并发压力的场景下,两者差距没有想象中那么大。但如果并发访问量上来了,差异就出来了。
- NFS 的性能瓶颈通常集中在:协议解析、文件锁、inode 缓存一致性、元数据操作。读大文件、顺序传输时表现不错;但如果是海量小文件并发读写,NFS 的元数据开销会比较明显,很容易造成延迟抖动。
- iSCSI 的性能瓶颈则集中在:网络延迟、TCP 队列深度、以及底层磁盘的 IOPS 能力。因为它传输的是原始 SCSI 命令和块数据,不涉及文件系统解析,所以 CPU 开销相对低,但对网络质量更敏感,任何丢包、乱序都会导致整体性能雪崩。
我自己在虚拟化平台上做了不少沟通。简单总结一下个人经验:
如果平台上主要跑的是 Linux 虚拟机,虚拟机磁盘文件放在 NFS 数据存储上完全可行,VMware 官方也支持 NFS 数据存储,运维上还因为“文件级可见”而多了一层便利——可以直接通过 NFS 把虚拟机的 vmdk 文件拷贝出来。但如果虚拟机是 Windows,或者是 Oracle、SQL Server 这类对随机 IO 敏感的数据库应用,我会更倾向于把数据存储配置成 iSCSI。原因无他,Windows 的系统内部对块设备响应非常敏感,文件级协议带来的额外延迟在数据库高并发场景下会被放大。
不要迷信“iSCSI 一定比 NFS 快”这种一刀切的说法。真正常见的性能杀手是网络拥塞和小文件随机写,协议本身的差异在万兆网时代已经被大幅削弱了。
2.4 Windows 安装报错“NFS 分区”问题的原因分析
讲到这,我们再回到文章开头那个报错:“windows 必须安装在格式化为 NTFS 的分区,windows 无法安装到这个硬盘空间,分区是一个 NFS 分区”。
这句话直接透露了一个事实:Windows 安装程序在启动阶段,只认它能直接从底层块设备访问的磁盘。它需要往磁盘的 MBR(或 GPT)区域写入引导代码,并在指定分区写入 Windows 引导管理器。NFS 挂载出来的空间在 Windows 眼里是一个网络位置,Windows 安装程序没有为它提供文件系统驱动来当启动介质,更不可能通过它加载引导扇区。iSCSI 则不同,因为 Windows 在系统启动早期就内置了微软 iSCSI Initiator 驱动,可以建立会话、枚举 lun、把远端 LUN 当作普通本地磁盘来初始化。所以 Windows 可以装在 iSCSI 目标盘上,却不能装在 NFS 共享目录上。
往后你如果再看到类似报错,第一反应就应该是:是不是我把网络文件系统当成本地磁盘来用了?如果是,那就需要把存储协议换成块级方案,或者调整存储架构——比如采用 SMB 3.0 挂载共享,虽然 Windows 支持从 SMB 共享启动(需要支持 SMB Direct 和适当的网络适配器),但生产环境里还是 iSCSI 最稳。
3. 实操过程与核心环节实现
光讲理论不行。下面我带大家完整走一遍两种协议的搭建和调试过程,你可以直接照着做。为了演示方便,假设我们有两台 Ubuntu 22.04 服务器,服务器 A(192.168.1.100)提供存储,服务器 B(192.168.1.101)作为客户端挂载和使用存储。
3.1 搭建一个 NFSv4 服务端
生产环境里,我推荐使用 NFSv4,省去一堆兼容性麻烦。在服务器 A 上操作:
# 安装 NFS 服务端 apt update && apt install nfs-kernel-server -y # 创建一个用于共享的目录 mkdir -p /srv/nfs/data # 给共享目录分配合理的权限 chown nobody:nogroup /srv/nfs/data chmod 755 /srv/nfs/data接着编辑/etc/exports文件,添加 NFS 导出规则:
/srv/nfs/data 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)这里我特别说明一下几个选项的含义,避免你只知道抄配置:
rw:客户端可读可写。sync:服务端只在数据写入稳定存储后才返回响应,这对一致性很重要,虽然会损失部分性能。no_subtree_check:禁用子树检查,降低协议复杂度、提升性能。现在不太推荐用 subtree 检查,反而容易出问题。no_root_squash:允许客户端的 root 用户保留 root 权限访问共享目录。生产环境不建议这样,这里只是演示。默认的root_squash会把 root 映射成 nobody,这能提升安全性。
建议再添加一条安全加固规则:
/srv/nfs/data 192.168.1.101(rw,sync,no_subtree_check,root_squash)改完配置后,导出并重启服务:
exportfs -ra systemctl restart nfs-server在客户端(服务器 B)上挂载:
apt install nfs-common -y mount -t nfs4 192.168.1.100:/srv/nfs/data /mnt/data挂载成功后,df -h里会出现对应的记录。开机自动挂载的话,把这一条加进/etc/fstab:
192.168.1.100:/srv/nfs/data /mnt/data nfs4 defaults,_netdev 0 0_netdev很关键。它告诉系统网络就绪后再挂载,避免因为网络还没起来导致挂载失败。
3.2 把一块“网路硬盘”切给 iSCSI Target
在服务器 A 上,用 target 软件(比如tgt或者targetcli)把一块磁盘或文件导出成 LUN。
最简单的方式是先用一个文件充当“虚拟磁盘”。我平时调试环境就这么干:
# 创建一块 10GB 大小的文件,模拟磁盘 dd if=/dev/zero of=/srv/iscsi/disk01.img bs=1M count=10240 # 安装 targetcli apt install targetcli -y进入 targetcli 交互界面,敲下面的命令:
targetcli # 进入 backstores 目录,创建一个 fileio 后端存储 cd /backstores/fileio create disk01 /srv/iscsi/disk01.img 10G # 创建 target,并绑定 IQN cd /iscsi create iqn.2024-01.com.example:storage-lun1 # 在 target 下创建 LUN 映射 cd iqn.2024-01.com.example:storage-lun1/tpg1/luns create /backstores/fileio/disk01 # 配置 ACL,只允许指定 initiator 登录 cd /iqn.2024-01.com.example:storage-lun1/tpg1/acls create iqn.2024-01.com.client:initiator1 # 设置监听 IP 和端口(默认 3260) cd /iqn.2024-01.com.example:storage-lun1/tpg1/portals create 192.168.1.100 3260把 IQN 记下来,后面客户端登录要用。
然后保证机器防火墙放行 TCP 3260,否则客户端的 discovery 会直接超时:
ufw allow 3260/tcp在客户端(服务器 B)上操作:
apt install open-iscsi -y # 发现 target iscsiadm -m discovery -t sendtargets -p 192.168.1.100:3260 # 登录 iscsiadm -m node -T iqn.2024-01.com.example:storage-lun1 -p 192.168.1.100:3260 --login登录完成后,用lsblk就能看到一个新的磁盘,比如/dev/sdb。然后就可以像操作本地磁盘一样分区、格式化了:
fdisk /dev/sdb mkfs.ext4 /dev/sdb1 mount /dev/sdb1 /mnt/iscsi_data这套流程跑通后,你会感受到 iSCSI 和 NFS 在“使用体验”上的天壤之别:NFS 挂载完直接就是一个目录;iSCSI 挂载完还要自己建分区、格式化,多了一步,但换来的是“这块盘完全归我管”的掌控感。
3.3 选型决策指南:一张表帮你快速判断
当你需要快速确定用哪种协议时,可以对照下面的表格勾选:
| 需求特征 | 推荐协议 | 原因 |
|---|---|---|
| Linux/Unix 机器间共享文件、目录 | NFS | 文件级共享天然适合,零客户端兼容负担 |
| 跨平台文件共享(Windows/Linux/macOS) | NFS(v4)或 SMB | NFS 在 Linux 生态体验更佳,SMB 在 Windows 生态更佳 |
| 给虚拟机提供数据存储,跑 VMware/KVM | NFS 或 iSCSI 均可 | 取决于虚拟化平台特性和运维习惯 |
| 需要启动远程操作系统(无盘启动/集中部署) | iSCSI | 必须使用块级协议 |
| 数据库、核心业务应用,对随机 IO 敏感 | iSCSI | 块级路径开销更低,更趋近本地磁盘体验 |
| 需要多台主机同时读写同一文件的场景(如共享工作目录) | NFS(配合分布式文件系统) | 文件级锁机制和一致性更成熟 |
| 需要低成本、维护简单的普通文件备份 | NFS | 结构透明,便于 rsync 等工具直接管理 |
一句话总结选型思路:只要不是特别需要“裸盘”能力,优先考虑 NFS;只要有“格式化分区、启动系统、跑专属文件系统”的需求,大概率要用 iSCSI。
4. 常见问题与排查技巧实录
4.1 挂载 NFS 时出现 “Permission denied” 怎么办
NFS 的权限问题,九成是两种原因:
一是/etc/exports没配对。比如导出的网段只允许了192.168.1.101,而你自己从192.168.1.102去挂载,肯定被拒。修改 exports 文件后,要记得exportfs -ra重新导出。二是客户端的 UID/GID 和服务端不一致。NFSv3 的认证本质上只看数字 ID,不看用户名。检查方法很简单,在服务端看共享目录的属主 UID,然后在客户端用同名 UID 的用户去访问,问题就解决了。
这类问题,可以通过在服务端用tail -f /var/log/syslog实时观察 RPC 请求的拒绝日志来定位到底卡在哪一步。
4.2 iSCSI 登录超时或连接断开
iSCSI 是一个基于 TCP 的长连接会话,对网络稳定性要求极高。我遇到过比较多的情况是:
- 客户端和服务端之间有防火墙拦截了 3260 端口,导致 discovery 阶段就超时。
- MTU 不匹配,尤其是启用了巨型帧(jumbo frame)后,交换机某个端口没开 9000 MTU,导致数据包被丢弃。这个问题最隐蔽,表现就是 ping 通、TCP 建连成功,但传输大文件时随机断连或卡死。排查手段:在两端同时执行
ping -M do -s 8972 目标IP,如果通,说明巨型帧链路OK。 - 多路径(MPIO)配置错误导致 I/O 路径切换时中断。如果你有多根网卡参与 iSCSI,建议先把 MPIO 配好,不要裸用多个网卡直接访问同一个 target。
另外,很多人在iscsiadm -m node --login后发现重启就掉线,忘了设置自动登录。把下面这条加进去:
iscsiadm -m node -T iqn.2024-01.com.example:storage-lun1 -p 192.168.1.100:3260 --op update -n node.startup -v automatic这样登录状态会自动持久化,重启服务器后客户端会自动重连。
4.3 NFS 文件锁和缓存一致性
NFS 在代码编译、数据库小文件读写等场景下,偶尔会遇到 “No locks available” 或缓存不一致的情况。NFSv3 时代的锁服务不稳定是出了名的。如果真的要用 NFS 跑数据库类应用,有几个要点:
- 强制使用 NFSv4,锁管理集成进协议内部,比 v3 稳得多。
- 在挂载时加入
hard选项(默认就是 hard),避免网络抖动时应用返回 I/O 错误。soft选项虽然看起来“友好”,但会导致数据库误判写入失败,别用。 - 对于极端的一致性需求,可以考虑
actimeo=0来禁用 client 端的属性缓存,但这样会显著降低性能。一般不用这么激进,actimeo=30左右是很多生产环境的平衡点。
4.4 安全加固:别把存储裸奔在网络上
不少人在内网环境图省事,把 NFS 和 iSCSI 的认证都关了,直接 IP 白名单就上。内网环境不一定出事,但养成良好的安全习惯总是好的:
- NFSv4 可以配置 Kerberos 认证(
sec=krb5p),虽然配置略繁,但对于想保护数据的场景非常值得。 - iSCSI 有 CHAP 认证。通过 CHAP 至少可以防止未知 initiator 随便登录 target。配置示例:
# 在 target 的 ACL 下配置创建用户 cd /iqn.2024-01.com.example:storage-lun1/tpg1/acls/iqn.2024-01.com.client:initiator1 create user username set auth userid=username set auth password=Passw0rd!客户端登录时也要带上用户名密码,否则会被拒绝。
- 尽量让存储流量走独立 VLAN 或独立网卡,不要把存储流量和管理流量混在一起。一个广播风暴,整条存储链路都跟着遭殃,这种事故我经历过不止一次。
4.5 性能实测建议:先压测再上线
很多运维朋友在实际部署时,习惯直接挂上就跑,等业务反馈慢了才开始排查。我的习惯是,任何新的存储链路在上线前都要做一轮压测。
- 对 NFS,可以用
fio做顺序写、随机读、小文件创建等不同负载模式的测试。重点观察:吞吐量(MB/s)、IOPS、延迟的 P99 值。 - 对 iSCSI,同样可以用
fio或 Windows 下的crystaldiskmark测试。重点观察多队列深度下的 IOPS 以及延迟抖动。
压测时别忽略元数据操作的负载,很多存储系统跑大文件读写没问题,一遇到成千上万的小文件就原形毕露。所以测试负载一定要模拟实际业务。
5. 写在最后的一些个人经验
存储协议选型从来不是一道简单的二选一题。我见过很多公司把数据库跑在 NFS 上,最后因为锁问题天天加班;也见过有人非要用 iSCSI 来共享家目录,结果因为多客户端并发写同一目录,把文件系统搞得一塌糊涂。
根据过往经验,我再总结三条实实在在的建议:
- 没把握时,先跑 POC。拿真实业务的数据集,分别挂在 NFS 和 iSCSI 上,跑一轮压测和真实业务模拟。性能看数据,选型看需求,不要拍脑袋。
- 存储网络要舍得投入。不管选哪种协议,万兆网卡和配套交换机带来的性能提升,比纠结协议本身大得多。千兆网络下,NFS 和 iSCSI 都容易成为瓶颈。
- 运维一致性思维更重要。对于一个团队来说,熟悉 NFS 的运维模式和熟悉 iSCSI 的运维模式完全不同。考虑方案时,也要把团队的经验和能力考虑进去。NFS 在文件可见性、排障直观性上有优势;iSCSI 在块设备兼容性、性能一致性上有优势。没有绝对的好坏,只有合不合适的场景。
最后再分享一个小技巧:当你搞不清楚一个应用到底适合哪种存储协议时,去查一下官方文档里提到的“共享文件系统”还是“独立磁盘”的选型说明。官方推荐的存储类型,往往就直接标明了答案。
希望这篇文章能让你对 NFS 和 iSCSI 有一个更立体的认识。技术选型的路上,少踩几个坑,项目推进就顺畅得多。