初学者备份 ZFS 存储池

初学者备份 ZFS 存储池

我正在考虑将我的个人家庭数据移至 Debian PC 上的 ZFS,以利用 ZFS 功能,例如数据完整性和校验和、重复数据删除和快照。该盒子不仅仅是一个 NAS,所以我对将盒子专用于 FreeNAS 之类的东西不感兴趣。

在此过程中,我还在考虑如何每晚备份数据并定期将其移出现场。我当前的设置将在本文后面介绍。如果您能告诉我下面介绍的第三种备份方法的优缺点,我将不胜感激。

(1) 由于我是 ZFS 的新手并且不熟悉,因此我考虑将我的实时数据放入 ZFS 池中,但继续使用 Dirvish 将这些数据备份到非 ZFS 备份驱动器上,以保证安全。

(2) 我还了解了如何设置 cron 作业来定期拍摄快照,其频率可以与每小时拍摄一次一样,因此我开始考虑设置实时数据驱动器,每小时或每天拍摄一次快照,然后发送/接收至同样为 ZFS 格式化的备份驱动器。

(3) 最后,最近我突然意识到,我可能不需要使用 ZFS 做任何如此复杂的事情。如果我将两个驱动器设置为类似于 RAID1 的镜像 vdev 配置,然后设置每小时快照,会怎么样?这样,我似乎会有一个即时备份,并且可以避免可怕的 RAID 不是备份:

