FreeBSD 中文手册
FreeBSD 中文社区
  • FreeBSD 中文手册
  • 编辑日志
  • 译者说明
  • FreeBSD 中文手册
  • 目录
  • 概述
  • 前言
    • 致读者
    • 第四版
    • 第三版
    • 第二版(2004)
    • 第一版(2001)
    • 本书的组织结构
    • 本书中使用的一些约定
    • 致谢
  • 第一部分:快速开始
  • 第1章 简介
    • 1.1.概述
    • 1.2.欢迎来到 FreeBSD!
    • 1.3.关于 FreeBSD 项目
  • 第2章 安装 FreeBSD
    • 2.1.概述
    • 2.2.最低硬件要求
    • 2.3.安装前的准备工作
    • 2.4.开始安装
    • 2.5.使用 bsdinstall
    • 2.6.分配磁盘空间
    • 2.7.获取安装文件
    • 2.8.账户、时区、服务和安全
    • 2.9.故障排除
    • 2.10.使用 Live CD
  • 第3章 FreeBSD 基础
    • 3.1.概述
    • 3.2.虚拟控制台和终端
    • 3.3.用户和基本账户管理
    • 3.4.权限
    • 3.5.目录结构
    • 3.6.磁盘结构
    • 3.7.文件系统的挂载与卸载
    • 3.8.进程和守护进程
    • 3.9.Shell
    • 3.10.文本编辑器
    • 3.11.设备和设备节点
    • 3.12.手册页
  • 第4章 安装应用程序:软件包和 Ports
    • 4.1.概述
    • 4.2.软件安装的概述
    • 4.3.寻找所需的应用程序
    • 4.4.使用 pkg 管理二进制包
    • 4.5.使用 Ports
    • 4.6.使用 Poudriere 构建软件包
    • 4.7.安装后的注意事项
    • 4.8.如何处理损坏的 port
  • 第5章 X Window 系统
    • 5.1.概述
    • 5.2.安装 Xorg
    • 5.3.显卡驱动
    • 5.4.Xorg 配置
    • 5.5.在 X11 中使用字体
  • 第6章 FreeBSD 中的 Wayland
    • 6.1.简介
    • 6.2.Wayland 概述
    • 6.3.Wayfire 混成器
    • 6.4.Hikari 混成器
    • 6.5.Sway 混成器
    • 6.6.使用 Xwayland
    • 6.7.使用 VNC 进行远程连接
    • 6.8.Wayland 登录管理器
    • 6.9.实用工具
  • 第7章 网络
    • 7.1.概述
    • 7.2.设置网络
    • 7.3.有线网络
    • 7.4.无线网络
    • 7.5.主机名
    • 7.6.DNS
    • 7.7.故障排除
  • 第二部分:常见任务
  • 第8章 桌面环境
    • 8.1.概述
    • 8.2.桌面环境
    • 8.3.浏览器
    • 8.4.开发工具
    • 8.5.桌面办公应用
    • 8.6.文档阅读器
    • 8.7.财务
  • 第9章 多媒体
    • 9.1.概述
    • 9.2.设置声卡
    • 9.3.音频播放器
    • 9.4.视频播放器
    • 9.5.视频会议
    • 9.6.图像扫描仪
  • 第10章 配置 FreeBSD 内核
    • 10.1.概述
    • 10.2.为什么要构建定制内核
    • 10.3.浏览系统硬件
    • 10.4.配置文件
    • 10.5.构建并安装定制内核
    • 10.6.如果发生了错误
  • 第11章 打印
    • 11.1.快速入门
    • 11.2.连接打印机
    • 11.3.常见的页面描述语言(PDL)
    • 11.4.直接打印
    • 11.5.LPD(行式打印机程序)
    • 11.6.其他打印系统
  • 第12章 Linux 二进制兼容层
    • 12.1.概述
    • 12.2.配置 Linux 二进制兼容层
    • 12.3.Linux 用户空间
    • 12.4.高级主题
  • 第13章 WINE
    • 13.1.概述
    • 13.2.WINE 概述和概念
    • 13.3.在 FreeBSD 上安装 WINE
    • 13.4.在 FreeBSD 上运行第一个 WINE 程序
    • 13.5.配置 WINE 安装程序
    • 13.6.WINE 图形化用户管理界面
    • 13.7.多用户 FreeBSD 与 WINE
    • 13.8.FreeBSD 上的 WINE 常见问题
  • 第三部分:系统管理
  • 第14章 配置与优化
    • 14.1.概述
    • 14.2.配置文件
    • 14.3.管理 FreeBSD 中的服务
    • 14.4.Cron 和 Periodic
    • 14.5.配置系统日志
    • 14.6.电源和资源管理
    • 14.7.添加交换空间
  • 第15章 FreeBSD 的引导过程
    • 15.1.概述
    • 15.2.FreeBSD 的引导过程
    • 15.3.Device Hints
    • 15.4.关机流程
  • 第16章 安全
    • 16.1.概述
    • 16.2.简介
    • 16.3.账户安全
    • 16.4.入侵检测系统(IDS)
    • 16.5.安全等级
    • 16.6.文件标志位
    • 16.7.OpenSSH
    • 16.8.OpenSSL
    • 16.9.Kerberos
    • 16.10.TCP 封装器(TCP Wrapper)
    • 16.11.访问控制列表(ACL)
    • 16.12.Capsicum
    • 16.13.进程记账
    • 16.14.资源限制
    • 16.15.监控第三方安全问题
    • 16.16.FreeBSD 安全公告
  • 第17章 jail 与容器
    • 17.1.概述
    • 17.2.jail 的类型
    • 17.3.主机配置
    • 17.4.传统 jail(厚 jail)
    • 17.5.瘦 jail
    • 17.6.管理 jail
    • 17.7.更新 jail
    • 17.8.jail 资源限制
    • 17.9.jail 管理器与容器
  • 第18章 强制访问控制
    • 18.1.概述
    • 18.2.关键术语
    • 18.3.了解 MAC 标签
    • 18.4.规划安全配置
    • 18.5.可用的 MAC 策略
    • 18.6.用户锁定
    • 18.7.MAC Jail 中的 Nagios
    • 18.8.MAC 框架的故障排除
  • 第19章 安全事件审计
    • 19.1.概述
    • 19.2.关键术语
    • 19.3.审计配置
    • 19.4.使用审计跟踪
  • 第20章 存储
    • 20.1.概述
    • 20.2.添加磁盘
    • 20.3.调整和增加磁盘大小
    • 20.4.USB 存储设备
    • 20.5.创建和使用 CD
    • 20.6.创建和使用 DVD
    • 20.7.创建和使用软盘
    • 20.8.备份的基础知识
    • 20.9.内存盘
    • 20.10.文件系统快照
    • 20.11.磁盘配额
    • 20.12.加密磁盘分区
    • 20.13.加密交换分区
    • 20.14.高可用性存储(HAST)
  • 第21章 GEOM: 模块化磁盘转换框架
    • 21.1.概述
    • 21.2.RAID0——条带
    • 21.3.RAID1——镜像
    • 21.4.RAID3——带有专用奇偶校验的字节级条带
    • 21.5.软件 RAID 设备
    • 21.6.GEOM Gate 网络设备
    • 21.7.为磁盘设备添加卷标
    • 21.8.通过 GEOM 实现 UFS 日志
  • 第22章 Z 文件系统(ZFS)
    • 22.1.是什么使 ZFS 与众不同
    • 22.2.快速入门指南
    • 22.3.zpool 管理
    • 22.4.zfs 管理
    • 22.5.委托管理
    • 22.6.高级主题
    • 22.7.更多资源
    • 22.8.ZFS 特性和术语
  • 第23章 其他文件系统
    • 23.1.概述
    • 23.2.Linux® 文件系统
    • 23.3.Windows® 文件系统
    • 23.4.MacOS® 文件系统
  • 第24章 虚拟化
    • 24.1.概述
    • 24.2.使用 macOS® 上的 Parallels Desktop 安装 FreeBSD
    • 24.3.使用 macOS® 上的 VMware Fusion 安装 FreeBSD
    • 24.4.使用 VirtualBox™ 安装 FreeBSD
    • 24.5.在 FreeBSD 上安装 VirtualBox™
    • 24.6.使用 FreeBSD 上的 QEMU 虚拟化
    • 24.7.使用 FreeBSD 上的 bhyve 虚拟机
    • 24.8.基于 FreeBSD 的 Xen™ 虚拟机
  • 第25章 本地化——i18n/L10n 的使用和设置
    • 25.1.概述
    • 25.2.使用本地化
    • 25.3.寻找 i18n 应用程序
    • 25.4.特定语言的区域配置
  • 第26章 FreeBSD 更新与升级
    • 26.1.概述
    • 26.2.更新 FreeBSD
    • 26.3.更新 Bootcode
    • 26.4.更新文档
    • 26.5.追踪开发分支
    • 26.6.从源代码更新 FreeBSD
    • 26.7.多台机器的追踪
    • 26.8.在非 FreeBSD 主机上进行构建
  • 第27章 DTrace
    • 27.1.概述
    • 27.2.实现上的差异
    • 27.3.开启 DTrace 支持
    • 27.4.启用内核外部模块 DTrace
    • 27.5.使用 DTrace
  • 第28章 USB 设备模式/USB OTG
    • 28.1.概述
    • 28.2.USB 虚拟串行端口
    • 28.3.USB 设备模式网络接口
    • 28.4.USB 虚拟存储设备
  • 第四部分:网络通讯
  • 第29章 串行通信
    • 29.1.概述
    • 29.2.串行术语和硬件
    • 29.3.终端
    • 29.4.拨入服务
    • 29.5.拨出服务
    • 29.6.设置串行控制台
  • 第30章 PPP
    • 30.1.概述
    • 30.2.配置 PPP
    • 30.3.PPP 连接的故障排除
    • 30.4.使用以太网 PPP(PPPoE)
    • 30.5.使用 ATM 上的 PPP (PPPoA)
  • 第31章 电子邮件
    • 31.1.概述
    • 31.2.邮件组件
    • 31.3.DragonFly 邮件代理(DMA)
    • 31.4.Sendmail
    • 31.5.修改邮件传输代理
    • 31.6.邮件用户代理
    • 31.7.高级主题
  • 第32章 网络服务器
    • 32.1.概述
    • 32.2.inetd 超级服务器
    • 32.3.网络文件系统(NFS)
    • 32.4.网络信息系统(NIS)
    • 32.5.轻型目录访问协议(LDAP)
    • 32.6.动态主机设置协议(DHCP)
    • 32.7.域名系统(DNS)
    • 32.8.零配置网络(mDNS/DNS-SD)
    • 32.9.Apache HTTP 服务器
    • 32.10.文件传输协议(FTP)
    • 32.11.用于 Microsoft® Windows® 客户端的文件和打印服务(Samba)
    • 32.12.用 NTP 进行时钟同步
    • 32.13.iSCSI target 和 initiator 的配置
  • 第33章 防火墙
    • 33.1.概述
    • 33.2.防火墙的概念
    • 33.3.PF
    • 33.4.IPFW
    • 33.5.IPFILTER(IPF)
    • 33.6.Blacklistd
  • 第34章 高级网络
    • 34.1.概述
    • 34.2.网关和路由
    • 34.3.虚拟主机
    • 34.4.无线高级身份验证
    • 34.5.无线自组织(Ad-hoc)模式
    • 34.6.USB 网络共享
    • 34.7.蓝牙
    • 34.8.桥接
    • 34.9.链路聚合与故障转移
    • 34.10.使用 PXE 进行无盘操作
    • 34.11.共用地址冗余协议(CARP)
    • 34.12.VLAN
  • 第五部分:附录
  • 附录 A.获取 FreeBSD
    • A.1.镜像站
    • A.2.使用 Git
    • A.3.使用 Subversion
    • A.4.光盘
  • 附录 B.书目
    • B.1.FreeBSD 相关书籍
    • B.2.安全性参考文献
    • B.3.UNIX 历史
    • B.4.期刊与杂志
  • 附录 C.网络资源
    • C.1.网站
    • C.2.邮件列表
    • C.3.Usenet 新闻组
  • 附录 D.OpenPGP 密钥
    • D.1.官方成员
  • 术语表
  • 后记
