ZFS 是由 Sun Microsystems 设计的组合文件系统和逻辑卷管理器。从 Proxmox VE 3.4 开始,ZFS 文件系统包含在 Linux 内核中,作为可选文件系统引入,同时也可选择作为根文件系统,无需用户自行手动编译 ZFS 模块。
通过使用 ZFS,可以通过低预算硬件实现最大的企业功能,还可以通过利用 SSD 缓存甚至仅设置 SSD 来实现高性能系统。ZFS 可以通过适度的 CPU 和内存负载以及简单的管理来取代成本密集的硬件 RAID 卡,通用 ZFS 的优势为:
- 可使用图形界面及命令行轻松配置和管理
- 高可靠性
- 防止数据损坏
- 文件系统级别的数据压缩
- 快照
- 写入复制克隆(COW)
- 各种 RAID 级别:RAID0、RAID1、RAID10、RAIDZ-1、RAIDZ-2 和 RAIDZ-3
- 可以使用 SSD 作为缓存
- 出错时自愈修复
- 持续完整性检查
- 专为高存储容量而设计
- 网络异步复制
- 开源
- 加密
- …
硬件 #
ZFS 严重依赖内存,因此您至少需要 8GB 才能启动。在实践中,尽可能多地使用硬件/预算。为防止数据损坏,我们建议使用高质量的 ECC RAM。
如果您使用专用缓存和/或日志磁盘,则应使用企业级 SSD(例如 Intel SSD DC S3700 系列)。这可以显着提高整体性能。
不要在具有自己的缓存管理的硬件 RAID 控制器上使用 ZFS。ZFS 需要直接与磁盘通信。在直通模式下的 HBA 适配器或类似 LSI 控制器的东西更合适。 |
如果您正在尝试在 VM(嵌套虚拟化)中安装 Proxmox VE,请不要将virtio用于该 VM 的磁盘,因为 ZFS 不支持它们。请改用 IDE 或 SCSI(也适用于virtio SCSI 控制器类型)。
作为根文件系统安装 #
当您使用 Proxmox VE 安装程序进行安装时,您可以选择 ZFS 作为根文件系统。安装时需要选择RAID类型:
RAID0 | 也称为“条带化”。该卷的容量是所有磁盘容量的总和。但是 RAID0 并没有添加任何冗余,因此单个驱动器的故障会导致该卷无法使用。 |
RAID1 | 也称为“镜像”。数据以相同方式写入所有磁盘。此模式至少需要 2 个大小相同的磁盘。产生的容量是单个磁盘的容量。 |
RAID10 | RAID0 和 RAID1 的组合。至少需要 4 个磁盘。 |
RAIDZ-1 | RAID-5 的一种变体,单奇偶校验。至少需要 3 个磁盘。 |
RAIDZ-2 | RAID-5 的一种变体,双奇偶校验。至少需要 4 个磁盘。 |
RAIDZ-3 | RAID-5 的一种变体,三重奇偶校验。至少需要 5 个磁盘。 |
安装程序自动对磁盘进行分区,创建一个名为rpool的 ZFS 池,并将根文件系统安装在 ZFS 子卷 rpool/ROOT/pve-1上。
创建另一个名为rpool/data的子卷来存储 VM 映像。为了将其与 Proxmox VE 工具一起使用,安装程序在/etc/pve/storage.cfg中创建以下配置条目:
zfspool: local-zfs
pool rpool/data
sparse
content images,rootdir
安装后,您可以使用zpool命令查看 ZFS 池状态 :
# zpool status
pool: rpool
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
rpool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
sda2 ONLINE 0 0 0
sdb2 ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
errors: No known data errors
zfs命令用于配置和管理 ZFS 文件系统。以下命令列出安装后的所有文件系统:
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
rpool 4.94G 7.68T 96K /rpool
rpool/ROOT 702M 7.68T 96K /rpool/ROOT
rpool/ROOT/pve-1 702M 7.68T 702M /
rpool/data 96K 7.68T 96K /rpool/data
rpool/swap 4.25G 7.69T 64K -
RAID 级别注意事项 #
择 ZFS 池的布局时需要考虑几个因素。ZFS 池的基本构建块是虚拟设备或 vdev。池中的所有 vdev 均平等使用,并且数据在它们之间进行条带化 (RAID0)。查看zpool(8)手册页以获取有关 vdev 的更多详细信息。
性能
每种vdev类型都有不同的性能,通常考虑的两个性能参数分别是 IOPS(每秒输入/输出操作数)和可以写入或读取数据的带宽。
在写入数据时,镜像vdev (RAID1) 在两个参数方面的性能类似于单个磁盘。读取数据时,将表现得像镜像中的磁盘数的性能。
一个常见的情况是有 4 个磁盘。将其设置为 2 个镜像 vdev (RAID10) 时,池将在 IOPS 和带宽方面具有两个单磁盘的写入性能。对于读取操作,它将类似于 4 个单磁盘的读取性能。
就具有大带宽的 IOPS 而言,任何冗余级别的RAIDZ都将近似地表现为单个磁盘。多少带宽取决于 RAIDZ vdev 的大小和冗余级别。
对于正在运行的 VM,IOPS 在大多数情况下是更重要的指标。
大小、空间使用和冗余
虽然由镜像vdev 组成的池有最佳性能特征,但可用空间将是裸磁盘容量的 50%。如果镜像 vdev 包含超过 2 个磁盘,则更少,例如在 3 路镜像中。每个镜像至少需要一个健康磁盘才能使池保持正常运行。
N个磁盘的RAIDZ类型vdev的可用空间大致为NP,其中P为RAIDZ级别。RAIDZ 级别表示有多少任意磁盘可以在不丢失数据的情况下发生故障。一个特殊情况是具有 RAIDZ2 的 4 个磁盘池。在这种情况下,通常最好使用 2 个镜像 vdev 以获得更好的性能,因为可用空间相同。
使用任何 RAIDZ 级别时的另一个重要因素是用于 VM 磁盘的 ZVOL 数据集的行为方式。对于每个数据块,池需要奇偶校验数据,该数据至少是池的ashift 值定义的最小块大小的大小。ashift 为 12 时,池的块大小为 4k。ZVOL 的默认块大小为 8k。因此,在 RAIDZ2 中,写入的每个 8k 块将导致写入两个额外的 4k 奇偶校验块,8k + 4k + 4k = 16k。这当然是一种简化的方法,实际情况会略有不同,元数据、压缩等在本示例中未考虑在内。
检查 ZVOL 的以下属性时可以观察到此行为:
- volsize
- refreservation(如果池不是精简配置)
- used(如果池是精简配置且不存在快照)
# zfs get volsize,refreservation,used <pool>/vm-<vmid>-disk-X
volsize是呈现给 VM 的磁盘大小,而 refreservation显示池上的保留空间,其中包括奇偶校验数据所需的预期空间。如果池是精简配置的,则 refreservation将设置为 0。查看另一种方法是比较 VM 中的已用磁盘空间和used属性。请注意,快照会使该值失真。
有几个选项可以应对空间使用量的增加:
- 增加volblocksize以提高数据奇偶校验比
- 使用镜像vdevs 而不是RAIDZ
- 使用ashift=9(块大小为 512 字节)
volblocksize属性只能在创建 ZVOL 时设置。可以在存储配置中更改默认值。执行此操作时,需要根据具体的使用情况对客户机进行相应调整,如果只是从 ZFS 层移动到客户机,则会出现写入放大问题。
在创建池时使用ashift=9可能会导致性能下降,具体取决于下面的磁盘,并且以后无法更改。
镜像 vdev(RAID1、RAID10)对 VM 工作负载具有良好的行为。使用它们,除非您的环境具有可接受的 RAIDZ 性能特征的特定需求和特征
引导加载程序 #
Proxmox VE 使用proxmox-boot-tool来管理引导加载程序配置。有关详细信息,请参阅Proxmox VE 主机引导加载程序一章。
ZFS 管理 #
本节为您提供一些常见任务的使用示例。ZFS 本身确实很强大,并且提供了很多选项。管理 ZFS 的主要命令是zfs和zpool。这两个命令都带有很好的手册页,可以通过以下方式阅读:
# man zpool
# man zfs
创建一个新的 zpool #
要创建新池,至少需要一个磁盘。ashift应该与底层磁盘具有相同的扇区大小(ashift 的 2次方)或更大。
# zpool create -f -o ashift=12 <pool> <device>
要激活压缩(请参阅ZFS 中的压缩部分):
# zfs set compression=lz4 <pool>
使用 RAID-0 创建一个新池
至少 需要1 个磁盘
# zpool create -f -o ashift=12 <pool> <device1> <device2>
使用 RAID-1 创建新池
最少 2 个磁盘
# zpool create -f -o ashift=12 <pool> mirror <device1> <device2>
使用 RAID-10 创建新池
最少 4 个磁盘
# zpool create -f -o ashift=12 <pool> mirror <device1> <device2> mirror <device3> <device4>
使用 RAIDZ-1 创建新池
最少 3 个磁盘
# zpool create -f -o ashift=12 <pool> raidz1 <device1> <device2> <device3>
使用 RAIDZ-2 创建新池
最少 4 个磁盘
# zpool create -f -o ashift=12 <pool> raidz2 <device1> <device2> <device3> <device4>
使用缓存创建新池 (L2ARC)
可以使用专用的缓存磁盘分区来提高性能(使用 SSD)。
作为<device>可以使用更多设备,如“使用 RAID* 创建新池”中所示。
# zpool create -f -o ashift=12 <pool> <device> cache <cache_device>
使用日志 (ZIL) 创建一个新池
可以使用专用的缓存磁盘分区来提高性能(SSD)。
作为<device>可以使用更多设备,如“使用 RAID* 创建新池”中所示。
# zpool create -f -o ashift=12 <pool> <device> log <log_device>
将缓存和日志添加到现有池
如果您有一个没有缓存和日志的池。首先使用parted或gdisk将 SSD 分区为 2 个分区
注意 | 始终使用 GPT 分区表。 |
日志设备的最大大小应该是物理内存大小的一半左右,所以这通常很小。SSD 的其余部分可用作缓存。
# zpool add -f <pool> log <device-part1> cache <device-part2>
更换故障设备
# zpool replace -f <pool> <old device> <new device>
更改失败的可启动设备
根据 Proxmox VE 的安装方式,它使用systemd-boot或grub 通过proxmox-boot-tool
[使用 Proxmox VE 6.4 或更高版本安装的系统,使用 Proxmox VE 5.4 或更高版本安装的 EFI 系统]
或普通grub作为引导加载程序(请参阅 主机引导加载程序)。您可以通过运行检查:
# proxmox-boot-tool status
复制分区表、重新发布 GUID 和替换 ZFS 分区的第一步是相同的。为了使系统可以从新磁盘启动,需要不同的步骤,这取决于所使用的引导加载程序。
# sgdisk <healthy bootable device> -R <new device>
# sgdisk -G <new device>
# zpool replace -f <pool> <old zfs partition> <new zfs partition>
提示 | 使用 # zpool status -v 命令来监控新磁盘的重新同步过程的进度。 |
使用proxmox-boot-tool:
# proxmox-boot-tool format <new disk's ESP>
# proxmox-boot-tool init <new disk's ESP>
提示 | ESP代表 EFI 系统分区,自 5.4 版起由 Proxmox VE 安装程序设置为可引导磁盘上的分区 #2。有关详细信息,请参阅 设置新分区以用作同步 ESP。 |
用普通的 grub:
# grub-install <new disk>
提示 | 普通grub仅用于安装了 Proxmox VE 6.3 或更早版本的系统,这些系统尚未手动迁移到使用proxmox-boot-tool。 |
配置电子邮件通知 #
ZFS 带有一个事件守护程序ZED,它监视由 ZFS 内核模块生成的事件。该守护程序还可以发送有关 ZFS 事件(如池错误)的电子邮件。较新的 ZFS 包将守护进程放在单独的zfs-zed包中,默认情况下它应该已经安装在 Proxmox VE 中。
您可以使用您喜欢的编辑器通过文件/etc/zfs/zed.d/zed.rc配置守护程序。电子邮件通知所需的设置是 ZED_EMAIL_ADDR,默认设置为root。
ZED_EMAIL_ADDR="root"
请注意 Proxmox VE 将邮件转发到root到为 root 用户配置的电子邮件地址。
限制 ZFS 内存使用 #
默认情况下, ZFS 将50%的主机内存用于自适应替换缓存 ( ARC )。为 ARC 分配足够的内存对于 IO 性能至关重要,因此请谨慎减少。作为一般经验法则,分配至少2 GiB Base + 1 GiB/TiB-Storage。例如,如果您有一个具有 8 TiB可用存储空间的池,那么您应该为 ARC 使用10 GiB内存。
您可以通过直接写入zfs_arc_max模块参数来更改当前引导的 ARC 使用限制(重新引导会再次重置此更改):
echo "$[10 * 1024*1024*1024]" >/sys/module/zfs/parameters/zfs_arc_max
要永久更改ARC 限制,请将以下行添加到 /etc/modprobe.d/zfs.conf:
options zfs zfs_arc_max=8589934592
此示例设置将使用限制为 8 GiB ( 8 * 2 30 )。
如果您想要的zfs_arc_max值小于或等于 zfs_arc_min(默认为系统内存的 1/32),则zfs_arc_max将被忽略,除非您还将zfs_arc_min设置为最多zfs_arc_max – 1。 |
echo "$[8 * 1024*1024*1024 - 1]" >/sys/module/zfs/parameters/zfs_arc_min
echo "$[8 * 1024*1024*1024]" >/sys/module/zfs/parameters/zfs_arc_max
在总内存超过 256 GiB 的系统上, 此示例设置(暂时)将使用量限制为 8 GiB ( 8 * 2 30 ),其中仅设置fs_arc_max不起作用。
重要提示 | 如果您的根文件系统是 ZFS,则每次此值更改时都必须更新 initramfs: # update-initramfs -u 您必须重新启动才能激活这些更改。 |
ZFS 上的 SWAP #
在 zvol 上创建的交换空间可能会产生一些问题,例如阻塞服务器或产生高 IO 负载,这在启动备份到外部存储时经常出现。
我们强烈建议使用足够的内存,这样您通常不会遇到内存不足的情况。如果您需要或想要添加交换,最好在物理磁盘上创建一个分区并将其用作交换设备。您可以在安装程序的高级选项中为此留出一些空间。此外,您可以降低“swappiness”值。服务器的一个好的值是 10:
# sysctl -w vm.swappiness=10
要使 swappiness 持久化,请使用您选择的编辑器打开/etc/sysctl.conf并添加以下行:
vm.swappiness = 10
价值 | 战略 |
---|---|
vm.swappiness = 0 | 内核将交换只是为了避免内存不足的情况 |
vm.swappiness = 1 | 在不完全禁用的情况下进行最小交换量。 |
vm.swappiness = 10 | 当系统中存在足够的内存时,有时建议使用此值来提高性能。 |
vm.swappiness = 60 | 默认值。 |
vm.swappiness = 100 | 内核将积极交换。 |
加密的 ZFS 数据集 #
Linux 版本 0.8.0 上的 ZFS 引入了对数据集本机加密的支持。在 Linux 版本上从以前的 ZFS 升级后,可以为每个池启用加密功能:
# zpool get feature@encryption tank
NAME PROPERTY VALUE SOURCE
tank feature@encryption disabled local
# zpool set feature@encryption=enabled
# zpool get feature@encryption tank
NAME PROPERTY VALUE SOURCE
tank feature@encryption enabled local
目前不支持使用 Grub 从具有加密数据集的池引导,并且仅有限支持在引导时自动解锁加密数据集。不支持加密的旧版本 ZFS 将无法解密存储的数据。 |
建议 | 建议在启动后手动解锁存储数据集,或者编写自定义单元将启动时解锁所需的密钥材料传递给zfs load-key。 |
警告 | 在启用生产数据加密之前建立并测试备份程序。如果相关的密钥材料/密码/密钥文件丢失,则无法再访问加密数据。 |
创建 datasets/zvols 时需要设置加密,默认继承到子数据集。例如,要创建加密数据集 tank/encrypted_data并将其配置为 Proxmox VE 中的存储,请运行以下命令:
# zfs create -o encryption=on -o keyformat=passphrase tank/encrypted_data
Enter passphrase:
Re-enter passphrase:
# pvesm add zfspool encrypted_zfs -pool tank/encrypted_data
在此存储上创建的所有来宾卷/磁盘都将使用父数据集的共享密钥材料进行加密。
要实际使用存储,需要加载关联的密钥材料并挂载数据集。这可以通过以下步骤一步完成:
# zfs mount -l tank/encrypted_data
Enter passphrase for 'tank/encrypted_data':
也可以使用(随机)密钥文件,而不是通过设置keylocation和keyformat属性来提示输入密码,无论是在创建时还是在现有数据集上使用zfs change-key :
# dd if=/dev/urandom of=/path/to/keyfile bs=32 count=1
# zfs change-key -o keyformat=raw -o keylocation=file:///path/to/keyfile tank/encrypted_data
使用密钥文件时,需要特别注意保护密钥文件免受未经授权的访问或意外丢失。没有密钥文件,就无法访问明文数据! |
在加密数据集下创建的来宾卷将相应地设置其 加密根属性。密钥材料只需为每个加密根加载一次,即可供其下的所有加密数据集使用。
有关更多详细信息和高级用法,请参阅encryptionroot、encryption、keylocation、keyformat和 keystatus属性、zfs load-key、zfs unload-key和zfs change-key命令以及来自man zfs的Encryption部分。
ZFS 中的压缩 #
在数据集上启用压缩后,ZFS 会尝试在写入所有新 块之前对其进行压缩,并在读取时对其进行解压缩。已经存在的数据不会被追溯压缩。
您可以通过以下方式启用压缩:
# zfs set compression=<algorithm> <dataset>
我们推荐使用lz4算法,因为它增加了非常少的 CPU 开销。其他算法,如lzjb和gzip-N,其中N是从1(最快)到9(最佳压缩比)的整数,也可用。根据算法和数据的可压缩程度,启用压缩甚至可以提高 I/O 性能。
您可以随时通过以下方式禁用压缩:
# zfs set compression=off <数据集>
# zfs set compression=off <dataset>
同样,只有新块会受到此更改的影响。
ZFS 特殊设备 #
从 0.8.0 版开始,ZFS 支持特殊设备。池中的特殊设备用于存储元数据、重复数据删除表和可选的小文件块。
一种特殊的设备可以提高由具有大量元数据更改的慢速旋转硬盘组成的池的速度。例如,涉及创建、更新或删除大量文件的工作负载将受益于特殊设备的存在。ZFS 数据集还可以配置为将整个小文件存储在特殊设备上,这可以进一步提高性能。对特殊设备使用快速 SSD 。
特殊设备的冗余应该与池中的一个相匹配,因为特殊设备是整个池的故障点。 |
无法撤消向池中添加特殊设备! |
创建具有特殊设备和 RAID-1 的池:
# zpool create -f -o ashift=12 <pool> mirror <device1> <device2> special mirror <device3> <device4>
使用 RAID-1 将特殊设备添加到现有池:
# zpool add <pool> special mirror <device1> <device2>
ZFS 数据集公开了special_small_blocks=<size>属性。size可以是 0以禁用在特殊设备上存储小文件块,或者是512B到128K范围内的 2 的幂。设置属性后,小于size的新文件块将分配到特殊设备上。
如果special_small_blocks的值大于或等于数据集的记录大小(默认128K),所有数据都将写入特殊设备,所以要小心! |
在池上设置special_small_blocks属性将更改所有子 ZFS 数据集的该属性的默认值(例如,池中的所有容器都将选择小文件块)。选择加入池范围内小于 4K 块的所有文件:
# zfs set special_small_blocks=4K <pool>
为单个数据集选择小文件块:
# zfs set special_small_blocks=4K <pool>/<filesystem>
选择退出单个数据集的小文件块:
# zfs set special_small_blocks=0 <pool>/<filesystem>
ZFS 池功能 #
ZFS 中磁盘格式的更改仅在主要版本更改之间进行,并通过features指定。zpool-features(5)联机帮助页中详细记录了所有功能以及一般机制。
由于启用新功能可能会使旧版本的 ZFS 无法导入池,因此管理员需要通过 在池上运行zpool upgrade主动完成此操作(请参阅zpool-upgrade(8)联机帮助页)。
除非您需要使用其中一项新功能,否则启用它们没有任何好处。
事实上,启用新功能有一些缺点:
- 如果在 rpool 上启用了新功能,由于 grub 中 ZFS 的实现不兼容, 在 ZFS 上仍使用grub引导的具有 root 权限的系统将变得无法引导。
- 当使用旧内核引导时,系统将无法导入任何升级的池,该内核仍随旧 ZFS 模块一起提供。
- 引导较旧的 Proxmox VE ISO 来修复无法引导的系统同样不起作用。
如果您的系统仍然使用 grub引导,请不要升级您的 rpool ,因为这会使您的系统无法引导。这包括在 Proxmox VE 5.4 之前安装的系统,以及使用旧版 BIOS 引导引导的系统(请参阅 如何确定引导加载程序)。 |
为 ZFS 池启用新功能:
# zpool upgrade <pool>