RHEL配置ZFS存储
环境声明
OS Version: Rocky9
实验环境使用4
块1T硬盘
ZFS简介
https://www.wolai.com/littlenewton/gJvungs54zWgZ3YfoXAvKW
ZFS块指针的结构
ZFS的存储池布局
存储池 (zpool)
│ [ 基于 Vdev(s) 构建 ]
│ └── 虚拟设备 (vdev)
│ │ [ 基于 Disk(s) 构建 ]
│ └── 物理磁盘/设备 (disk)
│
├── 根数据集 (root dataset)
│ ├── 子数据集 (child dataset)
│ ├── 卷 (zvol, 块设备)
│ └── 快照 (snapshot)
└── (其他组件: 如 Cache vdev, Log vdev - 可选)
下面这张图能更好地体现dataset
和zvol
之间的关系。
ZFS优势
- ZFS 核心优势:
- 端到端校验和 (End-to-end Checksums): ZFS 在数据写入时计算校验和,并在读取时验证,能检测并(若有冗余)修复静默数据损坏 (Silent Data Corruption),这是传统硬件 RAID 卡通常不具备或不完善的功能。
- 写时复制 (Copy-on-Write, CoW): ZFS 从不覆盖旧数据。修改数据时,新数据写入空闲块,然后更新元数据指向新块。这使得快照几乎瞬时完成,且从根本上消除了 RAID 写漏洞 (Write Hole) 问题(即写入过程中断电导致奇偶校验与数据不一致)。
- 动态条带宽 (Dynamic Stripe Width): RAID-Z 的条带宽不是固定的,可以根据写入的数据块大小变化,能更有效地利用空间,尤其在有压缩时。
- 集成管理: ZFS 将卷管理和文件系统功能集成在一起,简化了管理。
- 容量计算: 假设 vdev 中所有磁盘容量相同。
- 性能: 为相对比较,实际性能受硬件影响很大。
- 扩展性: ZFS 不支持向现有的 Mirror 或 RAID-Z vdev 中添加单个磁盘来扩展容量。扩展 ZFS 池通常通过替换现有磁盘为更大容量或添加新的 vdev 实现。
- vdev: ZFS 的虚拟设备是构建存储池 (zpool) 的基础块。一个 zpool 可以包含多个 vdev,数据会跨这些 vdev 进行条带化(除非只有一个 vdev)。
总结:
ZFS 提供了与传统 RAID 类似的冗余级别,但通过其独特的设计(如 CoW 和校验和)提供了更高的数据完整性保障,并解决了传统 RAID 的一些固有问题(如写漏洞)。选择哪种策略需要根据对数据安全性、容量效率、性能和成本的具体需求来权衡。
Centos7安装ZFS
https://openzfs.github.io/openzfs-docs/Getting%20Started/RHEL-based%20distro/index.html
# 安装zfs库
yum install -y https://zfsonlinux.org/epel/zfs-release.el7_9.noarch.rpm
# 禁用zfs dkms源
## zfs源是dkms(动态内核模块支持)---ZFS on Linux for EL 7 - dkms
yum config-manager --disable zfs
# 启用zfs-kmod源
## kmod是内核模块
yum config-manager --enable zfs-kmod
RHEL8/RHEL9安装ZFS
# 安装zfs源
dnf install -y https://zfsonlinux.org/epel/zfs-release-2-2$(rpm --eval "%{dist}").noarch.rpm
# 安装epel源
dnf install -y epel-release
# 安装dev内核
dnf install -y kernel-devel
# 禁用zfs dkms源
## zfs源是dkms(动态内核模块支持)---ZFS on Linux for EL 7 - dkms
dnf config-manager --disable zfs
# 启用zfs-kmod源
## kmod是内核模块
dnf config-manager --enable zfs-kmod
# 安装zfs主程序
dnf install -y zfs
# 加载zfs内核模块
modprobe zfs
# 安装分区工具
dnf install -y gdisk dosfstools
# 查看zfs版本
zfs version
始终在启动时加载OpenZFS模块
默认情况下,当检测到 ZFS 池时,会自动加载 OpenZFS
内核模块。如果您希望**始终在启动时加载**
模块,则必须创建一个 /etc/modules-load.d/zfs.conf
文件:
# 在启动时自动加载zfs模块
echo zfs >/etc/modules-load.d/zfs.conf
开机自启zfs服务
# 开机自启zfs服务
systemctl enable --now zfs-import-scan.service zfs-mount zfs-import.target zfs-zed zfs.target
# 查看zfs-import-scan服务状态
systemctl status zfs-import-scan
创建ZFS的步骤:
- 规划创建存储池
- 选择冗余策略
- 配置数据集/子数据集
- 定义挂载点
- 优化与扩展
https://blog.csdn.net/wanghai__/article/details/6196790
https://www.escapelife.site/posts/caf259ea.html
│ |--- 物理磁盘/设备 (disk)
│ |--- 虚拟设备 (vdev)
│ │
存储池 (zpool)
├── 根数据集(root dataset)
│ ├── 子数据集(child dataset)
│ ├── 卷(zvol,块设备)
│ └── 快照(snapshot)
指定存储池的冗余策略
ZFS 策略 | 类似 RAID | 简述 | 最小盘数 (每 Vdev) | 容错盘数 (每 Vdev) | 容量效率 (约) | 性能 (读/写) | 主要场景 | 优点 | 缺点/注意 |
---|---|---|---|---|---|---|---|---|---|
Stripe(默认策略) | RAID 0 | 数据条带化,无冗余 | 1+ | 0 | ~100% | 高 / 高 | 临时/非关键数据,最大性能/容量 | 最高性能/容量, ZFS完整性 | 无冗余!单盘故障 = 全池数据丢失 |
Mirror | RAID 1 | 数据完全复制 | 2+ | N-1 | ~1/N (单盘) | 高 / 中高 | 高数据安全, 随机读密集 (VMs) | 高冗余, 较快重建, 良好读性能, ZFS完整性 | 最低容量效率 |
RAID-Z1 | RAID 5 | 条带化 + 单奇偶校验 | 3 | 1 | ~(N-1)/N | 高 / 中 | 容量/冗余均衡 | 较好容量效率, ZFS完整性 (无写漏洞) | 写有开销, 重建慢且期间有风险 |
RAID-Z2 | RAID 6 | 条带化 + 双奇偶校验 | 4 | 2 | ~(N-2)/N | 高 / 中低 | 较高数据安全, 大容量盘 | 高冗余 (更安全重建), ZFS完整性 | 写开销更大, 重建更慢 |
RAID-Z3 | N/A | 条带化 + 三奇偶校验 | 5 | 3 | ~(N-3)/N | 高 / 低 | 最高数据安全, 关键数据 | 最高冗余, ZFS完整性 | 写开销最大, 重建非常慢 |
dRAID | RAID 5/6 | 分布式 RAID-Z, 重建快 | 变化 | 1, 2, 或 3 | 类 RAID-Z | 高 / 中低 | 需极快重建的大型池 | 极快重建, ZFS完整性, 集成热备 | 较新, 配置稍复杂 |
Cache | N/A | L2ARC - SSD 读缓存 | 1 (SSD) | N/A | N/A | 提升读 | 改善常用数据读取性能 | 加速读访问 | 需SSD, 需内存管理, 不加速写 |
Log | N/A | SLOG - SSD 同步写日志 (ZIL) | 1 (SSD,常镜像=2) | N/A / 1(镜像时) | N/A | 提升同步写 | 加速 NFS, DB, VM 等同步写操作 | 降低同步写延迟 | 需高速耐用SSD, 仅加速同步写, 单盘有风险 |
## 冗余模式 (type: “”,mirror,raidz,raidz2)
zpool create zfspool <type> <磁盘1> <磁盘2>
Stripe条带化–默认
RAID0,最少2
块硬盘,速度快,但**不容灾**
;
且不支持做热备,做了也没用
# 创建RAID0
zpool create -f zfspool /dev/sdc /dev/sdd
mirror镜像存储池
-
镜像(Mirror)
:适用于高随机读写场景(如数据库),写入性能最优
。
# 创建一个镜像(mirror)存储池(双磁盘冗余)
# - `zpool create` : 创建新 ZFS 存储池
# - `-f` : 强制操作(覆盖现有池或忽略缺失设备警告)
# - `zfspool` : 存储池名称(可自定义)
# - `mirror` : 配置镜像冗余模式(需至少2块磁盘)
# - `vdc vdd` : 指定用作镜像的物理设备(例如磁盘或分区)
# ▶ 特点:数据实时双副本,提供高可用性,但存储利用率50%
# ▶ 警告:使用 `-f` 前需确认目标设备无重要数据
zpool create -f zfspool mirror vdc vdd
RAIDZ2/(对标RAID6)
-
RAIDZ1/RAIDZ2
:适合顺序大文件读写(如备份存储),平衡性能与空间利用率
# 创建RAIDZ2
# 创建一个 RAID-Z 存储池(单磁盘冗余)
# - `raidz` : 配置 RAID-Z 冗余模式(类似 RAID5,需至少3块磁盘)
# - `vdc vdd vde` : 指定3块物理设备
# 特点:存储利用率 ≈ (N-1)/N(本例约66.6%),允许单盘故障
# 注意:RAID-Z 适用于3块及以上设备,不同版本支持 raidz1/2/3
zpool create -f zfspool raidz2 /dev/sdc /dev/sdd /dev/sde /dev/sdf
pool(存储池)管理命令
│ |--- 物理磁盘/设备 (disk)
│ |--- 虚拟设备 (vdev)
│ │
存储池 (zpool)
├── 根数据集(root dataset)
│ ├── 子数据集(child dataset)
│ ├── 卷(zvol,块设备)
│ └── 快照(snapshot)
创建一个pool(存储池)
ZFS 创建存储池时并不严格要求
所有磁盘容量必须完全相同,但强烈建议使用相同容量的磁盘。
# 创建一个存储池
## 默认的冗余策略是 条带化 (Stripe)
## zpool create -f <存储池名称> 磁盘1 磁盘2 磁盘3 磁盘4
zpool create -f zfspool vdc vdd vde vdf
向存储池中添加更多空间
# 向zfspool 池中添加磁盘
## mirror 冗余策略为 镜像
zpool add zfspool mirror vdg vdh
验证存储池是否创建成功
如果存储池创建成功,df -Th
中会会出现一个路径为zfspool
大小3.8TB的空间,同时挂载在/zfspool
。
# 查看磁盘使用率
df -Th
查看存储池(pool)列表
# 查看存储池
zpool list
修改存储池的名称(ZFS存储池迁移)
# 将名为 "zfspool" 的 ZFS 存储池从当前系统导出
## export 导出存储池
# 导出操作会使该存储池在当前系统上暂时不可用,
# 并将其标记为“已导出”,以便可以安全地移动物理磁盘或在稍后重新导入(可能使用新名称)。
zpool export <存储池名称>
# 从旧服务器上导出存储池
zpool export zfspool
# 列出所有可以导入的存储池
zpool import
# 导入先前导出的 ZFS 存储池,并将其重命名
## import 导入存储池
# 这个命令会查找原始名为 "zfspool" 的已导出存储池,
# 并将其以 "newpool" 的新名称导入到当前系统中。
# 如果省略 "newpool",则会以原始名称 "zfspool" 导入。
zpool import <已导出的存储池名称> <new存储池名称>
zpool import zfspool newpool
# 查看导入后到存储池状态
zpool status
显示存储池的状态
# 显示可用池的状态
# 查看zpool中有哪些磁盘
zpool status
# 获取存储服务的状态
zpool get all 存储池名
# 获取存储服务的状态
zpool get all
显示存储池修改历史
# 显示以前修改了存储池状态信息
zpool history
更新存储池
# 查看存储池是否需要升级以及可以启用哪些功能
# 在执行此操作前,建议先使用 'zpool status' 检查池状态,并确保有备份。
zpool status zfspool
# 升级指定的 ZFS 存储池以启用新功能
# 这个命令会检查当前 ZFS 版本支持的,但该存储池尚未启用的功能,并将其启用。
# 警告:升级通常是单向操作。一旦升级,该存储池可能无法被运行旧版本 ZFS 的系统导入或访问。
## upgrade: zpool 的子命令,用于启用存储池的新特性标志 (feature flags)。
## zfspool: 需要进行升级操作的 ZFS 存储池的名称。
zpool upgrade zfspool
# 更新全部存储池
zpool upgrade -a
# 升级存储池到指定SPA版本
zpool upgrade -V <version> zfspool
销毁一个存储池
# 销毁一个地址池
## zpool destroy <存储池名称>
zpool destroy zfspool
# 查看存储池列表
zpool list
# 查看存储池状态
zpool status
# 查看磁盘空间使用情况
df -Th
dataset(数据集)|ZFS 文件系统管理
ZFS 数据集 (Dataset - zfs filesystem)可以将其理解为 ZFS 文件系统
│ |--- 物理磁盘/设备 (disk)
│ |--- 虚拟设备 (vdev)
│ │
存储池 (zpool)
├── 根数据集(root dataset)
│ ├── 子数据集(child dataset)
│ ├── 卷(zvol,块设备)
│ └── 快照(snapshot)
创建数据集
# 创建一个新的 ZFS 数据集
## pool/dataset: 要创建的数据集的完整路径名 (例如: zfspool/mydata)。数据集会自动继承父数据集的属性。
zfs create <存储池名/数据集名>
zfs create pool/dataset
销毁数据集
# 销毁一个 ZFS 数据集 (警告: 这将永久删除数据集中所有数据!)
## pool/dataset: 要销毁的数据集的路径名<存储池名/数据集名>
zfs destroy pool/dataset
# 递归销毁一个 ZFS 数据集及其所有子数据集和快照 (警告: 非常危险的操作!)
## -r: 递归销毁,包括所有子数据集和快照
## pool/dataset: 要销毁的父数据集路径名<存储池名/数据集名>
zfs destroy -r pool/dataset
# 删除文件系统
## -R:递归删除,包括所有子数据集和快照
## -f:强制删除,即使数据集正在使用或挂载
zfs destroy -Rf pool/dataset
列出和查看属性
# 列出系统上所有的 ZFS 数据集及其基本属性
zfs list
# 列出所有类型的文件系统和卷 (默认行为)
## -t filesystem,volume: 指定要列出的类型 (可以是 snapshot, bookmark 等)
zfs list -t filesystem,volume
# 列出指定数据集及其子数据集
## pool/dataset: 指定要查看的父数据集路径<存储池名/数据集名>
zfs list pool/dataset
# 列出所有快照
## -t snapshot: 指定只列出快照类型
zfs list -t snapshot
# 列出指定属性
## -o property1,property2,...: 指定要显示的属性列,以逗号分隔 (例如: name,used,available,mountpoint,compression)
zfs list -o name,used,available,mountpoint
# 获取指定数据集的特定属性值
## property: 要查询的属性名称 (例如: mountpoint, compression, quota, recordsize, all 等)
## pool/dataset: 目标数据集的路径名<存储池名/数据集名>
zfs get property pool/dataset
# 获取指定数据集的所有属性值
## all: 表示查询所有可获取的属性
## pool/dataset: 目标数据集的路径名<存储池名/数据集名>
zfs get all pool/dataset
设置属性
# 设置指定数据集的特定属性值
## property=value: 要设置的属性及其新值 (例如: compression=lz4, quota=10G, recordsize=128k, mountpoint=/mnt/mydata)
## pool/dataset: 目标数据集的路径名<存储池名/数据集名>
zfs set property=value pool/dataset
# 示例:启用压缩
## compression=lz4: 设置压缩算法为 lz4
## zfspool/mydata: 目标数据集
zfs set compression=lz4 zfspool/mydata
# 示例:设置配额
## quota=20G: 设置此数据集及其子数据集总共能使用的最大空间为 20GB
## zfspool/userdata: 目标数据集
zfs set quota=20G zfspool/userdata
# 示例:设置预留空间
## reservation=5G: 保证此数据集至少有 5GB 的可用空间(不含子数据集)
## zfspool/important: 目标数据集
zfs set reservation=5G zfspool/important
快照操作
# 创建一个指定数据集的快照 (快照是只读的时间点副本)
## pool/dataset@snapname: 要创建快照的数据集路径名和快照名称,用 '@' 分隔
zfs snapshot pool/dataset@snapname
# 递归地为指定数据集及其所有子数据集创建同名快照
## -r: 递归创建快照
## pool/dataset@snapname: 父数据集路径名和快照名称
zfs snapshot -r pool/dataset@snapname
# 销毁一个快照
## pool/dataset@snapname: 要销毁的快照的完整名称
zfs destroy pool/dataset@snapname
# 将数据集回滚到指定的快照状态 (警告: 快照之后的所有更改将丢失!)
## pool/dataset@snapname: 要回滚到的目标快照
zfs rollback pool/dataset@snapname
# 回滚数据集,并销毁比目标快照更新的所有快照
## -r: 在回滚时,销毁所有比指定快照更新的快照
## pool/dataset@snapname: 要回滚到的目标快照
zfs rollback -r pool/dataset@snapname
克隆、提升和重命名
# 基于快照创建一个可写的数据集克隆 (克隆初始时几乎不占用额外空间)
## pool/dataset@snapname: 源快照
## pool/new_clone_dataset: 新克隆数据集的路径名
zfs clone pool/dataset@snapname pool/new_clone_dataset
# 提升一个克隆数据集,使其与其原始快照解除依赖关系
# 提升后,原始快照依赖的父数据集可以被销毁,而克隆不受影响
## pool/clone_dataset: 要提升的克隆数据集的路径名
zfs promote pool/clone_dataset
# 重命名一个 ZFS 数据集、快照或卷
## old_pool/old_path: 对象当前的完整路径名 (可以是数据集、快照或卷)
## new_pool/new_path: 对象新的完整路径名 (通常在同一池中,仅改变路径或名称)
zfs rename old_pool/old_path new_pool/new_path
# 重命名数据集并递归重命名其快照 (如果快照名称包含旧数据集名)
## -r: 递归地重命名快照,如果快照名包含旧数据集名,会相应更新
## old_pool/old_dataset: 数据集当前的完整路径名
## new_pool/new_dataset: 数据集新的完整路径名
zfs rename -r old_pool/old_dataset new_pool/new_dataset
挂载和卸载
# 挂载一个 ZFS 数据集 (通常 ZFS 会根据 'mountpoint' 属性自动处理挂载)
## pool/dataset: 要挂载的数据集路径名
zfs mount pool/dataset
# 挂载所有 'mountpoint' 属性不是 'none' 或 'legacy' 的数据集
## -a: 挂载所有符合条件的数据集
zfs mount -a
# 卸载一个 ZFS 数据集
## pool/dataset: 要卸载的数据集路径名
zfs unmount pool/dataset
# 强制卸载一个 ZFS 数据集 (如果正常卸载失败)
## -f: 强制卸载
## pool/dataset: 要卸载的数据集路径名
zfs unmount -f pool/dataset
# 卸载所有已挂载的 ZFS 数据集
## -a: 卸载所有已挂载的数据集
zfs unmount -a
发送和接收 (用于备份和复制)
# 发送快照流 (通常用于备份或复制到另一位置)
## pool/dataset@snapname: 要发送的快照
# (输出通常通过管道 | 或重定向 > 到文件或 ssh)
zfs send pool/dataset@snapname
# 发送增量快照流 (仅发送从旧快照到新快照的变化)
## -i @oldsnap: 指定起始的旧快照 (增量发送的基础)
## pool/dataset@newsnap: 要发送的截止新快照
zfs send -i @oldsnap pool/dataset@newsnap
# 接收快照流并在目标位置创建/更新数据集
## destination_pool/destination_dataset: 接收数据并创建/更新的目标数据集路径
# (输入通常来自管道 | 或重定向 < 从文件或 ssh)
zfs receive destination_pool/destination_dataset
# 接收快照流,强制覆盖目标数据集 (如果存在) (警告: 可能导致目标数据丢失!)
## -F: 强制接收,如果目标存在,会先回滚再接收
## destination_pool/destination_dataset: 接收数据的目标数据集路径
zfs receive -F destination_pool/destination_dataset
设置zfs挂载点
# 修改ZFS数据集的挂载路径为/export/home
## set : 用于动态修改已存在数据集的属性值
## mountpoint=/export/home :
### - mountpoint : ZFS属性名,控制数据集在操作系统中的挂载位置
### - =/export/home : 将该属性值设置为指定路径(需绝对路径)
## zfspool/home :
### - zfspool : 存储池名称(zpool名称,需预先存在)
### - home : 目标数据集名称(位于zfspool池中)
#### ▶ 该数据集必须已存在,否则命令会报错"dataset does not exist"
# 无需修改/etc/fstab,ZFS自动管理挂载(除非属性设为legacy模式)
zfs set mountpoint=<本地挂载点> <存储池名称>/<数据集名称>
zfs set mountpoint=/export/home zfspool/home
## inherit 清除自定义设置,恢复为/pool/dataset格式
zfs inherit mountpoint <存储池名称>/<数据集名称>
zfs inherit mountpoint zfspool/home
为多个用户创建起始目录
请注意:由于继承而自动挂载在 /export/home/{ahrens,bonwick,billm}
下
zfs create zfspool/home/ahrens
zfs create zfspool/home/bonwick
zfs create zfspool/home/billm
向池中添加更多空间
# 向存储池中添加磁盘
zpool add zfspool -f /dev/sdx
# 创建名为 “zfspool” 的存储池 (type: “”,mirror,raidz,raidz2)
zpool create zfspool <type> c0t0d0 c1t0d0 c1t1d0
重命名ZFS数据集
# 使用 zfs rename 命令重命名一个 ZFS 数据集
# 源数据集:zfspool/home/ahrens
# 目标数据集:zfspool/home/nahrens
# 该命令将 zfspool/home/ahrens 数据集重命名为 zfspool/home/nahrens
# 注意:挂载点会自动更新为新的名称,但快照名称不会自动更新
# 需要确保目标路径不存在,否则会报错
zfs rename zfspool/home/ahrens zfspool/home/nahrens
# 验证重命名是否成功
# 使用 zfs list 检查数据集是否已重命名为 zfspool/home/nahrens
zfs list
删除ZFS数据集
# 使用 zfs destroy 命令删除 ZFS 数据集及其所有子数据集和快照
## -R:递归删除,包括所有子数据集和快照
## -f:强制删除,即使数据集正在使用或挂载
## 目标数据集:zfspool/fs
zfs destroy -Rf zfspool/fs
# 验证数据集是否已被删除
# 使用 zfs list 检查数据集是否已从系统中移除
zfs list
ZVOL(ZFS卷)管理
│ |--- 物理磁盘/设备 (disk)
│ |--- 虚拟设备 (vdev)
│ │
存储池 (zpool)
├── 根数据集(root dataset)
│ ├── 子数据集(child dataset)
│ ├── 卷(zvol,块设备)
│ └── 快照(snapshot)
ZFS 卷 (Volume - ZVOL)
-
本质: 可以将其理解为 ZFS 块设备 (Block Device)。它模拟一个原始的、未格式化的磁盘驱动器。
-
行为: 它不像数据集那样可以直接挂载来存储文件。它在操作系统层面表现为一个块设备文件(通常在 /dev/zvol/<pool_name>/<volume_name>)。
-
特点:
- 固定大小 (逻辑上): 创建时需要指定大小。虽然 ZFS ZVOL 通常是稀疏分配 (thin-provisioned) 的,意味着它们初始不占用其声明的全部空间,只在写入数据时才实际分配块,但逻辑上它们有一个固定的容量上限。可以通过设置 refreservation 使其成为厚分配 (thick-provisioned)。
- 块设备接口: 提供标准的块设备接口给操作系统或应用程序。
- 继承池特性: 仍然受益于 ZFS 的特性,如写时复制 (CoW)、快照、克隆、校验和(在块级别)。
- 快照: 同样可以为 ZVOL 创建快照。
-
主要用途:
- 虚拟机硬盘镜像。
- iSCSI Target LUNs。
- 数据库裸设备存储。
- 需要提供块级存储接口给其他应用程序或系统的场景。
创建ZFS卷
# 创建一个新的 ZFS 卷 (zvol),用于块设备 (例如给虚拟机或 iSCSI 使用)
## -V size: 指定卷的大小 (例如: 10G, 500M) 注意 -V 参数是关键
### 默认是稀疏分配 (thin-provisioned),即初始不占用 100G 物理空间
## pool/zvolname: 要创建的 ZFS 卷的完整路径名 (例如: zfspool/vmdisk)
zfs create -V <容量> <存储池名/zfs卷名>
zfs create -V 10G pool/zvolname
## volblocksize 创建一个块大小为 16K 的卷
## volblocksize,默认为 8K,影响性能
zfs create -V 100G -o volblocksize=16K pool/vmdisk_16k
- 创建时预留空间 (厚分配 - thick-provisioned):
# 创建并立即预留 100G 空间
zfs create -V 100G -o reservation=100G tank/thick_vmdisk
# 或者使用 refreservation 效果类似,但不包含快照元数据开销
# zfs create -V 100G -o refreservation=100G tank/thick_vmdisk_ref
查看 ZVOL 信息 (List/Get)
- 列出池中的所有 ZVOL:
zfs list -t volume
- 列出特定 ZVOL 的信息:
zfs list tank/vmdisk
- 获取 ZVOL 的所有属性:
zfs get all tank/vmdisk
- 获取 ZVOL 的特定属性(例如大小和块大小):
zfs get volsize,volblocksize tank/vmdisk
修改 ZVOL 属性 (Set)
- 调整 ZVOL 大小 (逻辑大小):
# 增大到 150GB
zfs set volsize=150G tank/vmdisk
- 注意: 增大通常没问题,但缩小 `volsize` 非常危险,除非你确定卷内的数据(例如文件系统)允许缩小并且已经缩小。直接缩小 `volsize` 可能导致数据丢失。
- 设置/更改预留空间:
# 为已存在的卷设置 50G 的空间预留
zfs set reservation=50G tank/vmdisk
# 取消预留
zfs set reservation=none tank/vmdisk
- 更改其他属性(例如压缩):
zfs set compression=lz4 tank/vmdisk
删除 ZVOL (Destroy)
- 删除 ZVOL(警告:这将永久删除卷及其所有数据!):
zfs destroy tank/vmdisk
- 如果 ZVOL 有快照,需要先删除快照或使用
-r
或-R
选项:
# 递归删除 ZVOL 及其所有快照和克隆
zfs destroy -r tank/vmdisk
快照与克隆 (Snapshot & Clone)
同样可以为 ZVOL
创建快照
- 为 ZVOL 创建快照:
zfs snapshot tank/vmdisk@backup-2023-10-27
- 列出 ZVOL 的快照:
zfs list -t snapshot | grep tank/vmdisk
- 从快照克隆一个新的 ZVOL:
zfs clone tank/vmdisk@backup-2023-10-27 tank/vmdisk_clone
- 克隆初始时几乎不占用额外空间,它与源快照共享数据块。
- 删除快照:
zfs destroy tank/vmdisk@backup-2023-10-27
发送与接收 (Send & Receive - 用于备份和迁移)
- 将 ZVOL 快照发送到文件:
zfs send tank/vmdisk@backup-2023-10-27 > /path/to/backupfile.zfs
- 从文件接收快照到新的 ZVOL:
zfs receive otherpool/restored_vmdisk < /path/to/backupfile.zfs
- 增量发送/接收 (只发送两次快照之间的差异):
# 发送从 snap1 到 snap2 的增量流
zfs send -i tank/vmdisk@snap1 tank/vmdisk@snap2 > /path/to/incremental_backup.zfs
# 在目标端接收增量流
zfs receive targetpool/vmdisk_replica < /path/to/incremental_backup.zfs
ZFS snapshot(快照)
│ |--- 物理磁盘/设备 (disk)
│ |--- 虚拟设备 (vdev)
│ │
存储池 (zpool)
├── 根数据集(root dataset)
│ ├── 子数据集(child dataset)
│ ├── 卷(zvol,块设备)
│ └── 快照(snapshot)
快照的定义
快照是指文件系统某一个时间点
的只读副本
即时创建、数量不限,不占用额外空间 - 块仅在发生更改时才会被复制
可通过每个文件系统根目录下的 **.zfs/snapshot**
访问
使用户可在没有系统管理员介入的情况下恢复文件,
创建快照
ZFS数据集快照
- 创建快照
# 为数据集创建快照
zfs snapshot <存储池>/<数据集>/<子数据集>@<快照名称标识符>
- 删除快照
# 删除数据集快照
zfs destroy -R zfspool/home/usera@monday
ZVOL
快照
ZVOL
创建快照
# 创建快照
## zfs snapshot 挂载点名称@快照名称
zfs snapshot volume@snapname
- 删除ZVOL快照
# 删除快照
## zfs destroy 挂载点名称@快照名称
zfs destroy data@2020-04-28
为所有后代文件系统创建快照
# 通过使用-r选项可为所有后代文件系统创建快照
## ## zfs snapshot -r 挂载点名称@快照名称
zfs snapshot -r data@2020-04-28
删除后代快照
如果使用**-r**
参数来创建快照,需要先删除下层快照。
按照提示删除下层快照即可
查看快照列表
# 查看快照列表
zfs list -t snapshot
- 查看后代快照
# 查看后代快照列表
zfs list -t snapshot -r data@2020-04-28
查看快照文件详情
查看快照中的文件
# 查看星期三的foo.c版本
cat /zfspool/home/usera/.zfs/snapshot/wednesday/foo.c
查看数据集快照详情
# 默认显示
zfs list -t snapshot -r zfspool/home
# 列出为特定文件系统创建的快照
zfs list -r -t snapshot -o name,creation zfspool/home
查看快照属性
# 获取快照属性
## zpool get listsnapshots 快照名
zpool get listsnapshots data
设置快照属性
快照属性的默认值为listsnapshots=on
,zfs list
命令**会显示**
快照列表。
设置listsnapshots=off
,zfs list
命令**不会显示**
快照列表;要使用 **zfs list -t snapshot**
命令显示快照信息。
# 设置快照显示属性
## zpool set listsnapshots=off 快照名
zpool set listsnapshots=off data
保持快照
保持快照的作用是防止被不小心销毁。
每个快照都有一个关联的用户引用计数,其初始值为 0。在一个快照上设置一个保持标志时,此计数**递增1**
;释放一个保持标志时,此计数**递减1**
。
**设置保持**
后会**禁止删除**
该快照。
# 保持一个快照或一组快照
zfs hold keep data@2020-04-28
# 使用-r选项递归保持所有后代文件系统的快照
zfs hold -r keep data@2020-04-28
# 要销毁保持的快照,须使用-d选项
zfs destroy -d data@2020-04-28
# 显示受保持的快照列表
zfs holds data@2020-04-28
zfs holds -r data@2020-04-28
# 释放对一个快照或一组快照的保持
zfs release -r keep data@2020-04-28
# 释放快照后销毁快照
zfs destroy -r data@2020-04-28
设置**保持快照**
后,删除快照时将**禁止删除**
快照重命名
# 单个快照重命名
zfs rename data@2020-04-28 data@2020-04-27
# 以递归方式重命名快照
zfs rename -r data@2020-04-28 @2020-04-27
快照回滚
-r
删除中间快照,恢复早期版本
-R
选项以销毁中间快照的克隆
# 示例快照列表
zfs list -t snapshot -r zfspool/home
# 将zfspool/home/matt文件系统回滚到tuesday快照
## zfs rollback <存储池>/<数据集>@快照名
zfs rollback zfspool/home/matt@tuesday
# 删除中间的快照即可恢复到之前的版本
zfs rollback -r zfspool/home/matt@tuesday
快照恢复
当无法直接回滚
到之前快照的时候,就需要手动恢复
数据了。
原理:将快照挂载
到一个临时挂载点
,进入这个挂载点
去拷贝
数据。
# 将快照挂载到一个临时挂载点,手动进行数据恢复
mount -t zfs data@2020-04-28 /mnt/recovery
对比两个快照差异
# 确定两个快照之间的差异
zfs diff zfspool/home/tim@snap1 zfspool/home/timh@snap2
ZFS Clone
快照的可写副本,
即时创建、数量不限;
存储大部分为共享数据的众多专用副本的理想方法.
软件安装
工作区
无盘客户机
数据集克隆
# 创建OpenSolaris源代码的克隆
zfs clone zfspool/solaris@monday zfspool/ws/lori/fix
发送与接收 (Send & Receive - 用于备份和迁移)
基于快照点
完整备份:任何快照
增量备份:任何快照增量
速度很快 - 开销与更改的数据成比例
非常高效,可执行远程复制
生成完整备份
# 生成完整备份
zfs send zfspool/fs@A >/backup/A
生成增量备份
# 生成增量备份
zfs send -i zfspool/fs@A zfspool/fs@B >/backup/B-A
远程复制:每分钟发送一次增量
# 远程复制:每分钟发送一次增量
zfs send -i zfspool/fs@11:31 zfspool/fs@11:32 |
ssh host zfs receive -d /zfspool/fs
设置属性
自动以NFS方式共享该文件系统
# 自动以 NFS 方式共享该文件系统
zfs set sharenfs=rw zfspool/home
对文件系统中所有数据启用压缩
# 对文件系统中所有数据启用压缩
zfs set compression=on zfspool
将用户A的最大空间限制为10g
# 将用户A的最大空间限制为10g
zfs set quota=10g zfspool/home/usera
保证用户B有20g的预留空间
# 保证用户B有20g的预留空间
zfs set reservation=20g zfspool/home/userb
可通过命令查询文件系统的所有属性
# 可通过命令查询文件系统的所有属性
zfs get all zfspool/home
可通过命令查询存储池的所有属性
# 可通过命令查询存储池的所有属性
zpool get all zfspool
大多数属性可通过继承方式自动设置
# 大多数属性可通过继承方式自动设置
zfs inherit <property> zfspool/home/eschrock
ZFS数据迁移
独立于主机的磁盘格式
将服务器从 x86
更改为 SPARC
,也能运行
自适应字节存储顺序 (Adaptive endianness):在两个平台上都无需额外成本
写入总是使用本地字节存储顺序 (native endianness),在块指针中设置位
仅当主机字节存储顺序 (endianness) != 块字节存储顺序时,才会针对读取进行字节交换
ZFS 负责所有处理
无需考虑设备路径、配置文件、/etc/vfstab 等等
ZFS 会在必要时进行共享/取消共享、挂载/取消挂载等等
从旧服务器上导出池
# 从旧服务器上导出池
zpool export zfspool
物理移动磁盘并将池导入到新服务器中
# 物理移动磁盘并将池导入到新服务器中
zpool import zfspool
磁盘管理
│ |--- 物理磁盘/设备 (disk)
│ |--- 虚拟设备 (vdev)
│ │
存储池 (zpool)
├── 根数据集(root dataset)
│ ├── 子数据集(child dataset)
│ ├── 卷(zvol,块设备)
│ └── 快照(snapshot)
查看磁盘
# 查看磁盘
lsblk
添加磁盘
# 将磁盘添加到存储池中
zpool add zfspool -f /dev/sdx
# 添加新设备
## (type: “”,mirror,raidz,raidz2)
zpool add zfspool <type> c0t2d0 c0t3d0 c0t4d0
标记磁盘运行状态
将设备停止或手工启动
# 将设备停止
# 在有故障的时候,标记磁盘状态为非运行
zpool offline zfspool sdc
# 将设备上线(启动)
# 标记磁盘状态为运行
zpool online zfspool sdc
删除磁盘
不能直接删除一个磁盘,因为它是一个冗余或raidz池
# 将磁盘从存储池中删除
zpool remove <存储池名称> /dev/sdx
vdc
已从zfspool
中删除
添加热备件(hot spare)磁盘
https://www.onitroad.com/jc/unix/solaris/solaris-zfs-how-to-specify-hot-spare-in-storage-pool.html
热备件磁盘平时是空闲状态,当工作磁盘
出现故障
时,可以立即将热备件磁盘
附加到存储池中,顶替故障磁盘
后,将故障磁盘分离
,然后到物理机上拆除更换故障磁盘。
创建存储池时指定镜像和热备件磁盘
# 创建存储池时添加备件
### mirror参数为镜像,后面跟两个磁盘
### spare表示热备件,后面参数跟磁盘
zpool create <存储池名称> mirror sdb sdc spare <热备件磁盘1> <热备件磁盘2>
向现有存储池添加热备件磁盘
# 添加热备磁盘
zpool add zfspool spare c0t2d0
# 向现有存储池添加热备件
## zpool add 存储池名称 spare 磁盘名
### spare表示热备件,后面参数跟磁盘名
zpool add <存储池名称> spare sdf sdg
从现有存储池中删除热备件磁盘
# 将热备磁盘删除
# 从现有存储池中删除热备件
## zpool remove 存储池名称 spare 磁盘名
zpool remove <存储池名称> sdf
附加热备件磁盘
如果已使用热备件自动替换了故障磁盘,则您可能需要在替换故障磁盘
后分离该热备件
# 例如: 如果替换故障磁盘后,sdf仍为活动热备件,则对其进行附加
zpool attach <存储池名称> sdf
替换故障磁盘
# 启动指定热备件磁盘
# 磁盘发生故障,使用replace命令替换故障磁盘sdc
## 使用用SDD磁盘替换SDC磁盘
zpool replace <存储池名称> sdc sdd
分离热备件磁盘
停止指定热备件磁盘
# 停止指定热备件磁盘
# 例如: 如果替换故障磁盘后,sdf仍为活动热备件,则对其进行分离
zpool detach <存储池名称> sdf
磁盘镜像配置
镜像会让两个磁盘数据完全一致,损坏一个磁盘,另一个磁盘的数据还在。
替换这个损坏的磁盘,数据会很快同步回来,保障数据不丢失。
添加/移除镜像磁盘
# 添加镜像设备
zpool attach <存储池> <磁盘1> <磁盘2>
zpool attach zfspool c0t1d0 c0t2d0
# 移除镜像设备
zpool detach <存储池> <磁盘1>
zpool detach zfspool c0t2d0
使用镜像创建存储池
# 在镜像配置当中我们将爆力的测试一个设备
## mirror参数为镜像,后面跟两个磁盘
zpool create -f <存储池名称> mirror sdd sde
模拟磁盘故障
# 这将创建一个镜像磁盘池组成的SDD和SDE
# 现在,让我们故意损坏SDD写零到磁盘中
dd if=/dev/zero of=/dev/sdd
检测存储池是否损坏
# 我们将使用“scrub”命令来检测这种损坏
zpool scrub <存储池名称>
替换磁盘
# 使用用SDC替换SDD
zpool replace <存储池名称> sdd sdc
# 查看存储池状态
zpool status
查看存储池当前状态和I/O状况
# 查看存储池当前状态
zpool status -v <存储池>
# 查看存储池当前I/O状况
zpool iostat <存储池> 1
添加/删除独立的日志设备(性能改善)
# 添加独立的日志设备(性能改善)
zpool add <存储池名称> log <磁盘>
# 删除独立的日志设备(性能改善)
zpool remove <存储池名称> <磁盘>
ZFS 权限管理
可以将zfs(1M) 的管理权限分派给普通用户
zfs allow
zfs unallow
将权限授予一个普通用户
# 将权限授予一个普通用户
zfs allow marks create,snapshot <存储池名称>/<数据集>
将指定权限回收
# 将指定权限回收
zfs unallow marks create,snapshot <存储池名称>/<数据集>
查看文件系统当前的权限
# 查看文件系统当前的权限
zfs allow <存储池名称>/<数据集>
其它命令
显示存储池所有操作历史记录
# 显示存储池所有操作历史记录
zpool history <存储池名称>
升级文件系统到指定ZPL版本
# 升级文件系统到指定ZPL版本
zfs upgrade -V <version> <存储池名称>/<数据集>
手工挂载/卸载文件系统
# 手工挂载文件系统
zfs mount -a
# 卸载文件系统
zfs unmount <存储池名称>/<数据集>
# 自动卸载临时挂载
zfs unmount -a