由 GitBook 提供支持

FreeBSD 中文社区

在本页
  • 22.4.1. 创建和销毁数据集
  • 22.4.2. 创建和销毁卷
  • 22.4.3. 重命名数据集
  • 22.4.4. 设置数据集属性
  • 22.4.4.1. 获取和设置共享属性
  • 22.4.5. 管理快照
  • 22.4.5.1. 创建快照
  • 22.4.5.2. 比较快照
  • 22.4.5.3. 快照回滚
  • 22.4.5.4. 从快照中恢复单个文件
  • 22.4.6. 管理克隆
  • 22.4.7. 复制
  • 22.4.7.1. 增量备份
  • 22.4.7.2. 通过 SSH 发送加密备份
  • 22.4.8. 数据集、用户和组配额
  • 22.4.9. 保留空间
  • 22.4.10. 压缩
  • 22.4.11. Zstandard 压缩
  • 22.4.12. 去重
  • 22.4.13. ZFS 和 Jail

这有帮助吗?

在GitHub上编辑
导出为 PDF
  1. 第22章 Z 文件系统(ZFS)

22.4.zfs 管理

22.4.1. 创建和销毁数据集

与传统的磁盘和卷管理器不同,ZFS 中的空间 不是 预先分配的。在传统文件系统中,分区和分配空间后,无法在没有新增磁盘的情况下添加新的文件系统。而在 ZFS 中,可以随时创建新的文件系统。每个 数据集 都有包括压缩、去重、缓存和配额等特性,还包含只读、大小写敏感、网络文件共享和挂载点等其他有用的属性。可以将数据集嵌套在彼此内部,子数据集将继承其父数据集的属性。可以 委托、复制、快照、jail 来管理和销毁每个数据集。为每种不同类型或文件集创建一个单独的数据集具有优势。拥有大量数据集的缺点是,像 zfs list 这样的命令会变慢,而且挂载数百个甚至数千个数据集会减慢 FreeBSD 启动过程。

创建新的数据集并启用 LZ4 压缩:

# zfs list
NAME                  USED  AVAIL  REFER  MOUNTPOINT
mypool                781M  93.2G   144K  none
mypool/ROOT           777M  93.2G   144K  none
mypool/ROOT/default   777M  93.2G   777M  /
mypool/tmp            176K  93.2G   176K  /tmp
mypool/usr            616K  93.2G   144K  /usr
mypool/usr/home       184K  93.2G   184K  /usr/home
mypool/usr/ports      144K  93.2G   144K  /usr/ports
mypool/usr/src        144K  93.2G   144K  /usr/src
mypool/var           1.20M  93.2G   608K  /var
mypool/var/crash      148K  93.2G   148K  /var/crash
mypool/var/log        178K  93.2G   178K  /var/log
mypool/var/mail       144K  93.2G   144K  /var/mail
mypool/var/tmp        152K  93.2G   152K  /var/tmp
# zfs create -o compress=lz4 mypool/usr/mydataset
# zfs list
NAME                   USED  AVAIL  REFER  MOUNTPOINT
mypool                 781M  93.2G   144K  none
mypool/ROOT            777M  93.2G   144K  none
mypool/ROOT/default    777M  93.2G   777M  /
mypool/tmp             176K  93.2G   176K  /tmp
mypool/usr             704K  93.2G   144K  /usr
mypool/usr/home        184K  93.2G   184K  /usr/home
mypool/usr/mydataset  87.5K  93.2G  87.5K  /usr/mydataset
mypool/usr/ports       144K  93.2G   144K  /usr/ports
mypool/usr/src         144K  93.2G   144K  /usr/src
mypool/var            1.20M  93.2G   610K  /var
mypool/var/crash       148K  93.2G   148K  /var/crash
mypool/var/log         178K  93.2G   178K  /var/log
mypool/var/mail        144K  93.2G   144K  /var/mail
mypool/var/tmp         152K  93.2G   152K  /var/tmp

