Linux zfs运维篇:scrub、扩容、换盘

AI 概述
本文详解ZFS核心日常运维操作,包含scrub巡检、存储扩容、故障换盘三大模块。介绍scrub校验修复数据原理、常用命令、执行频率与自动化配置,区分其与resilver差异。讲解冗余vdev、L2ARC、SLOG添加及整盘替换扩容方法。提供故障盘识别、替换、离线恢复流程,附带NAS升级、故障处理等实战案例。同时说明扩容与重建限速、版本升级、磁盘稳定命名规范,并总结关键运维注意事项与核心操作命令。
目录
文章目录隐藏
  1. 一、scrub:自愈的”心脏”
  2. 二、扩容
  3. 三、换盘
  4. 四、实战案例
  5. 五、扩容期间的性能
  6. 六、resilver 性能
  7. 七、版本升级(Feature Flags)
  8. 八、命名规范
  9. 九、本篇小结

Linux zfs 运维篇:scrub、扩容、换盘

玩 ZFS 存储、搭建 NAS 或服务器存储集群,日常运维核心无非三件事:定期巡检校验、存储空间扩容、故障硬盘替换。很多人只会基础的创建存储池命令,却不懂定期 scrub 的重要性,扩容、换盘也经常踩坑,比如乱加单盘导致数据风险、扩容不生效、换盘 resilver 出错等问题。我结合长期实操经验,把 ZFS 最核心的日常运维操作、底层原理、完整命令和避坑要点全部整理出来,覆盖家用 NAS 到企业存储场景,看完就能直接落地使用。

一、scrub:自愈的”心脏”

1.1 scrub 是什么?

scrub = 遍历 pool 中所有 block,校验 checksum,发现并修复不一致的 block。

scrub 过程中:

  1. 读取每个 block;
  2. 重新计算 checksum;
  3. 与存储的 checksum 对比;
  4. 不一致 → 用冗余副本修复。

scrub 是 ZFS “端到端校验和” 价值的最终体现。

1.2 scrub 的特性

  • 只读为主(除修复不一致数据外);
  • 后台运行,可以暂停/恢复;
  • 不影响业务(性能会降 30~50%);
  • 优先级可调(zfs scrub vs zpool scrub)。

1.3 scrub 命令

# 启动 scrub
$ zpool scrub tank

# 看 scrub 进度
$ zpool status
  pool: tank
 state: ONLINE
  scan: scrub in progress since Sun Jun 23 03:00:00 2024
        9.50G scanned out of 100G at 100M/s, 14h30m to go
        0B repaired, 0.13% done

# 暂停 scrub(OpenZFS 2.1+)
$ zpool scrub -p tank

# 停止 scrub
$ zpool scrub -s tank

1.4 scrub vs resilver

操作 触发条件 行为
scrub 手动 校验所有 block
resilver 替换/添加盘后 把新盘数据补全

1.5 scrub 频率

场景 建议频率
家用 每月 1 次
企业关键 每周 1 次
大容量(>50TB) 每月 1 次,限时窗口跑
冷存储 每月 1 次

1.6 自动化 scrub

# systemd timer
$ cat /etc/systemd/system/zfs-scrub-monthly.timer
[Unit]
Description=Monthly ZFS scrub

[Timer]
OnCalendar=monthly
RandomizedDelaySec=4h
Persistent=true

[Install]
WantedBy=timers.target

$ cat /etc/systemd/system/zfs-scrub-monthly.service
[Unit]
Description=Monthly ZFS scrub

[Service]
Type=oneshot
ExecStart=/sbin/zpool scrub tank

$ systemctl enable --now zfs-scrub-monthly.timer

或者 FreeBSD cron:

# /etc/cron.d/zfs-scrub
0 4 1 * * root /sbin/zpool scrub tank

1.7 scrub 性能

scrub 性能受限于最慢的盘。一个 vdev 内所有盘要全部扫完。

# 限制 scrub 速度(避免影响业务)
# zfs 模块参数
options zfs zfs_scan_idle=0      # 0 = 高优先级;1 = 空闲时跑

二、扩容

2.1 加 vdev(最常见的扩容方式)

# 看当前 pool
$ zpool list
NAME   SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
tank  9.50G   1.2G  8.30G        -         -     5%    12%  1.00x    ONLINE  -

# 加新 vdev(raidz2)
$ zpool add tank raidz2 /dev/sdh /dev/sdi /dev/sdj /dev/sdk

# 加 mirror vdev
$ zpool add tank mirror /dev/sdl /dev/sdm

