SStorpath
原理预计 25 分钟

存储协议与接入方式

iSCSI、NFS、S3、NVMe-oF 各自的开销与坑,接入前先知道。

学完这节你能做到

  • 为给定业务选择接入协议并说明理由
  • 排查 NFS 挂载卡死、S3 签名失败一类常见故障
  • 理解多路径与客户端侧缓存的影响

接入协议决定了你会遇到什么故障

同样一套后端存储,用 NFS 接入和用 S3 接入,日常故障完全不同:前者会卡在 D 状态的进程和陈旧的文件句柄上,后者会卡在签名不匹配和分段上传残留上。这一节把四类主流协议的机制和典型故障串一遍。

iSCSI 与多路径

iSCSI 把 SCSI 命令封装进 TCP,让远端的块设备看起来像本地盘。

# 发现 target
iscsiadm -m discovery -t st -p 10.0.1.10:3260

# 登录
iscsiadm -m node -T iqn.2026-01.com.example:storage.disk1 -p 10.0.1.10 -l

# 之后就多了一个块设备
lsblk

单条路径是单点。生产上通常配多路径(multipath):同一个 LUN 通过两条网络路径暴露,客户端把它们识别成一个设备。

multipath -ll
mpatha (36000d31000...) dm-2 EXAMPLE,STORAGE
size=2.0T features='1 queue_if_no_path' hwhandler='0' wp=rw
|-+- policy='round-robin 0' prio=50 status=active
| `- 7:0:0:1 sdb 8:16  active ready running
`-+- policy='round-robin 0' prio=10 status=enabled
  `- 8:0:0:1 sdc 8:32  active ready running
×queue_if_no_path 会让进程永久卡死

这个特性的本意是:所有路径都断了就把 I/O 排队,等路径恢复后继续,避免业务报错。但如果路径永远不恢复,所有访问这个设备的进程会永久卡在 D 状态(不可中断睡眠),kill -9 都杀不掉,只能重启机器。

排查时看到一堆 D 状态进程加上 multipath -ll 显示 faulty,就是这个组合。生产上要根据业务性质决定用 queue_if_no_path(要求绝不丢 I/O)还是 no_path_retry fail(宁可报错也要让进程能退出)。

NFS:v3 与 v4 的关键差别

NFSv3NFSv4
状态无状态有状态(服务端记录客户端打开的文件)
靠额外的 NLM 协议内置在协议里
端口需要 portmapper,多个动态端口只用 2049 一个端口
故障恢复服务端重启后客户端自动继续需要经过 grace period 恢复状态
防火墙友好度
# 常用挂载参数
mount -t nfs -o vers=4.1,hard,timeo=600,retrans=2,rsize=1048576,wsize=1048576 \
      10.0.1.20:/export/data /mnt/data

关键参数:

  • hard vs softhard 在服务端无响应时无限重试(进程卡住但数据不会错),soft 会超时返回错误(进程不卡但应用可能拿到不完整的数据)。存放重要数据一律用 hard
  • rsize / wsize:单次读写的大小,调大能显著提升大文件吞吐
  • noatime:同本地文件系统,减少无谓的元数据往返
!Stale file handle 是怎么来的

ls: cannot access: Stale file handle 表示客户端手里的文件句柄在服务端已经失效——通常是服务端重新导出了目录、文件系统被重新挂载、或者底层 inode 被重建。

处理方式是在客户端重新挂载(umount -l + mount)。要避免它,服务端导出配置里加 fsid=<固定值>,让句柄在重新导出后保持稳定。

S3:签名、分段上传与一致性

S3 是对象存储的事实标准。三个必须理解的机制:

1. 签名(SigV4)

每个请求都要用 secret key 对「方法 + 路径 + 头部 + 时间戳」做 HMAC 签名。因此:

SignatureDoesNotMatch 的常见原因:
  - 客户端与服务端时间相差超过 15 分钟   ← 最常见
  - endpoint 里带了错误的 region
  - 路径风格(path-style)与虚拟主机风格(virtual-hosted)配置不匹配
  - 反向代理改写了某个参与签名的头部

自建 RGW 时前两条和最后一条尤其高发。先查 NTP 几乎是条件反射。

2. 分段上传(Multipart Upload)

大对象要分片上传,最后调用 CompleteMultipartUpload 合并。如果客户端中途崩溃且没有 Abort,这些分片会一直占着空间但在 bucket 列表里看不见

# 列出未完成的分段上传
aws s3api list-multipart-uploads --bucket mybucket

# 配置生命周期规则自动清理
aws s3api put-bucket-lifecycle-configuration --bucket mybucket \
  --lifecycle-configuration file://lifecycle.json
×用量对不上,先查残留的分段上传

aws s3 ls 统计出来只有 40TB,但 ceph df 显示这个池用了 60TB」——最常见的原因就是残留的分段上传分片。给每个 bucket 都配上「7 天后自动清理未完成分段上传」的生命周期规则,是自建对象存储的标准动作。

3. 路径风格

virtual-hosted 风格:https://mybucket.s3.example.com/key
path 风格:        https://s3.example.com/mybucket/key

自建 RGW 用 virtual-hosted 风格需要配置泛域名 DNS(*.s3.example.com)。没配好就会出现"用 path-style 能通、用默认配置报错"的现象。很多客户端要显式加 --endpoint-url 并开启 s3.addressing_style = path

NVMe-oF:把 NVMe 协议搬到网络上

iSCSI 封装的是老的 SCSI 命令集,协议开销大、队列模型落后。NVMe-oF 直接把 NVMe 的多队列模型延伸到网络上:

传输要求延迟
NVMe/RDMA (RoCE)无损网络,交换机要配 PFC/ECN最低,接近本地 NVMe
NVMe/TCP普通以太网即可略高,但部署简单得多
nvme discover -t tcp -a 10.0.1.30 -s 4420
nvme connect -t tcp -n nqn.2026-01.com.example:subsys1 -a 10.0.1.30 -s 4420
nvme list

选型建议和上一阶段谈 RoCE 时一致:没有能独立调 PFC/ECN 的网络工程师,就先用 NVMe/TCP

检查点单选

自建 RGW,客户端上传报 SignatureDoesNotMatch。最该先检查什么?

检查点多选

NFS 客户端上一批进程卡在 D 状态,kill -9 无效。下面哪些是合理的分析?(多选)

检查点单选

S3 bucket 里 ls 出来 40TB,但后端池显示占用 60TB。最可能的原因是?

这节课的落点

  • iSCSI 多路径的 queue_if_no_path 会让进程永久 D 状态,按业务性质选择策略
  • NFS 用 hard 保数据正确性,代价是服务端故障时进程会卡;Stale file handle 靠固定 fsid 预防
  • S3 签名失败先查时间同步;分段上传残留是用量对不上的头号原因
  • NVMe-oF 优于 iSCSI,但 RDMA 传输要求团队有无损网络能力,否则先用 TCP

L1 到此结束。你已经有了一套与产品无关的存储心智模型,下一阶段用 Ceph 把它落到具体命令上。

延伸资料

  • ·k8s-in-actionstorage/nfs-csi/
  • ·k8s-in-actionstorage/vast/nfs/