销毁数据集比删除数据集中的文件要快得多,因为它不涉及扫描文件和更新相应的元数据。

销毁创建的数据集:

# zfs list
NAME                   USED  AVAIL  REFER  MOUNTPOINT
mypool                 880M  93.1G   144K  none
mypool/ROOT            777M  93.1G   144K  none
mypool/ROOT/default    777M  93.1G   777M  /
mypool/tmp             176K  93.1G   176K  /tmp
mypool/usr             101M  93.1G   144K  /usr
mypool/usr/home        184K  93.1G   184K  /usr/home
mypool/usr/mydataset   100M  93.1G   100M  /usr/mydataset
mypool/usr/ports       144K  93.1G   144K  /usr/ports
mypool/usr/src         144K  93.1G   144K  /usr/src
mypool/var            1.20M  93.1G   610K  /var
mypool/var/crash       148K  93.1G   148K  /var/crash
mypool/var/log         178K  93.1G   178K  /var/log
mypool/var/mail        144K  93.1G   144K  /var/mail
mypool/var/tmp         152K  93.1G   152K  /var/tmp
# zfs destroy mypool/usr/mydataset
# zfs list
NAME                  USED  AVAIL  REFER  MOUNTPOINT
mypool                781M  93.2G   144K  none
mypool/ROOT           777M  93.2G   144K  none
mypool/ROOT/default   777M  93.2G   777M  /
mypool/tmp            176K  93.2G   176K  /tmp
mypool/usr            616K  93.2G   144K  /usr
mypool/usr/home       184K  93.2G   184K  /usr/home
mypool/usr/ports      144K  93.2G   144K  /usr/ports
mypool/usr/src        144K  93.2G   144K  /usr/src
mypool/var           1.21M  93.2G   612K  /var
mypool/var/crash      148K  93.2G   148K  /var/crash
mypool/var/log        178K  93.2G   178K  /var/log
mypool/var/mail       144K  93.2G   144K  /var/mail
mypool/var/tmp        152K  93.2G   152K  /var/tmp

在现代版本的 ZFS 中,zfs destroy 是异步的,释放空间可能需要几分钟才会在池中显示出来。使用 zpool get freeing poolname 来查看 freeing 属性,显示哪些数据集正在后台释放其块。如果有子数据集,例如 快照 或其他数据集,销毁父数据集是不可行的。要销毁数据集及其子数据集,可以使用 -r 递归销毁数据集及其子数据集。使用 -n -v 来列出将在此操作中销毁的数据集和快照,但不会实际销毁任何东西。销毁快照时回收的空间也会显示出来。

22.4.2. 创建和销毁卷

卷是一种特殊的数据集类型。它不是作为文件系统挂载,而是作为块设备暴露在 /dev/zvol/poolname/dataset 下。这使得卷可以用于其他文件系统、作为虚拟机的磁盘,或通过 iSCSI 或 HAST 等协议将其提供给其他网络主机。

你可以格式化卷,使用任何文件系统,或者不使用文件系统来存储原始数据。对于用户来说,卷看起来像是普通磁盘。将普通文件系统放到这些 zvol 上提供了普通磁盘或文件系统没有的功能。例如,在一个 250MB 的卷上使用压缩属性,可以创建一个压缩的 FAT 文件系统。

# zfs create -V 250m -o compression=on tank/fat32
# zfs list tank
NAME USED AVAIL REFER MOUNTPOINT
tank 258M  670M   31K /tank
# newfs_msdos -F32 /dev/zvol/tank/fat32
# mount -t msdosfs /dev/zvol/tank/fat32 /mnt
# df -h /mnt | grep fat32
Filesystem           Size Used Avail Capacity Mounted on
/dev/zvol/tank/fat32 249M  24k  249M     0%   /mnt
# mount | grep fat32
/dev/zvol/tank/fat32 on /mnt (msdosfs, local)

销毁卷的过程与销毁常规文件系统数据集类似。该操作几乎是即时完成的,但可能需要几分钟才能在后台回收空闲空间。

22.4.3. 重命名数据集

要更改数据集的名称,使用 zfs rename 命令。要更改数据集的父级,也使用这个命令。将数据集重命名为不同的父级,将改变继承自父级的属性值。重命名一个数据集会卸载它并将其挂载到新位置(该位置继承自新父级)。要防止这种行为,使用 -u。

将数据集重命名并移动到不同的父级:

# zfs list
NAME                   USED  AVAIL  REFER  MOUNTPOINT
mypool                 780M  93.2G   144K  none
mypool/ROOT            777M  93.2G   144K  none
mypool/ROOT/default    777M  93.2G   777M  /
mypool/tmp             176K  93.2G   176K  /tmp
mypool/usr             704K  93.2G   144K  /usr
mypool/usr/home        184K  93.2G   184K  /usr/home
mypool/usr/mydataset  87.5K  93.2G  87.5K  /usr/mydataset
mypool/usr/ports       144K  93.2G   144K  /usr/ports
mypool/usr/src         144K  93.2G   144K  /usr/src
mypool/var            1.21M  93.2G   614K  /var
mypool/var/crash       148K  93.2G   148K  /var/crash
mypool/var/log         178K  93.2G   178K  /var/log
mypool/var/mail        144K  93.2G   144K  /var/mail
mypool/var/tmp         152K  93.2G   152K  /var/tmp
# zfs rename mypool/usr/mydataset mypool/var/newname
# zfs list
NAME                  USED  AVAIL  REFER  MOUNTPOINT
mypool                780M  93.2G   144K  none
mypool/ROOT           777M  93.2G   144K  none
mypool/ROOT/default   777M  93.2G   777M  /
mypool/tmp            176K  93.2G   176K  /tmp
mypool/usr            616K  93.2G   144K  /usr
mypool/usr/home       184K  93.2G   184K  /usr/home
mypool/usr/ports      144K  93.2G   144K  /usr/ports
mypool/usr/src        144K  93.2G   144K  /usr/src
mypool/var           1.29M  93.2G   614K  /var
mypool/var/crash      148K  93.2G   148K  /var/crash
mypool/var/log        178K  93.2G   178K  /var/log
mypool/var/mail       144K  93.2G   144K  /var/mail
mypool/var/newname   87.5K  93.2G  87.5K  /var/newname
mypool/var/tmp        152K  93.2G   152K  /var/tmp

重命名快照使用相同的命令。由于快照的性质,不能更改它们的父级。要重命名递归快照,指定 -r;这将重命名所有具有相同名称的子数据集中的快照。

# zfs list -t snapshot
NAME                                USED  AVAIL  REFER  MOUNTPOINT
mypool/var/newname@first_snapshot      0      -  87.5K  -
# zfs rename mypool/var/newname@first_snapshot new_snapshot_name
# zfs list -t snapshot
NAME                                   USED  AVAIL  REFER  MOUNTPOINT
mypool/var/newname@new_snapshot_name      0      -  87.5K  -

22.4.4. 设置数据集属性

每个 ZFS 数据集都有一些控制其行为的属性。大多数属性默认从父数据集继承,但可以在本地进行覆盖。使用 zfs set 命令设置数据集的属性,语法为 <property=value dataset>。大多数属性有一组有限的有效值,zfs get 将显示每个可能的属性及其有效值。使用 zfs inherit 可以将大多数属性恢复为继承的值。也可以定义用户自定义属性,它们成为数据集配置的一部分,并提供关于数据集或其内容的更多信息。为了区分这些自定义属性与 ZFS 提供的属性,可以使用冒号(:)创建自定义命名空间。

