如何在 ubuntu 18.04 上缩小 zfs 卷?

Chr*_*per 6 zfs 18.04

鉴于在单个磁盘上使用 zfs 进行安装,如何缩小 zfs 分区/池以便我可以向磁盘添加新分区?我见过的其他说明表明在池上设置 volsize 属性,但这样做会产生以下错误:cannot set property for 'rpool': 'volsize' does not apply to datasets of this type

$ zpool list
NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
bpool  1.88G   196M  1.68G        -         -      -    10%  1.00x    ONLINE  -
rpool   228G  10.9G   217G        -         -     2%     4%  1.00x    ONLINE  -
Run Code Online (Sandbox Code Playgroud)

小智 5

事实上,是可以做到的。因为如果空间允许,可以从池中删除顶级 vdev。所以诀窍是:

1. add a temp disk/file vdev to the pool with smaller size, but is enough to hold all existing data (including snapshots etc)
2. remove the old vdev
3. possibly re-partition old vdev to smaller size, or replace with a smaller disk
4. add it back 
5. remove the temp disk.

Run Code Online (Sandbox Code Playgroud)

所有文件应保持完整。

为了说明步骤:

  1. 分配文件
# fallocate -l 3G 3G_1.img
# fallocate -l 3G 3G_2.img
# fallocate -l 2G 2G_1.img
# fallocate -l 2G 2G_2.img
Run Code Online (Sandbox Code Playgroud)
  1. 用2个带镜像的3G文件创建zfs。(我的目录是/var/snap/lxd/common/lxd/disks)
# zpool create test3g mirror /var/snap/lxd/common/lxd/disks/3G_1.img /var/snap/lxd/common/lxd/disks/3G_2.img
# zpool status test3g
  pool: test3g
 state: ONLINE
  scan: none requested
config:

    NAME                                         STATE     READ WRITE CKSUM
    test3g                                       ONLINE       0     0     0
      mirror-0                                   ONLINE       0     0     0
        /var/snap/lxd/common/lxd/disks/3G_1.img  ONLINE       0     0     0
        /var/snap/lxd/common/lxd/disks/3G_2.img  ONLINE       0     0     0

errors: No known data errors
# zpool list test3g
NAME     SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
test3g  2.75G   111K  2.75G        -         -     0%     0%  1.00x    ONLINE  -
Run Code Online (Sandbox Code Playgroud)

您可以清楚地看到 test3g 池有 2.75G 可用,它在镜像中。

  1. 让我们尝试在里面创建虚拟文件。这是为了模拟您现有的数据。练习后您可以验证您的数据是否完好。
# echo test > /test3g/test.txt
# cat /test3g/test.txt
test
#
Run Code Online (Sandbox Code Playgroud)
  1. 现在附加另一个较小尺寸的镜子(例如2G)
# zpool add test3g mirror /var/snap/lxd/common/lxd/disks/2G_1.img /var/snap/lxd/common/lxd/disks/2G_2.img
# zpool status test3g
  pool: test3g
 state: ONLINE
  scan: none requested
config:

    NAME                                         STATE     READ WRITE CKSUM
    test3g                                       ONLINE       0     0     0
      mirror-0                                   ONLINE       0     0     0
        /var/snap/lxd/common/lxd/disks/3G_1.img  ONLINE       0     0     0
        /var/snap/lxd/common/lxd/disks/3G_2.img  ONLINE       0     0     0
      mirror-1                                   ONLINE       0     0     0
        /var/snap/lxd/common/lxd/disks/2G_1.img  ONLINE       0     0     0
        /var/snap/lxd/common/lxd/disks/2G_2.img  ONLINE       0     0     0

errors: No known data errors
# zpool list test3g
NAME     SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
test3g  4.62G   156K  4.62G        -         -     0%     0%  1.00x    ONLINE  -
Run Code Online (Sandbox Code Playgroud)

现在我们有一个可用的 4.62GB 的条纹镜像。

  1. 让我们删除之前的 3G 部分。
# zpool remove test3g mirror-0
# zpool status
  pool: default
 state: ONLINE
  scan: scrub repaired 0B in 0 days 00:06:45 with 0 errors on Fri May 21 15:20:30 2021
config:

    NAME                                            STATE     READ WRITE CKSUM
    default                                         ONLINE       0     0     0
      mirror-0                                      ONLINE       0     0     0
        /opt/lxc_image/default.img                  ONLINE       0     0     0
        /var/snap/lxd/common/lxd/disks/default.img  ONLINE       0     0     0

errors: No known data errors

  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 0 days 00:00:10 with 0 errors on Tue May 18 19:42:56 2021
config:

    NAME                                         STATE     READ WRITE CKSUM
    tank                                         ONLINE       0     0     0
      mirror-0                                   ONLINE       0     0     0
        /var/snap/lxd/common/lxd/disks/tank.img  ONLINE       0     0     0
        /nfs-dual/zfs-images/tank.img            ONLINE       0     0     0

errors: No known data errors

  pool: test3g
 state: ONLINE
  scan: none requested
remove: Removal of vdev 0 copied 102K in 0h0m, completed on Fri May 21 15:33:19 2021
    72 memory used for removed device mappings
config:

    NAME                                         STATE     READ WRITE CKSUM
    test3g                                       ONLINE       0     0     0
      mirror-1                                   ONLINE       0     0     0
        /var/snap/lxd/common/lxd/disks/2G_1.img  ONLINE       0     0     0
        /var/snap/lxd/common/lxd/disks/2G_2.img  ONLINE       0     0     0

errors: No known data errors
# zpool list test3g
NAME     SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
test3g  1.88G   142K  1.87G        -         -     0%     0%  1.00x    ONLINE  -
Run Code Online (Sandbox Code Playgroud)

空间降至1.87G。请注意,这可能需要很长时间,具体取决于您的数据大小,但它会正常完成。检查上面的消息:

Removal of vdev 0 copied 102K in 0h0m, completed on Fri May 21 15:33:19 2021
Run Code Online (Sandbox Code Playgroud)

您从技术上将 zpool 大小从 3G 减少到 2G,无需停机,也不会丢失数据。

  1. 让我们验证一下数据是否仍然存在
# cat /test3g/test.txt
test
#
Run Code Online (Sandbox Code Playgroud)

是的当然。

请注意,只有最新版本的 zfs 支持此功能。您的里程可能会有所不同。

谢谢最好的士林


KK *_*tel 2

将磁盘添加到 zfs 池后,默认情况下 zfs 会分配整个磁盘以供使用,并使用 EFI 标签格式化磁盘以包含单个大片。这是推荐的方式。

如果您分配了整个磁盘,则无法缩小卷的大小。从技术上讲,您可以通过 gparted 或其他工具强制它收缩,但这会导致 zfs 池出现问题,并且您将丢失数据,因此根本不建议这样做。

您可以减小特定 zfs 池的大小并从可用空间创建新池。释放一些空间的唯一方法是您可以使磁盘脱机(我希望您在 zfs 池中有多个磁盘),重新格式化它并为您所需的分区使用一些空间,并将剩余空间分配给 zfs 分区c150d0。当您将磁盘添加回 zfs 池时,您需要添加 zfs 分区以供使用。这不是推荐的方法,但应视为解决方法。这样做的风险由您自己承担。