/bin/rm -Rf /*

使用 #3,如果任何一个驱动器出现故障,我都有镜像可用来继续。正如我下面提到的,我可以忍受没有 RAID 的高可用性,但在这种情况下,我似乎可以免费获得它。

我唯一担心的就是下面描述的离线异地驱动器。定期轮换一个镜像驱动器和几个星期或几个月前的备用驱动器会不会有问题?

关于我目前的设置,我目前将所有内容保存在 Ubuntu 机器上,可能是一个普通的 ext3 分区。我不再使用 RAID;我个人不需要高可用性;如果出现问题,我可以腾出时间从备份中恢复。

我每晚使用 dirvish 备份我的数据、笔记本电脑和其他有价值的东西,并保存大约两个月前的快照。

我会定期轮换备份驱动器,这样就可以将其移出现场并离线。如果我丢失了主驱动器和实时备份驱动器,至少我还有异地驱动器,即使它已经有几个星期了。

我不考虑维护驱动器阵列;我更愿意用一个驱动器来存储所有数据,用另一个驱动器来存储整个备份。这样,我可以轻松地定期轮换一个异地备份驱动器,而当前插入的备份驱动器则不会更换。

谢谢。

编辑:我在运行 Debian 的 VM 上尝试了 jlliagre 的 #2,该 VM 安装了 Linux 上的 ZFS,使用此处描述的命令:

http://www.bsdnow.tv/tutorials/zfs

我首先创建了三个文件来模拟我的三个磁盘:

# cd /mnt/sda3
# truncate -s 2G primary
# truncate -s 2G rotating_mirror1
# truncate -s 2G rotating_mirror2

如上所述,我仅使用其中一个镜像文件创建了一个镜像池:

# zpool create mypool mirror /mnt/sda3/primary /mnt/sda3/rotating_mirror1
# zfs list
NAME     USED  AVAIL  REFER  MOUNTPOINT
mypool   106K  1.95G    30K  /mypool
# zpool status -v mypool
  pool: mypool
 state: ONLINE
  scan: none requested
config:

    NAME                            STATE     READ WRITE CKSUM
    mypool                          ONLINE       0     0     0
      mirror-0                      ONLINE       0     0     0
        /mnt/sda3/primary           ONLINE       0     0     0
        /mnt/sda3/rotating_mirror1  ONLINE       0     0     0

errors: No known data errors

接下来,我尝试使用此处引用的脚本设置自动快照:

http://alblue.bandlem.com/2008/11/crontab-generated-zfs-snapshots.html

我为 root 创建了一个 crontab 文件:

# crontab -e

我从上面的链接粘贴并修改了以下内容。我不是 cron 专家,所以我想知道这其中是否存在竞争条件:

@reboot /sbin/zpool scrub mypool
@daily  /sbin/zpool scrub mypool
@hourly /sbin/zpool status mypool | /bin/egrep -q "scrub completed|none requested" && /sbin/zfs snapshot -r mypool@AutoH-`date +"\%FT\%H:\%M"`
@daily  /sbin/zfs snapshot -r mypool@AutoD-`date +"\%F"`
@weekly /sbin/zfs snapshot -r mypool@AutoW-`date +"\%Y-\%U"`
@monthly /sbin/zfs snapshot -r mypool@AutoM-`date +"\%Y-\%m"`
@yearly /sbin/zfs snapshot -r mypool@AutoY-`date +"\%Y"`
# do a spot of housecleaning - somewhat assumes the daily ones have run ..
@hourly /sbin/zpool status mypool | /bin/egrep -q "scrub completed|none requested" && /sbin/zfs list -t snapshot -o name | /bin/grep mypool@AutoH- | /usr/bin/sort -r | /usr/bin/tail -n +26 | /usr/bin/xargs -n 1 /sbin/zfs destroy -r
@daily  /sbin/zfs list -t snapshot -o name | /bin/grep mypool@AutoD- | /usr/bin/sort -r | /usr/bin/tail -n +9 | /usr/bin/xargs -n 1 /sbin/zfs destroy -r
@weekly /sbin/zfs list -t snapshot -o name | /bin/grep mypool@AutoW- | /usr/bin/sort -r | /usr/bin/tail -n +7 | /usr/bin/xargs -n 1 /sbin/zfs destroy -r
@monthly /sbin/zfs list -t snapshot -o name | /bin/grep mypool@AutoM- | /usr/bin/sort -r | /usr/bin/tail -n +14 | /usr/bin/xargs -n 1 /sbin/zfs destroy -r

我认为这不会给我带来两个月的备份,但这是一个开始。

此时,我开始使用第一个链接中的示例来创建一个文件,创建一个快照,然后修改该文件。

继续遵循 jlliagre 的建议,我想换掉 spinning_mirror1 并用 spinning_mirror2 替换。(在真实的盒子中,我希望关闭盒子的电源以移除 SATA mirror1 驱动器,并用 mirror2 驱动器替换它。)

# zpool split mypool mypool_bak /mnt/sda3/rotating_mirror1
# zpool status
  pool: mypool
 state: ONLINE
  scan: none requested
config:

    NAME                 STATE     READ WRITE CKSUM
    mypool               ONLINE       0     0     0
      /mnt/sda3/primary  ONLINE       0     0     0

errors: No known data errors

此时,我遇到了一些麻烦;我无法导入 mypool_bak,也无法对 spinning_mirror1 执行任何其他操作。我最终尝试创建 mypool_bak,发现其中没有任何内容,因此将其销毁,然后将 spinning_mirror1 重新连接到主节点。

# zpool create -f mypool_bak /mnt/sda3/rotating_mirror1
# zpool destroy mypool_bak
# zpool attach mypool /mnt/sda3/primary /mnt/sda3/rotating_mirror1 

我纯粹假设此时的 spinning_mirror1 与 primary 的任何改变都同步。

我再次尝试分裂:

# zpool split mypool mypool2 /mnt/sda3/rotating_mirror1

再次出现同样的问题,因此我重新连接:

# zpool attach -f mypool /mnt/sda3/primary /mnt/sda3/rotating_mirror1

再次尝试使用 -R 选项。看起来效果更好:

# zpool split -R /mypool2a mypool mypool2 /mnt/sda3/rotating_mirror1
# ls /mypool2a/mypool2/
file1.txt  file2.txt  file3.txt  somefile
# zpool status
  pool: mypool
 state: ONLINE
  scan: resilvered 566K in 0h0m with 0 errors on Wed Dec  3 00:18:28 2014
config:

    NAME                 STATE     READ WRITE CKSUM
    mypool               ONLINE       0     0     0
      /mnt/sda3/primary  ONLINE       0     0     0

errors: No known data errors

  pool: mypool2
 state: ONLINE
  scan: resilvered 566K in 0h0m with 0 errors on Wed Dec  3 00:18:28 2014
config:

    NAME                          STATE     READ WRITE CKSUM
    mypool2                       ONLINE       0     0     0
      /mnt/sda3/rotating_mirror1  ONLINE       0     0     0

errors: No known data errors

下一个:

# zpool export mypool2
# rmdir /mypool2a

看起来我现在应该能够引入rotating_mirror2了:

# zpool attach mypool /mnt/sda3/primary /mnt/sda3/rotating_mirror2
# zpool status
  pool: mypool
 state: ONLINE
  scan: resilvered 524K in 0h0m with 0 errors on Wed Dec  3 00:25:36 2014
config:

    NAME                            STATE     READ WRITE CKSUM
    mypool                          ONLINE       0     0     0
      mirror-0                      ONLINE       0     0     0
        /mnt/sda3/primary           ONLINE       0     0     0
        /mnt/sda3/rotating_mirror2  ONLINE       0     0     0

errors: No known data errors

此时,我创建了更多文件和快照来模拟磁盘随着时间的推移而被更多地使用。

现在我想删除rotating_mirror2,但我还不想将rotating_mirror1重新放回来。

# zpool split -R /mypool2a mypool mypool2 /mnt/sda3/rotating_mirror2
# zpool export mypool2
# rmdir /mypool2a

我想,如果我此时尝试将 spinning_mirror1 重新带回来,它的所有内容都会被销毁,并且当前主镜像将被镜像到 spinning_mirror1 上。

如果主服务器出现故障,此时需要从 spinning_mirror1 恢复,该怎么办?如何使用 spinning_mirror1 重建主服务器?

# zpool destroy mypool
# zpool import -d /mnt/sda3/ -N mypool2 mypool
# zpool status
  pool: mypool
 state: ONLINE
  scan: resilvered 524K in 0h0m with 0 errors on Wed Dec  3 00:25:36 2014
config:

    NAME                          STATE     READ WRITE CKSUM
    mypool                        ONLINE       0     0     0
      /mnt/sda3/rotating_mirror1  ONLINE       0     0     0

errors: No known data errors
# zfs set mountpoint=/mypool mypool
# ls /mypool

有趣的是,此时,我本以为会看到第一个镜像上的文件,但我什么也没看到。

编辑:我重新开始执行了所有步骤,现在我了解得更多了,并做了一些小调整。我没有完成下面的所有步骤,但为了完整性,我把它们都放在这里。我想这次我明白了。

# cd /mnt/sda3
# truncate -s 2G primary
# truncate -s 2G rotating_mirror1
# truncate -s 2G rotating_mirror2
# zpool create mypool mirror /mnt/sda3/primary /mnt/sda3/rotating_mirror1
# crontab -e
# echo (Paste crontab snippet from above.)

使用泳池。

# echo QUESTION Should a snapshot be created here?
# zpool split -R /mypool2 mypool mypool2 /mnt/sda3/rotating_mirror1
# zpool export mypool2
# rmdir /mypool2
# zpool attach mypool /mnt/sda3/primary /mnt/sda3/rotating_mirror2

多使用一下游泳池。

# echo QUESTION Should a snapshot be created here?
# zpool split -R /mypool2 mypool mypool2 /mnt/sda3/rotating_mirror2
# zpool export mypool2
# rmdir /mypool2

对 mypool 做一些非常糟糕的事情以致于需要重新创建它。

# echo QUESTION Should a backup of rotating_mirror2 be made prior to restoration in case something bad happens, or is there any way to bring in its contents read-only?
# zpool export mypool
# zpool import -d /mnt/sda3/ mypool2 mypool
# zpool attach mypool /mnt/sda3/rotating_mirror2 /mnt/sda3/primary

请注意,一旦运行了导入命令,primary 和 spinning_mirror2 都会拥有相同的池名称,因此此示例中的任何后续导入命令都无法像上面列出的那样工作。相反,需要通过数字 ID 导入池:

# zpool import -d /mnt/sda3/
   pool: mypool
     id: 17080681945292377797
  state: ONLINE
 action: The pool can be imported using its name or numeric identifier.
 config:

    mypool                        ONLINE
      /mnt/sda3/rotating_mirror2  ONLINE

   pool: mypool
     id: 4810117573923218177
  state: ONLINE
 action: The pool can be imported using its name or numeric identifier.
 config:

    mypool               ONLINE
      /mnt/sda3/primary  ONLINE

# zpool import -d /mnt/sda3/ 4810117573923218177
# zpool export mypool
# zpool import -d /mnt/sda3/ 17080681945292377797

不过,老实说,这让我有点不舒服,因为导入镜像会导致它被修改,因为它的池名称已经改变,并且因为它现在是活动的,并且可以在重建主镜像时进行修改。

我可以理解这对于镜子来说很好,但回想一下,当它们“插入”时,我想将这些镜子视为实时备份。

我还没有尝试过这个,但如果没有异议的话,我想我宁愿不导入rotating_mirror2,而是执行以下操作:

# dd if=/mnt/sda3/rotating_mirror2 of=/mnt/sda3/primary bs=...

完成后,我希望我可以直接导入主要内容,并且每个人都会很高兴。

最后说明一下:我了解到我可以拥有多个镜像,所以如果我真的想要,我可以设置四个驱动器而不是三个,其中两个将是彼此始终活动的“主”镜像,并且rotating_mirror1和rotating_mirror2将是第三个驱动器而不是第二个驱动器。

谢谢。

答案1

1:如果您不想要ZFS冗余,您可以:

  • 使用您的第一个磁盘作为您的活动池。
  • 安排快照以便在出现人为错误时快速回滚rm -rf
  • 在第二个磁盘上创建备份池
  • 定期从第一个池增量快照更新此备份池:zfs send ... | zfs receive ...

需要使用备用根创建备份池以避免挂载点冲突。

您可以将备份磁盘与另一个磁盘交换以将其存储在其他地方。只需在移除磁盘之前导出备份池,在另一个磁盘上创建备用备份池并对第一个池进行初始完整备份即可。

2:如果您想要冗余,那么可以使用镜像池,当您想要交换磁盘时,使用命令拆分池zpool split,移除新创建的池磁盘,插入备用磁盘,销毁备用池并使用添加的磁盘配置镜像。

#2 更安全,因为存在数据冗余,因此我推荐它。

答案2

(3) 最后,最近我突然意识到,我可能不需要使用 ZFS 做任何如此复杂的事情。如果我将两个驱动器设置为类似于 RAID1 的镜像 vdev 配置,然后设置每小时快照,会怎么样?这样,我似乎会有一个即时备份,并且可以避免可怕的 RAID-is-not-a-backup:/bin/rm -Rf /*

这如何帮助您避免 ZFS 级别的命令意外完全删除所有快照、数据集和池?显然,RAID 仍然不是备份,ZFS 发送/接收为您提供了很好的工具,让您甚至不必考虑仅将 RAID 用作备份。

相关内容