# zfs set custom:costcenter=1234 tank
# zfs get custom:costcenter tank
NAME PROPERTY           VALUE SOURCE
tank custom:costcenter  1234  local

要删除自定义属性,使用 zfs inherit 并加上 -r 选项。如果自定义属性在任何父级数据集中未定义,此选项将删除它(但池的历史记录仍然会记录该更改)。

# zfs inherit -r custom:costcenter tank
# zfs get custom:costcenter tank
NAME    PROPERTY           VALUE              SOURCE
tank    custom:costcenter  -                  -
# zfs get all tank | grep custom:costcenter
#

22.4.4.1. 获取和设置共享属性

两个常用且有用的数据集属性是 NFS 和 SMB 共享选项。设置这些属性可以定义 ZFS 如何以及是否通过网络共享数据集。目前,FreeBSD 仅支持设置 NFS 共享。要获取共享的当前状态,可以输入:

# zfs get sharenfs mypool/usr/home
NAME             PROPERTY  VALUE    SOURCE
mypool/usr/home  sharenfs  on       local
# zfs get sharesmb mypool/usr/home
NAME             PROPERTY  VALUE    SOURCE
mypool/usr/home  sharesmb  off      local

要启用数据集的共享,可以输入:

#  zfs set sharenfs=on mypool/usr/home

可以为通过 NFS 共享的数据集设置其他选项,如 -alldirs、-maproot 和 -network。要设置共享选项,可以输入:

#  zfs set sharenfs="-alldirs,-maproot=root,-network=192.168.1.0/24" mypool/usr/home

22.4.5. 管理快照

快照 是 ZFS 最强大的功能之一。快照提供了数据集的只读、时间点拷贝。通过写时复制(COW)技术,ZFS 通过保留旧版本的数据在磁盘上创建快照,快速创建快照。如果没有快照,ZFS 会在数据被重写或删除时回收空间,为将来使用腾出空间。快照通过记录当前数据集与之前版本之间的差异来节省磁盘空间。快照适用于整个数据集,而不是单独的文件或目录。来自数据集的快照会复制其中包含的所有内容,包括文件系统属性、文件、目录、权限等。快照在创建时不会使用额外的空间,但随着它们引用的块发生变化,会消耗空间。使用 -r 创建的递归快照会在数据集及其子项中创建具有相同名称的快照,从而提供文件系统的一个一致的时间点快照。当一个应用程序在相关的数据集中或相互依赖的文件上工作时,这一点尤为重要。如果没有快照,备份将是不同时间点的文件副本。

ZFS 中的快照提供了许多其他文件系统所没有的功能。快照使用的一个典型示例是在执行像软件安装或系统升级等风险较高的操作时,作为快速备份当前文件系统状态的一种方式。如果操作失败,回滚到快照可以将系统恢复到创建快照时的状态。如果升级成功,则删除快照以释放空间。没有快照的情况下,失败的升级通常需要恢复备份,这既麻烦又费时,并且可能需要系统不可用的时间。回滚快照很快,即使系统在正常操作中运行,也几乎没有或没有停机时间。在多 TB 存储系统中,考虑到从备份中复制数据所需的时间,节省的时间是巨大的。快照不是池完整备份的替代品,但提供了一种快速简便的方式,在特定时间存储数据集的副本。

22.4.5.1. 创建快照

要创建快照,可以使用 zfs snapshot <数据集>@<快照名> 命令。添加 -r 选项可以递归创建快照,在所有子数据集上使用相同的名称。

创建整个池的递归快照:

# zfs list -t all
NAME                                   USED  AVAIL  REFER  MOUNTPOINT
mypool                                 780M  93.2G   144K  none
mypool/ROOT                            777M  93.2G   144K  none
mypool/ROOT/default                    777M  93.2G   777M  /
mypool/tmp                             176K  93.2G   176K  /tmp
mypool/usr                             616K  93.2G   144K  /usr
mypool/usr/home                        184K  93.2G   184K  /usr/home
mypool/usr/ports                       144K  93.2G   144K  /usr/ports
mypool/usr/src                         144K  93.2G   144K  /usr/src
mypool/var                            1.29M  93.2G   616K  /var
mypool/var/crash                       148K  93.2G   148K  /var/crash
mypool/var/log                         178K  93.2G   178K  /var/log
mypool/var/mail                        144K  93.2G   144K  /var/mail
mypool/var/newname                    87.5K  93.2G  87.5K  /var/newname
mypool/var/newname@new_snapshot_name      0      -  87.5K  -
mypool/var/tmp                         152K  93.2G   152K  /var/tmp
# zfs snapshot -r mypool@my_recursive_snapshot
# zfs list -t snapshot
NAME                                        USED  AVAIL  REFER  MOUNTPOINT
mypool@my_recursive_snapshot                   0      -   144K  -
mypool/ROOT@my_recursive_snapshot              0      -   144K  -
mypool/ROOT/default@my_recursive_snapshot      0      -   777M  -
mypool/tmp@my_recursive_snapshot               0      -   176K  -
mypool/usr@my_recursive_snapshot               0      -   144K  -
mypool/usr/home@my_recursive_snapshot          0      -   184K  -
mypool/usr/ports@my_recursive_snapshot         0      -   144K  -
mypool/usr/src@my_recursive_snapshot           0      -   144K  -
mypool/var@my_recursive_snapshot               0      -   616K  -
mypool/var/crash@my_recursive_snapshot         0      -   148K  -
mypool/var/log@my_recursive_snapshot           0      -   178K  -
mypool/var/mail@my_recursive_snapshot          0      -   144K  -
mypool/var/newname@new_snapshot_name           0      -  87.5K  -
mypool/var/newname@my_recursive_snapshot       0      -  87.5K  -
mypool/var/tmp@my_recursive_snapshot           0      -   152K  -

快照不会在正常的 zfs list 操作中显示。要列出快照,必须在 zfs list 命令后加上 -t snapshot 选项。-t all 会显示文件系统和快照。

快照不会直接挂载,因此在 MOUNTPOINT 列中不会显示路径。由于快照在创建后是只读的,因此 ZFS 不会在 AVAIL 列中显示可用空间。可以通过以下命令比较快照与原数据集:

# zfs list -rt all mypool/usr/home
NAME                                    USED  AVAIL  REFER  MOUNTPOINT
mypool/usr/home                         184K  93.2G   184K  /usr/home
mypool/usr/home@my_recursive_snapshot      0      -   184K  -

同时显示数据集和快照可以揭示快照是如何以 写时复制 COW 方式工作的。它们只保存所做的更改(delta),而不是重新保存整个文件系统的内容。这意味着,在进行更改时,快照占用的空间非常小。通过复制文件到数据集,再创建第二个快照,可以更加清楚地观察空间的使用:

# cp /etc/passwd /var/tmp
# zfs snapshot mypool/var/tmp@after_cp
# zfs list -rt all mypool/var/tmp
NAME                                   USED  AVAIL  REFER  MOUNTPOINT
mypool/var/tmp                         206K  93.2G   118K  /var/tmp
mypool/var/tmp@my_recursive_snapshot    88K      -   152K  -
mypool/var/tmp@after_cp                   0      -   118K  -

第二个快照包含了复制操作后数据集的更改,从而带来了巨大的空间节省。注意,mypool/var/tmp@my_recursive_snapshot 快照的大小也在 USED 列中发生了变化,显示了它与之后创建的快照之间的差异。

22.4.5.2. 比较快照

ZFS 提供了一个内建命令,用于比较两个快照之间内容的差异。这对于长期保存大量快照时非常有用,用户可以查看文件系统如何随时间变化。例如,zfs diff 让用户找到最近的快照,查看是否仍包含被误删的文件。对前面章节中创建的两个快照进行比较,得到以下输出:

