ZFS 手册

ZFS (Zettabyte file system) 是一个组合文件系统和逻辑卷管理器 由Jeff Bonwick和Matthew Ahrens领导的Sun Microsystems团队设计和实施,目前它可以存储多达256个ZiB(zebibytes)。

它开发始于2001年,并于2004年正式宣布。2005年,它被集成到Solaris的主干中,并作为OpenSolaris的一部分发布,目前,截至2015年1月,它原生于Solaris,OpenSolaris,OpenIndiana,illumos,Joyent SmartOS,OmniOS,FreeBSD。

Linux 受 GNU 公共许可证(General Public License,GPL)保护,而 ZFS 是遵循由 Sun 的通用开发和发布许可证(Common Development and Distribution License,CDDL)的。这些许可证协议的目标不同,各自的限制会有些冲突。这也就是为什么至今只有Ubuntu 16.04 + 引入了ZFS的原生内核模块。

术语 解释 备注
zpool ZFS Pool,由一个或多个VDEV构成,zpool之上再提供dataset和zvol。 zpool 不同于传统的FS特性,像LVM的VG,但是LVM最终做成LV之后还需要格式化才能使用,而zpool创建之后即使不创建dataset就可以直接使用了。
VDEV DISK,FILE VDEV 后端储存设备的类型,当然不建议FILE
Mirror 镜像VDEV,类似RAID-1
RAIDZ-1,RAIDZ-2,RAIDZ-3 RAIDZ 类型的VDEV,类似传统RAID,但是不存在写漏洞。
dataset * 数据集,比如在tank这个zpool上创建一个名为data的dataset,就表现为“tank/data”
* 可以针对不同dataset设置权限,限额,快照,挂载点等等高级特性;
zvol ZFS 提供的块设备方式,类似与dataset(文件系统),zvol为block设备,可以被格式化,可以被iSCSI分享 zvol_with_iscsi
Spare 热备盘
Slog / ZIL 单独额外的写日志设备,可以提高同步写的性能。
ARC / L2ARC 读缓存设备,一个基于RAM,一个基于外置高速SSD。
Deduplication 去重
Scrub ZFS 有scrub来替代fsck 来做一致性的检查。
在不正常的关闭之后并不需要做清洁动作,但建议每三个月至少执行一次。
snapshot 快照,可基于dataset,zvol做快照,还可以把快照克隆为dataset

Note: ZFS 是一个先进的文件系统,有了这个文件系统,大家再也不需要任何Volume Manager了。

特性 说明 备注
128文件系统 ZFS是128位,这意味着它具有很高的可扩展性:
* 最大单个文件大小为 16 EB(1 EB = 1024 PB);
* 最大 256 千万亿(256*1015 )的 ZB(1 ZB = 1024 EB)的存储;
储存池 ZFS作为一个全新的文件系统,全面抛弃传统File System + Volume Manager + Storage的架构,
所有的存储设备是通过ZFS Pool进行管理,只要把各种存储设备加 入同一个ZFS Pool,就可以轻松的在这个ZFS Pool管理配置文件系统。
不需要格式化就可以用了
丰富的VDEV架构 支持non-RAID(单盘),RAIDZ-1,RAIDZ-2,RAIDZ-3,Mirror,RAID-0,RAID-10等阵列级别,甚至一个zpool里可以包含多种VDEV以实现RAID-50,RAID-60等级别。
热备盘支持 支持Hot-spare,最大程度保证pool的数据安全。
缓存特性 不光支持基于内存的ARC缓存,还支持基于外部高速设备(SSD等)的ZiL(写)和cache(读)缓存,丰富了储存的层级。
COW
(写时拷贝)
ZFS 可以彻底抛弃fsck这种工具,因为ZFS是一个基于COW(Copy on Write)机制的文件系统。
COW是不会对硬盘上现有的文件进行重写,保证所有硬盘上的文件都是有效的。
所以不会有这种inconsistent的概念,自然就不需要这种工具了。
快照 非常简单高效的快照管理。
数据完整性验证,自动修复 在线检查(清理)和在线恢复故障,即scrub功能,实际使用中,比传统的阵列卡rebuild快得不是一点半点。 zpool scrub tank
安全 在安全上,ZFS支持类似NT风格NFSv4版的ACL(读取控制列表)。而且前面所提到的256位验证码,用户可选择多种验证方式,包括SHA-256验证算法,从而在物理存储单元级别上保证数据的安全性。
Quota
(配额)
一条命令搞定限制某个 dataset 的容量上限。
zfs set quota=10G tank/data
Reservation
(预留)
Compression
(压缩)
zlib等算法进行数据压缩
Clone
(克隆)
dataset,snapshot克隆
send / receive 在不同zpool和dataset之间自由的发送接收,甚至可以通过网络来传送至另外的主机,类似网络拷贝。