注意:新加的 vdev 必须是冗余的(mirror/raidz),不要加单盘 stripe。

2.2 加 L2ARC / SLOG

# 加 L2ARC
$ zpool add tank cache /dev/nvme0n1p1

# 加 SLOG(独立 ZIL)
$ zpool add tank log /dev/nvme1n1p1
$ zpool add tank log mirror /dev/nvme1n1p1 /dev/nvme2n1p1

2.3 加 spare(热备盘)

# 加 spare(盘坏时自动顶替)
$ zpool add tank spare /dev/sdx

# 启用自动替换
$ zpool replace tank /dev/sdb /dev/sdx    # 手动
# 或损坏时自动

2.4 替换更大的盘

# 步骤:1 块块替换,触发自动扩容
$ zpool replace tank /dev/sdb /dev/sdb_new

# 全部替换后,启用 autoexpand
$ zpool set autoexpand=on tank
$ zpool online -e tank    # 强制扩容

# 看进度
$ zpool list

2.5 容量与时间

替换更大盘后,pool 自动扩容到最小盘的容量(raidz 是按最小成员盘算)。

例:5 块 1TB + 1 块 2TB 的 raidz2,有效空间还是 3TB((5-2) × 1TB)。要全用 2TB,需要 5 块全换 2TB。

三、换盘

3.1 故障盘识别

# 看哪个盘故障
$ zpool status
  pool: tank
 state: DEGRADED
status: One or more devices has experienced an unrecoverable error...
action: ...

config:
        NAME        STATE     READ WRITE CKSUM
        tank        DEGRADED     0     0     0
          raidz2-0  DEGRADED     0     0     0
            sdb     ONLINE       0     0     0
            sdc     FAULTED      5     2     0      ← 故障
            sdd     ONLINE       0     0     0
            sde     ONLINE       0     0     0
            sdf     ONLINE       0     0     0

3.2 替换故障盘(标准流程)

# 1. 物理换盘(关电?热插?)
#    多数 SATA/SAS 盘支持热插拔

# 2. 用 zpool replace 替换
$ zpool replace tank /dev/sdc /dev/sdc_new

# 或更详细(指定故障盘路径)
$ zpool replace tank /dev/disk/by-id/ata-WDC_WD...-sdc /dev/disk/by-id/ata-WDC_WD...-sdc-new

# 3. 看 resilver 进度
$ zpool status
  scan: resilver in progress since Sun Jun 23 03:00:00 2024
        2.5G scanned out of 100G at 200M/s, 7m to go
        2.5G resilvered, 2.5% done

3.3 mirror 单独替换

# mirror vdev 中替换单盘
$ zpool replace tank /dev/sdc /dev/sdc_new

3.4 离线盘

# 标记为离线(不立即换,先把业务保住)
$ zpool offline tank /dev/sdc

# 重新上线
$ zpool online tank /dev/sdc

3.5 强制 detach

# 强制把盘从 pool 中移除(危险!数据可能丢)
$ zpool detach tank /dev/sdc

3.6 replace 失败处理

# 场景:resilver 中断
$ zpool status
# 看具体错误

# 选项 1:重新 replace
$ zpool replace tank /dev/sdc /dev/sdc_new

# 选项 2:先 offline 再 replace
$ zpool offline tank /dev/sdc
$ zpool replace tank /dev/sdc /dev/sdc_new

# 选项 3:从 backup 恢复(最坏情况)

四、实战案例

案例 1:家用 4 盘 NAS 升级

# 当前:4 × 4TB raidz2,可用 8TB
# 想升级到 4 × 8TB raidz2,可用 16TB

# 1. 一块块替换
$ zpool replace tank /dev/sdb /dev/sdb_8t
$ zpool replace tank /dev/sdc /dev/sdc_8t
$ zpool replace tank /dev/sdd /dev/sdd_8t
$ zpool replace tank /dev/sde /dev/sde_8t

# 2. 启用自动扩容
$ zpool set autoexpand=on tank
$ zpool online -e tank

# 3. 看结果
$ zpool list
NAME   SIZE  ALLOC   FREE  ...  CAP
tank   32T   8T     24T   ...  25%
# 总容量 32T(4×8T),可用 16T(raidz2 损失 2 块)

案例 2:故障盘紧急处理

# 1. 收到 SMART 告警
$ smartctl -a /dev/sdc
# ... critical warning ...

# 2. 看 pool 状态
$ zpool status tank
# sdc 有 CKSUM 错误,但还没 FAULTED