# zfs list -rt all mypool/var/tmp
NAME                                   USED  AVAIL  REFER  MOUNTPOINT
mypool/var/tmp                         206K  93.2G   118K  /var/tmp
mypool/var/tmp@my_recursive_snapshot    88K      -   152K  -
mypool/var/tmp@after_cp                   0      -   118K  -
# zfs diff mypool/var/tmp@my_recursive_snapshot
M       /var/tmp/
+       /var/tmp/passwd

该命令列出了指定快照(此处为 mypool/var/tmp@my_recursive_snapshot)与当前文件系统之间的变化。第一列显示更改类型:

+
添加路径或文件

-

删除路径或文件

M

修改路径或文件

R

重命名路径或文件

将输出与表格对比,可以清楚地看到 ZFS 在创建 mypool/var/tmp@my_recursive_snapshot 快照后添加了 passwd 文件,这也导致了挂载在 /var/tmp 的父目录发生了修改。

比较两个快照在使用 ZFS 复制功能将数据集传输到不同主机进行备份时非常有帮助。

通过提供完整的数据集名称和两个快照名称来比较两个快照:

# cp /var/tmp/passwd /var/tmp/passwd.copy
# zfs snapshot mypool/var/tmp@diff_snapshot
# zfs diff mypool/var/tmp@my_recursive_snapshot mypool/var/tmp@diff_snapshot
M       /var/tmp/
+       /var/tmp/passwd
+       /var/tmp/passwd.copy
# zfs diff mypool/var/tmp@my_recursive_snapshot mypool/var/tmp@after_cp
M       /var/tmp/
+       /var/tmp/passwd

备份管理员可以比较从发送主机接收到的两个快照,并确定数据集中的实际变化。有关更多信息,请参阅 Replication 部分。

22.4.5.3. 快照回滚

当至少有一个快照可用时,随时可以回滚到该快照。最常见的情况是当前数据集状态不再有效,或者更倾向于使用旧版本。例如,进行本地开发测试时出错,或者系统更新失败导致系统功能受损,或需要恢复被删除的文件或目录,这些情况都很常见。要回滚到快照,可以使用 zfs rollback <snapshotname> 命令。如果有大量更改,操作可能会花费很长时间。在此期间,数据集始终保持一致的状态,就像一个符合 ACID 原则的数据库执行回滚一样。这个过程在数据集在线并且无需停机的情况下进行。回滚后,数据集的状态将恢复到原始快照创建时的状态。回滚到快照会丢弃该数据集中所有不属于该快照的其他数据。如果在回滚到先前快照之前拍摄当前状态的快照,那么在之后需要某些数据时,可以方便地进行回滚。这样,用户可以在快照之间来回切换,而不会丢失仍然有价值的数据。

在第一个示例中,由于不小心执行了 rm 命令删除了超过预期的数据,因此回滚到一个快照:

# zfs list -rt all mypool/var/tmp
NAME                                   USED  AVAIL  REFER  MOUNTPOINT
mypool/var/tmp                         262K  93.2G   120K  /var/tmp
mypool/var/tmp@my_recursive_snapshot    88K      -   152K  -
mypool/var/tmp@after_cp               53.5K      -   118K  -
mypool/var/tmp@diff_snapshot              0      -   120K  -
# ls /var/tmp
passwd          passwd.copy     vi.recover
# rm /var/tmp/passwd*
# ls /var/tmp
vi.recover

此时,用户发现删除了多余的文件,并希望恢复它们。ZFS 提供了一种简单的方式来恢复文件,只需定期执行重要数据的快照。在回滚到上一个快照后,可以恢复丢失的文件,并从该点重新开始:

# zfs rollback mypool/var/tmp@diff_snapshot
# ls /var/tmp
passwd          passwd.copy     vi.recover

回滚操作将数据集恢复到最后一个快照的状态。回滚到一个较早的快照并且之后有其他快照也是可能的。在尝试这样做时,ZFS 会发出以下警告:

# zfs list -rt snapshot mypool/var/tmp
AME                                   USED  AVAIL  REFER  MOUNTPOINT
mypool/var/tmp@my_recursive_snapshot    88K      -   152K  -
mypool/var/tmp@after_cp               53.5K      -   118K  -
mypool/var/tmp@diff_snapshot              0      -   120K  -
# zfs rollback mypool/var/tmp@my_recursive_snapshot
cannot rollback to 'mypool/var/tmp@my_recursive_snapshot': more recent snapshots exist
use '-r' to force deletion of the following snapshots:
mypool/var/tmp@after_cp
mypool/var/tmp@diff_snapshot

此警告表示,在用户想要回滚到的快照和当前数据集状态之间存在其他快照。要完成回滚,需要删除这些快照。由于快照是只读的,ZFS 无法跟踪数据集在不同状态之间的所有更改,除非用户指定 -r 选项确认这是所需的操作。如果这是预期的操作,并理解删除所有中间快照的后果,可以执行以下命令:

# zfs rollback -r mypool/var/tmp@my_recursive_snapshot
# zfs list -rt snapshot mypool/var/tmp
NAME                                   USED  AVAIL  REFER  MOUNTPOINT
mypool/var/tmp@my_recursive_snapshot     8K      -   152K  -
# ls /var/tmp
vi.recover

从 zfs list -t snapshot 的输出可以确认,在执行 zfs rollback -r 后,中间快照已被删除。

22.4.5.4. 从快照中恢复单个文件

快照存储在父数据集下的一个隐藏目录中:.zfs/snapshots/snapshotname。默认情况下,即使执行标准的 ls -a 命令,这些目录也不会显示。尽管目录不显示,仍然可以像访问普通目录一样访问它。名为 snapdir 的属性控制这些隐藏目录是否显示在目录列表中。将该属性设置为 visible 可以让它们出现在 ls 和其他涉及目录内容的命令的输出中。

# zfs get snapdir mypool/var/tmp
NAME            PROPERTY  VALUE    SOURCE
mypool/var/tmp  snapdir   hidden   default
# ls -a /var/tmp
.               ..              passwd          vi.recover
# zfs set snapdir=visible mypool/var/tmp
# ls -a /var/tmp
.               ..              .zfs            passwd          vi.recover

通过从快照中将文件复制回父数据集,可以将单个文件恢复到先前的状态。.zfs/snapshot 下的目录结构包含一个与之前创建的快照同名的目录,便于识别。以下示例展示了如何从隐藏的 .zfs 目录中恢复文件,通过将文件从包含最新版本的快照复制回来:

# rm /var/tmp/passwd
# ls -a /var/tmp
.               ..              .zfs            vi.recover
# ls /var/tmp/.zfs/snapshot
after_cp                my_recursive_snapshot
# ls /var/tmp/.zfs/snapshot/after_cp
passwd          vi.recover
# cp /var/tmp/.zfs/snapshot/after_cp/passwd /var/tmp

即使将 snapdir 属性设置为 hidden,执行 ls .zfs/snapshot 命令仍然会列出该目录的内容。管理员可以决定是否显示这些目录。该设置是针对每个数据集的。复制文件或目录从这个隐藏的 .zfs/snapshot 目录非常简单。反过来尝试复制文件到快照目录时会出现以下错误:

# cp /etc/rc.conf /var/tmp/.zfs/snapshot/after_cp/
cp: /var/tmp/.zfs/snapshot/after_cp/rc.conf: Read-only file system

此错误提醒用户,快照是只读的,创建后不能更改。无法将文件复制到快照目录中或从中删除文件,因为这样会改变它们所表示的数据集的状态。

快照根据自快照创建以来父文件系统的变化情况来消耗空间。快照的 written 属性跟踪该快照使用的空间。

要销毁快照并回收空间,可以使用 zfs destroy <数据集>@<快照> 命令。加上 -r 选项可以递归地删除父数据集下同名的所有快照。使用 -n -v 选项,命令会显示要删除的快照列表及其回收空间的估算值,而不会执行实际的销毁操作。

22.4.6. 管理克隆