商用产品:

DIY:

要使用 ZFS 有很多种途径,大致如下:

Ubuntu 16.04+ :

# 查看zfs.ko
locate zfs.ko
modprobe zfs
lsmod | grep zfs
modinfo zfs
# 安装zfs用户工具
sudo apt install zfsutils-linux

Debian 10:

# Install the kernel headers and other dependencies
apt install -y dpkg-dev linux-headers-$(uname -r) linux-image-amd64
# Install the zfs packages
apt install zfs-dkms zfsutils-linux
# bash completion for zfs
mkdir /etc/bash_completion.d
curl -o /etc/bash_completion.d/zfs https://raw.githubusercontent.com/zfsonlinux/zfs/master/contrib/bash_completion.d/zfs
chmod ugo+x /etc/bash_completion.d/zfs
# 选装,实质安装cron定时任务来创建快照
apt install zfs-auto-snapshot

CentOS 7:

ZFS 集文件系统和卷管理器为一体,所以会和普通文件系统(如xfs)有所不同,但是当你熟悉这些对象后,你一定会惊奇这样科学高效的设计!

总的来说,ZFS 中有以下几种管理对象:

  • pool/zpool
    • 由若干磁盘/块设备组成的一个pool,可以由几种架构组成,如stripe,mirror,RAIDZ-1,RAIDZ-2,RAIDZ-3等,也可以将这几种架构混合使用;
    • 通过 zpool create 命令创建;
    • 通过 zpool list 查看;
  • dataset
    • 就是zfs本身,标准的POSIX文件系统;
    • 通过 zfs create tank/data 创建,后就会有/tank/data这个挂载点,就和其他FS一样使用了;
    • 通过 zfs list 查看;
  • volume/zvol
  • snapshot
    • 顾名思义,快照,可以为dataset,zvol创建快照;
    • 快照不能被直接访问,通过克隆快照为dataset;
    • 可以配合windows的shadowcopy(卷影复制)和SAMBA来提供文件共享服务; shadow_cpoy

6.1 zpool 管理

创建zpool:

# 获取磁盘路径,强烈建议使用这种磁盘路径!!
ls /dev/disk/by-id/ | grep -v part
zpool create -f -o ashift=12 -O dedup=off -O atime=off -O compress=off tank raidz1 <disk_by_id>

参数:

  • create 创建zpool
  • -f: 强制创建,不显示相关警告
  • -m: 另设挂载点,默认为 /<pool_name>
  • raidz 阵列冗余级别,类似raid5,还有raidz2,raidz3
  • disk_by_ids 通过 ls /dev/disk/by-id查看
  • -o 针对zpool的属性设置,version=28兼容原生zfs和zol
  • -O 针对zfs文件系统的属性设置
  • -ashift=12 针对4K对齐
  • -atime=off 关闭访问时间更新
  • -dedup=off 关闭数据去重

查看ashift:

zdb | grep ashift

导入zpool:

# 导入名为tank的zpool
zpool import tank
# 将名为tank的zpool导入为tank2
zpool import -f tank [tank2]

删除zpool:

# destroy all datasets in the pool
zfs destroy -r tank
# destroy the pool itself
zpool destroy tank

重命名zpool:

# 还未导入zpool的情况下
zpool import -f oldname newname
# 已经导入zpool的情况下
zpool export oldname
zpool import oldname newname

查看zpool状态:

# 列出zpool列表
zpool list
# 查看zpool状态
zpool status -v
# 每秒刷新一次io状态
zpool iostat -v 1

更新zpool.cache文件:

zpool set cachefile=/etc/zfs/zpool.cache tank

6.2 dataset 管理

查看 dataset:

# 查看全部卷
zfs list
# 查看tank/data,类型为快照的卷
zfs list -r -t snapshot tank/data
# 查看tank/data,类型为volume的卷
zfs list -r -t volume tank/data

创建 dataset:

# 卷将被自动挂载在 /tank/volumes1/
zfs create tank/volume1

销毁 dataset:

# 销毁 dataset
zfs destroy tank/data
# 同时销毁子dataset
zfs destroy -r tank/data