# 3. 主动 replace(不等完全坏)
$ zpool replace tank /dev/sdc /dev/sdc_new

案例 3:扩容(不破坏数据)

# 当前:raidz2 4 盘,可用 8TB
# 想加 2 块盘(变成 2 个 vdev)

# 1. 加 vdev
$ zpool add tank raidz2 /dev/sdh /dev/sdi /dev/sdj /dev/sdk

# 2. 看结果
$ zpool list
# SIZE 翻倍

# 3. 数据会自动重新分布到所有 vdev
# 期间性能会下降(migration I/O)

五、扩容期间的性能

扩容会触发数据迁移:

  • 已有数据部分会重新分布到新 vdev;
  • 性能下降 30~50%;
  • 大量数据时耗时较长(几天)。
# 限制迁移速度
$ zpool set migration_limit=50M tank    # 50 MB/s

# 取消限速
$ zpool set migration_limit=none tank

经验:

  • 在业务低峰扩容;
  • 提前通知用户;
  • 监控 zpool iostat 确认完成。

六、resilver 性能

resilver 速度受限于多个因素:

  • 盘数(更多盘 = 更长);
  • 盘速(最慢盘决定);
  • CPU(校验计算);
  • I/O 队列。
# 限速
$ zpool set resilver=bandwidth tank    # 实际限速配置
# 50M = 50 MB/s
# 100M = 100 MB/s

经验:

场景 建议
业务高峰 50~100 MB/s
业务低峰 不限速

七、版本升级(Feature Flags)

OpenZFS 不断加新特性,但新 pool 默认关闭这些特性。要启用:

# 启用新特性
$ zpool upgrade tank

# 启用所有新特性
$ zpool upgrade -a

# 看当前版本
$ zpool get version tank

警告:升级feature flags之后,旧版 ZFS 不能读这个 pool。确保所有机器的 ZFS 版本足够新。

八、命名规范

为了让运维更轻松,盘命名推荐用/dev/disk/by-id/

# 看盘的稳定 ID
$ ls /dev/disk/by-id/
ata-WDC_WD80EFZZ-68BTXN0_VCC5Y6XL
ata-WDC_WD80EFZZ-68BTXN0_VCC5Y6YM
...

# 用 ID 创建 pool(避免设备名变化)
$ zpool create tank raidz2 \
    /dev/disk/by-id/ata-WDC_WD80EFZZ-68BTXN0_VCC5Y6XL \
    /dev/disk/by-id/ata-WDC_WD80EFZZ-68BTXN0_VCC5Y6YM \
    /dev/disk/by-id/ata-WDC_WD80EFZZ-68BTXN0_VCC5Y6ZN \
    /dev/disk/by-id/ata-WDC_WD80EFZZ-68BTXN0_VCC5Y6ZO

这样/dev/sdb → /dev/sdc不会影响 pool。

九、本篇小结

任务 命令
启动 scrub zpool scrub tank
看 scrub 进度 zpool status
加 vdev zpool add tank raidz2 /dev/sdX /dev/sdY …
加 L2ARC zpool add tank cache /dev/nvme0n1
加 SLOG zpool add tank log /dev/nvme0n1
替换盘 zpool replace tank /dev/old /dev/new
离线盘 zpool offline tank /dev/sdX
上线盘 zpool online tank /dev/sdX

关键提醒:

  • scrub必做——定期执行,发现并修复silent corruption
  • /dev/disk/by-id/——设备名稳定;
  • 新加的vdev一定要冗余——不能加单盘;
  • 扩容会触发数据迁移——低峰期做;
  • resilver速度要限速——避免业务抖动。

总的来说,ZFS 存储的稳定运行,不靠侥幸,全靠规范运维。定期 scrub 巡检可以提前发现静默数据损坏,是保障数据安全的核心;扩容切忌随意加盘,优先冗余 vdev、遵守扩容规则,才能兼顾容量和安全性;硬盘故障及时处理,规范换盘、合理限速,能最大程度避免业务波动。同时坚持用磁盘唯一 ID 管理设备、按需升级特性、错开业务高峰期操作,就能规避绝大多数 ZFS 运维故障。掌握这套标准化流程,足以搞定 99%的 ZFS 日常维护场景,让存储系统长期稳定运行。

以上关于Linux zfs运维篇:scrub、扩容、换盘的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。

「点点赞赏,手留余香」

23

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » Linux zfs运维篇:scrub、扩容、换盘

发表回复