克隆是某快照的副本,能像常规的数据集一样处理它。不同于快照,克隆是可写的和可挂载的,并且有自己的属性。在使用 zfs clone 创建克隆之后,无法销毁原始快照。要反转克隆和快照之间的父子关系,可以使用 zfs promote。提升克隆将使快照成为克隆的子项,而不是原始父数据集的子项。这将改变 ZFS 对空间的计算方式,但不会实际改变占用的空间。克隆可以挂载到 ZFS 文件系统层次结构中的任何位置,而不仅仅是原始快照所在的位置。

下面是展示克隆功能的示例数据集:

# zfs list -rt all camino/home/joe
NAME                    USED  AVAIL  REFER  MOUNTPOINT
camino/home/joe         108K   1.3G    87K  /usr/home/joe
camino/home/joe@plans    21K      -  85.5K  -
camino/home/joe@backup    0K      -    87K  -

克隆的典型用途是在保持快照的同时,尝试对特定数据集进行实验,以便在出现问题时可以恢复。由于快照无法更改,可以创建一个可读写的快照克隆。经过实验并取得理想结果后,可以提升克隆为数据集,并删除原始文件系统。删除原始数据集不是严格必要的,因为克隆和数据集可以共存而不会发生问题。

# zfs clone camino/home/joe@backup camino/home/joenew
# ls /usr/home/joe*
/usr/home/joe:
backup.txz     plans.txt

/usr/home/joenew:
backup.txz     plans.txt
# df -h /usr/home
Filesystem          Size    Used   Avail Capacity  Mounted on
usr/home/joe        1.3G     31k    1.3G     0%    /usr/home/joe
usr/home/joenew     1.3G     31k    1.3G     0%    /usr/home/joenew

创建克隆时,它是快照创建时数据集的完全副本。现在可以独立于其原始数据集更改克隆。两者之间的连接是快照,ZFS 会在 origin 属性中记录这个连接。使用 zfs promote 提升克隆将使克隆成为独立的数据集。这将删除 origin 属性的值,并断开克隆与快照之间的连接。以下示例展示了这一过程:

# zfs get origin camino/home/joenew
NAME                  PROPERTY  VALUE                     SOURCE
camino/home/joenew    origin    camino/home/joe@backup    -
# zfs promote camino/home/joenew
# zfs get origin camino/home/joenew
NAME                  PROPERTY  VALUE   SOURCE
camino/home/joenew    origin    -       -

在进行了一些更改后,比如将 loader.conf 复制到提升后的克隆中,旧目录在这种情况下变得过时。此时可以用提升后的克隆来替换它。要实现这一点,首先 zfs destroy 删除旧的数据集,然后 zfs rename 将克隆重命名为旧的数据集名称(或者完全不同的名称)。

# cp /boot/defaults/loader.conf /usr/home/joenew
# zfs destroy -f camino/home/joe
# zfs rename camino/home/joenew camino/home/joe
# ls /usr/home/joe
backup.txz     loader.conf     plans.txt
# df -h /usr/home
Filesystem          Size    Used   Avail Capacity  Mounted on
usr/home/joe        1.3G    128k    1.3G     0%    /usr/home/joe

现在,克隆的快照变成了一个普通的数据集。它包含来自原始快照的所有数据以及新增的文件,如 loader.conf。克隆为 ZFS 用户提供了在不同场景中非常有用的功能。例如,可以为 jail 提供包含不同应用集的快照。用户可以克隆这些快照并根据需要添加自己的应用程序。待对更改感到满意,就可以将克隆提升为完整的数据集,并将其提供给最终用户,用户可以像使用真正的数据集一样使用它。这在提供这些 jail 时节省了时间和管理开销。

22.4.7. 复制

将数据仅存储在单个池中的单一位置,会使其暴露于诸如盗窃、自然灾害或人为灾害等风险中。因此,定期备份整个池至关重要。ZFS 提供了内置的序列化功能,可以将数据的流表示发送到标准输出。利用此功能,可以将数据存储到连接到本地系统的另一个池中,也可以通过网络将其发送到另一个系统。快照是这种复制的基础(请参见 ZFS 快照 部分)。用于复制数据的命令是 zfs send 和 zfs receive。

以下示例展示了如何使用这两个池进行 ZFS 复制:

# zpool list
NAME    SIZE  ALLOC   FREE   CKPOINT  EXPANDSZ   FRAG   CAP  DEDUP  HEALTH  ALTROOT
backup  960M    77K   896M         -         -     0%    0%  1.00x  ONLINE  -
mypool  984M  43.7M   940M         -         -     0%    4%  1.00x  ONLINE  -

名为 mypool 的池是主池,用于定期读写数据。使用第二个备用池 backup,以防主池不可用。请注意,ZFS 不会自动执行故障转移,管理员需要在需要时手动进行。使用快照提供一致的文件系统版本进行复制。在创建了 mypool 的快照后,可以通过复制快照将其复制到 backup 池。这不包括自上次快照以来的更改。

# zfs snapshot mypool@backup1
# zfs list -t snapshot
NAME                    USED  AVAIL  REFER  MOUNTPOINT
mypool@backup1             0      -  43.6M  -

现在已经存在了一个快照,使用 zfs send 创建一个表示快照内容的流。将此流存储为文件,或在另一个池上接收它。必须将流重定向到文件或管道,否则会出现错误:

# zfs send mypool@backup1
Error: Stream can not be written to a terminal.
You must redirect standard output.

要备份数据集,使用 zfs send 时将流重定向到挂载的备份池上的文件。确保池有足够的可用空间来容纳发送的快照的大小,这意味着快照中包含的数据,而不是与上一个快照的更改。

# zfs send mypool@backup1 > /backup/backup1
# zpool list
NAME    SIZE  ALLOC   FREE   CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
backup  960M  63.7M   896M         -         -     0%     6%  1.00x  ONLINE  -
mypool  984M  43.7M   940M         -         -     0%     4%  1.00x  ONLINE  -

zfs send 将名为 backup1 的快照中的所有数据传输到了名为 backup 的池。要自动创建并发送这些快照,可以使用 cron(8) 任务。

与存储为归档文件不同,ZFS 可以将它们接收为活动文件系统,从而允许直接访问备份数据。要访问这些流中包含的实际数据,可以使用 zfs receive 将流转换回文件和目录。以下示例将 zfs send 和 zfs receive 结合起来,使用管道将数据从一个池复制到另一个池。在传输完成后,直接在接收池上使用数据。只能将数据集复制到一个空的数据集。

# zfs snapshot mypool@replica1
# zfs send -v mypool@replica1 | zfs receive backup/mypool
send from @ to mypool@replica1 estimated size is 50.1M
total estimated size is 50.1M
TIME        SENT   SNAPSHOT

# zpool list
NAME    SIZE  ALLOC   FREE   CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
backup  960M  63.7M   896M         -         -     0%     6%  1.00x  ONLINE  -
mypool  984M  43.7M   940M         -         -     0%     4%  1.00x  ONLINE  -

22.4.7.1. 增量备份

zfs send 还可以确定两个快照之间的差异,并仅发送这两者之间的差异。这节省了磁盘空间和传输时间。例如:

# zfs snapshot mypool@replica2
# zfs list -t snapshot
NAME                    USED  AVAIL  REFER  MOUNTPOINT
mypool@replica1         5.72M      -  43.6M  -
mypool@replica2             0      -  44.1M  -
# zpool list
NAME    SIZE  ALLOC   FREE   CKPOINT  EXPANDSZ   FRAG   CAP  DEDUP  HEALTH  ALTROOT
backup  960M  61.7M   898M         -         -     0%    6%  1.00x  ONLINE  -
mypool  960M  50.2M   910M         -         -     0%    5%  1.00x  ONLINE  -

创建第二个名为 replica2 的快照。这个第二个快照包含自上一个快照 replica1 以来对文件系统所做的更改。使用 zfs send -i 并指定这两个快照对,会生成一个增量复制流,其中仅包含更改的数据。如果初始快照已经存在于接收端,则此操作成功。