挂载/卸载dataset:

zfs mount tank/dataset1
zfs unmount tank/dataset1

如果数据集存在快照,则不能销毁该数据集。

dataset 限额:

zfs set quota=20G tank/data

属性设置: 1)

# 查看tank的某个属性
zfs get <property> tank/data
# 查看tank的全部属性
zfs get all tank
# 设置属性
zfs set <property> tank/data

ZFS 由于是从 Solaris 引入而来,所以自身也具备完善的命令来共享ZFS,如通过NFS和Samaba。

但是不同的发行版本,特别是UNIX,Solaris,和Linux差别较大,所以需要区别对待。总体来说,Oracle ZFS就通过集成的命令,Solaris通过安装相关的包,并结合自身命令,Linux就通过NFS,samba包来分享。

比如oracle ZFS就这样:

zfs create -o sharenfs=on tank/volume2
exportfs
#默认对所有网络共享
zfs set sharenfs="-maproot=root -alldir -network 192.168.1.254 -mask 255.255.255.0" tank/volume2
exportfs
#停止NFS共享
zfs set sharenfs=off tank/volume2
exportfs

8.1 创建快照

可以为dataset和volume创建快照,快照是使用 zfs snapshot 命令创建的,该命令将要创建的快照的名称用作其唯一参数,快照名称按如下方式指定:

  • 可以通过使用 -r 选项为所有子文件系统创建快照;
  • 快照没有可修改的属性,也不能将属性应用于快照;
# volume1@22082011 是快照的全名,@之后可为任意字符,一般建议是时间戳
zfs snapshot tank/volume1@now
zfs snapshot tank/dataset1@now

8.2 列出快照

# 查看快照占用情况
zfs list -t snap -o space
# 列出tank这个pool的全部快照
zfs list -r -t snapshot tank
# 列出tank/dataset这个dataset的全部快照
zfs list -t snapshot -r tank/dataset
# 列出快照,但仅显示指定的输出
zfs list -t snapshot -o name,creation tank/dataset
# 列出快照,但仅显示指定的输出,不输出header,常用于脚本
zfs list -Hpo name,creation -t snapshot -r $dataset

8.3 diff

zfs diff tank@early tank@later

8.4 销毁快照

如果已从快照创建克隆,则必须先销毁克隆,才能销毁快照。

# 销毁指定快照
zfs destroy tank/data@now
# 销毁全部快照
zfs destroy tank/data@%
# 删除所有dataset的所有快照
zfs list -H -o name -t snapshot | xargs -n1 zfs destroy

8.5 重命名快照

可以重命名快照,但是必须在从中创建它们的池和数据集中对它们进行重命名。例如:

zfs rename tank/home/cindys@083006 tank/home/cindys@today
# 快捷方式语法
zfs rename tank/home/cindys@083006 today
# -r 递归方式重命名快照
zfs rename -r users/home@yesterday @2daysago

不支持以下快照 rename 操作,因为目标池和文件系统名称与从中创建快照的池和文件系统不同:

zfs rename tank/home/cindys@today pool/home/cindys@saturday
 
cannot rename to 'pool/home/cindys@today': snapshots must be part of same dataset

8.6 克隆快照

卷的快照无法直接访问,但可以克隆,备份和回滚卷。

克隆是可写入的卷或文件系统,其初始内容与从中创建它的数据集的内容相同。与快照一样,创建克隆几乎是即时的,而且最初不占用其他磁盘空间。此外,还可以创建克隆的快照。

克隆只能从快照创建。克隆快照时,会在克隆和快照之间建立隐式相关性。即使克隆是在数据集分层结构中的某个其他位置创建的,但只要克隆存在,就无法销毁原始快照。origin 属性显示此相关性,而 zfs destroy 命令会列出任何此类相关性(如果存在)。

克隆不继承从其中创建它的数据集的属性。使用 zfs get 和 zfs set 命令,可以查看和更改克隆数据集的属性。

zfs clone tank/volume1@21082011 tank/volume1_restore

8.7 回滚快照

  • 快照回滚会丢弃指定快照之后的数据!!!
  • 可以使用 zfs rollback 命令放弃自特定快照创建以来对文件系统所做的全部更改;
  • 可以 rollback 到指定快照,如果一次回滚多个快照,需要使用 -r 选项;
  • 如果存在任何中间快照的克隆,则还必须指定-R选项以销毁克隆。
  • 如果要回滚的文件系统当前为挂载状态,则会取消挂载并重新挂载。如果无法取消挂载该文件系统,则回滚将失败。-f 选项可强制取消挂载文件系统;