# zfs send -v -i mypool@replica1 mypool@replica2 | zfs receive /backup/mypool
send from @replica1 to mypool@replica2 estimated size is 5.02M
total estimated size is 5.02M
TIME        SENT   SNAPSHOT

# zpool list
NAME    SIZE  ALLOC   FREE   CKPOINT  EXPANDSZ   FRAG  CAP  DEDUP  HEALTH  ALTROOT
backup  960M  80.8M   879M         -         -     0%   8%  1.00x  ONLINE  -
mypool  960M  50.2M   910M         -         -     0%   5%  1.00x  ONLINE  -

# zfs list
NAME                         USED  AVAIL  REFER  MOUNTPOINT
backup                      55.4M   240G   152K  /backup
backup/mypool               55.3M   240G  55.2M  /backup/mypool
mypool                      55.6M  11.6G  55.0M  /mypool

# zfs list -t snapshot
NAME                                         USED  AVAIL  REFER  MOUNTPOINT
backup/mypool@replica1                       104K      -  50.2M  -
backup/mypool@replica2                          0      -  55.2M  -
mypool@replica1                             29.9K      -  50.0M  -
mypool@replica2                                 0      -  55.0M  -

增量流仅复制了更改的数据,而不是整个 replica1。仅发送差异使传输时间大大缩短,并通过不每次复制整个池来节省磁盘空间。在通过慢速网络或按传输字节收费的网络进行复制时,这非常有用。

现在,一个新的文件系统 backup/mypool 可用了,其中包含 mypool 池的数据和文件。指定 -p 选项将复制数据集的属性,包括压缩设置、配额和挂载点。指定 -R 选项将复制数据集的所有子数据集及其属性。可以自动化发送和接收过程,以便在第二个池上创建定期备份。

22.4.7.2. 通过 SSH 发送加密备份

通过网络发送流数据是保持远程备份的一个好方法,但它有一个缺点:通过网络链路发送的数据没有加密,这使得任何人都可以拦截并将流数据转回原始数据,而不需要发送用户的授权。这在通过互联网向远程主机发送数据时是不可取的。为确保数据的安全传输,可以使用 SSH 对发送的数据进行加密。由于 ZFS 要求将流从标准输出重定向,因此可以通过 SSH 将其轻松地传输。为了确保文件系统的内容在传输过程中和在远程系统上都保持加密,考虑使用 PEFS。

首先更改一些设置并采取安全预防措施。以下描述了执行 zfs send 操作所需的步骤;有关 SSH 的更多信息,请参见 OpenSSH。

更改配置如下:

  • 在发送和接收主机之间使用 SSH 密钥进行无密码 SSH 访问

  • ZFS 需要 root 用户的权限来发送和接收流。这要求以 root 身份登录到接收系统。

  • 出于安全原因,默认情况下禁止 root 登录。

  • 使用 ZFS 授权 系统来允许每个系统上的非 root 用户执行相应的发送和接收操作。在发送系统上:

# zfs allow -u someuser send,snapshot mypool
  • 要挂载池,非特权用户必须拥有该目录,而且常规用户需要有挂载文件系统的权限。

在接收系统上:

# sysctl vfs.usermount=1
vfs.usermount: 0 -> 1
# echo vfs.usermount=1 >> /etc/sysctl.conf
# zfs create recvpool/backup
# zfs allow -u someuser create,mount,receive recvpool/backup
# chown someuser /recvpool/backup

现在,非特权用户可以接收和挂载数据集,并将 home 数据集复制到远程系统:

% zfs snapshot -r mypool/home@monday
% zfs send -R mypool/home@monday | ssh someuser@backuphost zfs recv -dvu recvpool/backup

首先创建名为 monday 的递归快照,针对文件系统数据集 home 在池 mypool 上。然后 zfs send -R 会将数据集、所有子数据集、快照、克隆以及设置包含在流中。将输出通过 SSH 管道传输到远程主机 backuphost 上等待的 zfs receive。使用 IP 地址或完全限定的域名是一种好的做法。接收机器将数据写入 recvpool 池上的 backup 数据集。添加 -d 到 zfs recv 会覆盖接收方池的名称为快照的名称。-u 会导致文件系统在接收方不挂载。使用 -v 可以显示更多关于传输的详细信息,包括传输的时间和传输的数据量。

22.4.8. 数据集、用户和组配额

使用 数据集配额 来限制特定数据集消耗的空间。 引用配额 的工作方式与数据集配额相似,但它计算的是数据集本身使用的空间,排除快照和子数据集。同样,可以使用 用户 和 组 配额来防止用户或组使用完池或数据集中的所有空间。

以下示例假设用户已经存在于系统中。在将用户添加到系统之前,确保先创建他们的家目录数据集并将 mountpoint 设置为 /home/bob。然后,创建用户并使家目录指向数据集的 mountpoint 位置。这将正确设置拥有者和组权限,而不会遮蔽可能存在的任何先前的家目录路径。

要对 storage/home/bob 强制实施 10 GB 的数据集配额:

# zfs set quota=10G storage/home/bob

要对 storage/home/bob 强制实施 10 GB 的引用配额:

# zfs set refquota=10G storage/home/bob

要删除 storage/home/bob 的 10 GB 配额:

# zfs set quota=none storage/home/bob

一般格式为 userquota@user=size,且用户的名称可以是以下任一格式:

  • POSIX 兼容的名称,如 joe。

  • POSIX 数字 ID,如 789。

  • SID 名称,如 joe.bloggs@example.com。

  • SID 数字 ID,如 S-1-123-456-789。

例如,要为名为 joe 的用户强制实施 50 GB 的用户配额:

# zfs set userquota@joe=50G

要删除任何配额:

# zfs set userquota@joe=none

注意

用户配额属性不会通过 zfs get all 显示。非 root 用户无法看到其他用户的配额,除非授予 userquota 特权。具有此特权的用户可以查看并设置所有人的配额。

设置组配额的一般格式为:groupquota@组=大小。

要将组 firstgroup 的配额设置为 50 GB,请使用:

# zfs set groupquota@firstgroup=50G

要删除组 firstgroup 的配额,或者确保没有设置配额,请使用:

# zfs set groupquota@firstgroup=none

与用户配额属性类似,非 root 用户可以查看其所属组的配额。具有 groupquota 特权的用户或 root 可以查看并设置所有组的配额。

要显示每个用户在文件系统或快照中使用的空间以及任何配额,请使用 zfs userspace。有关组信息,请使用 zfs groupspace。有关支持的选项或如何单独显示特定选项的更多信息,请参见 zfs(1)。

特权用户和 root 可以列出 storage/home/bob 的配额,方法是:

# zfs get quota storage/home/bob

22.4.9. 保留空间

保留空间 保证数据集始终有可用空间。保留的空间将不会分配给任何其他数据集。这个有用的功能确保了重要的数据集或日志文件有足够的空间。

reservation 属性的一般格式为 reservation=大小,因此,要对 storage/home/bob 设置 10 GB 的保留空间,请使用:

# zfs set reservation=10G storage/home/bob

要清除所有保留空间:

# zfs set reservation=none storage/home/bob

对于设置 引用保留空间 的 refreservation 属性,适用相同的原则,格式为 refreservation=size。

此命令显示了 storage/home/bob 上存在的任何保留空间或引用保留空间:

# zfs get reservation storage/home/bob
# zfs get refreservation storage/home/bob

22.4.10. 压缩

ZFS 提供透明压缩。在块级别压缩写入的数据可以节省空间,并且还提高了磁盘吞吐量。如果数据压缩率为 25%,压缩后的数据写入磁盘的速度与未压缩版本相同,结果是有效写入速度提高了 125%。压缩也可以是 去重 的一个很好的替代方案,因为它不需要额外的内存。

ZFS 提供了不同的压缩算法,每种算法都有不同的权衡。ZFS v5000 引入了 LZ4 压缩,它能在不牺牲其他算法的性能的情况下压缩整个池。LZ4 的最大优势是 提前中止 特性。如果 LZ4 在数据的头部部分没有达到至少 12.5% 的压缩率,ZFS 会将该块数据未压缩地写入,以避免浪费 CPU 周期在已压缩或无法压缩的数据上进行压缩。有关 ZFS 中不同压缩算法的详细信息,请参见术语部分中的 压缩 条目。

管理员可以通过数据集属性查看压缩效果。

# zfs get used,compressratio,compression,logicalused mypool/compressed_dataset
NAME        PROPERTY          VALUE     SOURCE
mypool/compressed_dataset  used              449G      -
mypool/compressed_dataset  compressratio     1.11x     -
mypool/compressed_dataset  compression       lz4       local
mypool/compressed_dataset  logicalused       496G      -

该数据集使用了 449 GB 空间(used 属性)。如果没有压缩,它将占用 496 GB 空间(logicalused 属性)。这得到了 1.11:1 的压缩比。

压缩与 用户配额 结合时可能会产生意想不到的副作用。用户配额限制的是用户在数据集上消耗的实际空间 压缩后 的空间。如果用户有 10 GB 的配额,并写入 10 GB 可压缩的数据,他们仍然可以存储更多数据。如果他们稍后更新某个文件,比如一个数据库,使用更多或更少可压缩的数据,他们可用的空间会发生变化。这可能导致一个奇怪的情况,即用户并没有增加实际的数据量(logicalused 属性),但由于压缩的变化,他们已经达到了配额限制。

压缩与备份的交互也可能会有类似的意外效果。配额通常用于限制数据存储,以确保有足够的备份空间可用。由于配额不考虑压缩,ZFS 可能会写入比未压缩备份更大的数据。

22.4.11. Zstandard 压缩

OpenZFS 2.0 增加了一种新的压缩算法。Zstandard(Zstd)提供比默认的 LZ4 更高的压缩比,同时比替代算法 gzip 提供更高的速度。OpenZFS 2.0 从 FreeBSD 12.1-RELEASE 开始通过 sysutils/openzfs 提供,并从 FreeBSD 13.0-RELEASE 起 OpenZFS 2.0 成为了默认选项。

Zstd 提供了多种压缩级别,允许对性能和压缩比进行细粒度的控制。Zstd 的一个主要优势是解压缩速度与压缩级别无关。对于那些只写一次但频繁读取的数据,Zstd 允许使用最高的压缩级别,而不会带来读取性能的惩罚。

即使在频繁更新数据的情况下,启用压缩通常也能提供更高的性能。最大优势之一来自于压缩 ARC 特性。ZFS 的自适应替换缓存(ARC)将数据的压缩版本缓存到内存中,每次解压缩时使用。这使得相同的内存容量可以存储更多的数据和元数据,从而提高缓存命中率。

ZFS 提供了 19 个 Zstd 压缩级别,每个级别都提供逐渐增加的空间节省,但会导致更慢的压缩。默认级别为 zstd-3,它提供比 LZ4 更高的压缩比,同时不会慢得太多。级别 10 以上需要大量内存来压缩每个块,因此系统内存小于 16 GB 的系统不应使用它们。ZFS 还使用了一些 Zstd_fast_ 级别,它们速度更快,但支持的压缩比更低。ZFS 支持 zstd-fast-1 到 zstd-fast-10,zstd-fast-20 到 zstd-fast-100(以 10 为增量),以及 zstd-fast-500 和 zstd-fast-1000,这些提供的压缩比最小,但性能极高。

如果 ZFS 无法为一个块分配所需的内存来进行 Zstd 压缩,它将回退到将该块存储为未压缩。除非在内存受限的系统上使用 Zstd 的最高级别,否则这种情况不太可能发生。ZFS 会计算从加载 ZFS 模块以来,发生这种情况的次数,结果可以通过 kstat.zfs.misc.zstd.compress_alloc_fail 查看。

22.4.12. 去重

启用去重后,去重 使用每个块的校验和来检测重复的块。当一个新块是现有块的重复时,ZFS 会写入一个新的引用到现有数据,而不是写入整个重复块。如果数据包含大量重复的文件或重复的信息,则可能节省大量空间。警告:去重需要大量内存,启用压缩则可以在没有额外成本的情况下提供大部分的空间节省。

要启用去重,请在目标池上设置 dedup 属性:

# zfs set dedup=on pool

去重仅影响写入池的新增数据。仅仅启用此选项并不会去重已经写入池中的数据。一个新启用去重属性的池将像下面这个例子:

# zpool list
NAME  SIZE ALLOC  FREE   CKPOINT  EXPANDSZ   FRAG   CAP   DEDUP   HEALTH   ALTROOT
pool 2.84G 2.19M 2.83G         -         -     0%    0%   1.00x   ONLINE   -

DEDUP 列显示了池的实际去重率。值为 1.00x 表示数据尚未去重。下一个例子将一些系统二进制文件复制三次到不同的目录中,以观察去重效果:

# for d in dir1 dir2 dir3; do
> mkdir $d && cp -R /usr/bin $d &
> done

要观察冗余数据的去重效果,可以使用:

# zpool list
NAME SIZE  ALLOC  FREE   CKPOINT  EXPANDSZ   FRAG  CAP   DEDUP   HEALTH   ALTROOT
pool 2.84G 20.9M 2.82G         -         -     0%   0%   3.00x   ONLINE   -

DEDUP 列显示了 3.00x 的去重系数。检测并去重数据副本只使用了三分之一的空间。节省空间的潜力巨大,但需要足够的内存来跟踪去重的块。

当池中的数据没有冗余时,去重未必总是有益的。ZFS 可以通过模拟去重来显示潜在的空间节省:

# zdb -S pool
Simulated DDT histogram:

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
     1    2.58M    289G    264G    264G    2.58M    289G    264G    264G
     2     206K   12.6G   10.4G   10.4G     430K   26.4G   21.6G   21.6G
     4    37.6K    692M    276M    276M     170K   3.04G   1.26G   1.26G
     8    2.18K   45.2M   19.4M   19.4M    20.0K    425M    176M    176M
    16      174   2.83M   1.20M   1.20M    3.33K   48.4M   20.4M   20.4M
    32       40   2.17M    222K    222K    1.70K   97.2M   9.91M   9.91M
    64        9     56K   10.5K   10.5K      865   4.96M    948K    948K
   128        2   9.50K      2K      2K      419   2.11M    438K    438K
   256        5   61.5K     12K     12K    1.90K   23.0M   4.47M   4.47M
    1K        2      1K      1K      1K    2.98K   1.49M   1.49M   1.49M
 Total    2.82M    303G    275G    275G    3.20M    319G    287G    287G

dedup = 1.05, compress = 1.11, copies = 1.00, dedup * compress / copies = 1.16

在 zdb -S 完成分析后,它会显示启用去重可能带来的空间减少比例。在这个例子中,1.16 是一个较低的空间节省比例,主要由压缩提供。如果在此池上启用去重,将不会节省任何空间,并且启用去重所需的内存量不值得。通过使用公式 ratio = dedup * compress / copies,系统管理员可以计划存储分配,决定工作负载是否包含足够的重复块来证明内存需求。如果数据具有良好的可压缩性,空间节省可能会很大。最佳实践是首先启用压缩,因为压缩也提供了显著的性能提升。在去重可以提供显著节省且有足够内存支持 DDT 的情况下启用去重。

22.4.13. ZFS 和 Jail

使用 zfs jail 和相应的 jailed 属性将 ZFS 数据集分配给 Jail。zfs jail jailid 将数据集附加到指定的 jail,zfs unjail 将其分离。要在 jail 内部控制数据集,请设置 jailed 属性。ZFS 禁止在主机上挂载被 jail 限制的数据集,因为它可能包含会危及主机安全的挂载点。

上一页22.3.zpool 管理下一页22.5.委托管理

最后更新于1个月前

这有帮助吗?