在以下示例中,会将 tank/home/ahrens 文件系统回滚到 tuesday 快照:

zfs rollback tank/home/ahrens@tuesday
 
cannot rollback to 'tank/home/ahrens@tuesday': more recent snapshots exist
use '-r' to force deletion of the following snapshots:
tank/home/ahrens@wednesday
tank/home/ahrens@thursday
 
zfs rollback -r tank/home/ahrens@tuesday
在本示例中,因为已回滚到以前的 tuesday 快照,所以销毁了 wednesday 和 thursday 快照。
 
zfs list -r -t snapshot -o name,creation tank/home/ahrens
NAME                  CREATION
tank/home/ahrens@now  Wed Jun 30 16:16 2010

  • ZFS send 可以将ZFS的快照通过数据流的方式保存到文件或传输到另一台主机;
  • ZFS receive 可以接收并回写这些数据流到ZFS;(如果接收了完整的流,那么同时会创建一个新文件系统)
# 递归地创建快照(包括子dataset也创建快照)
zfs snapshot -r pool/projects@now
# option1:直接发送到另一个dataset,-R发送所有属性,快照等,-F覆盖现有数据
zfs send -R pool/projects@now | zfs receive -F pool2/projects[@now]
# option2:保存到文件 & 利用文件来恢复
zfs send -R pool/projects@snap2 > ~/projects-snap.zfs
zfs receive -F pool/projects-copy < ~/projects-snap.zfs
# option3:通过ssh传输
zfs send -R tank/home@backup | ssh root@myserver "zfs receive -F backup/home"

即“多副本”功能,作为一项可靠性功能,如果可能,ZFS 文件系统元数据会在不同的磁盘中自动存储多次。此功能称为重复块 (ditto blocks)。

通过 “zfs set copies” 命令存储用户数据的多个副本,这些副本也按文件系统进行存储。例如:

zfs set copies=2 tank/data
zfs get copies tank/data
 
NAME        PROPERTY  VALUE       SOURCE
users/home  copies    2           local

可用的值为 1、2 或 3。缺省值为 1。除了任何池级别的冗余以外,这些副本还用于诸如镜像或 RAID-Z 之类的配置中。

存储 ZFS 用户数据的多个副本的优点如下:

  • 通过支持所有 ZFS 配置从不可恢复的块读取故障(例如介质故障(一般称为位损坏))恢复来提高数据保留能力;
  • 提供数据保护,即使只有一个磁盘可用;
  • 允许您在存储池功能之外以每个文件系统为基础选择数据保护策略;

  • ZFS Deduplication 将丢弃与现有块相同的块,而是使用对现有块的引用。这节省了设备空间,但是将导致占用更多内存!
  • 大概每个block使用~320字节,数据删除表越大,写入性能就越慢!
  • 建议是不要开启;

例如,在 “tank/data” 上启用重复数据删除:

zfs set dedup=on tank/data

Note: Ubuntu 16.04 + 上安装ZFS的话,会自动生成scrub的定时任务。

要手动启动 zpool 的数据完整性检查,请使用 “zfs scrub”命令:

# 开启scrub
zpool scrub tank
# 停止scrub
zpool scrub -s tank
# 检查scrub的状态
zpool status -v tank

  • 用容量更大的硬盘去替换zpool中的硬盘时,zpool不会自动扩展,因为zpool的autoexpand属性默认关闭的,当然可以在扩展前打开,也可以手动扩展zpool;
# 创建zpool时指定
zpool create -f -o ashift=12 -o autoexpand=on -O dedup=off -O atime=off tank raidz /dev/sd{a,b,c}
# 手动指定
zpool set autoexpand=on tank
# 手动扩展zpool,sdb为新的硬盘
zpool online -e tank sdb

zpool 历史查看:

zpool history [tank]

zpool/zfs 版本查看:

sudo zfs upgrade -v
sudo zpool upgrade -v

ZFS/zpool 升级: 2)

zpool upgrade tank
zfs upgrade tank/data

zpool IO 负载查看:

zpool iostat tank [-v] 1


1)
卷属性由zpool继承而来,可通过设置全局zpool属性,也可设置单卷属性,或者二者组合。
2)
升级以使用更多新特性
  • storage/zfs/zfs手册.txt
  • 最后更改: 2019/09/20 10:19
  • 由 mrco