Btrfs subvolumes and snapshots

本页指导用户在 MikroTik RouterOS 上创建 Btrfs 子卷和快照,说明如何组织数据、格式化磁盘、设置 Documents 和 Photos 等子卷,以及如何创建快照以实现高效备份而无需复制数据。

Btrfs 子卷与快照

信息

此功能需要 Storage 软件包。

创建子卷

创建子卷的主要好处是组织你 Btrfs 主(根)子卷上的数据。可以把子卷看作具备分区特性的文件夹,同时所有子卷之间仍然共享整个磁盘空间。之后你可以将这些子卷用于更高级的任务;当你拥有大量不同类型的数据,尤其是需要频繁备份的数据时,建议创建子卷。按照以下指南设置几个示例子卷:

提示

子卷与快照配合使用时最为有用。请务必也查看快照功能。

  1. 找到你想用作 Btrfs 磁盘的磁盘名称:

    /disk/print
    

    :::warning 在本示例中,使用的磁盘将被称为 <disk-name-1>,请确保将占位符替换为你实际的磁盘名称! :::

  2. 将该磁盘格式化为 Btrfs,本例中为 <disk-name-1>:

    /disk/format <disk-name-1> file-system=btrfs
    
  3. 为便于识别,为 Btrfs 磁盘添加一个标签:

    /disk/btrfs/filesystem/set [find where present-devs=<disk-name-1>] label=BtrfsDisk
    
  4. 为便于管理,你也可以更改 Btrfs 磁盘的挂载点:

    /disk/set <disk-name-1> mount-point-template=BtrfsDisk
    
  5. 创建一个名为 Documents 的新子卷到 BtrfsDisk:

    /disk/btrfs/subvolume/add name=Documents fs=BtrfsDisk
    

    :::info 子卷同时也是快照。你可能会在不同的菜单中遇到这两个名称。简单来说,快照是在特定时间创建的子卷,包含该时间点的数据。 :::

  6. 创建另一个名为 Photos 的子卷到 BtrfsDisk:

    /disk/btrfs/subvolume/add name=Photos fs=BtrfsDisk
    
  7. 你可以查看当前可用的子卷:

    /disk/btrfs/subvolume/print
    
  8. 现在你可以通过 /BtrfsDisk/Documents 和 /BtrfsDisk/Photos 访问这些子卷。

创建快照

快照是一种空间高效的备份数据方式。通过创建快照,你可以保存数据的当前状态,之后仍可访问。

警告

快照不会创建数据的副本,它们保存的是数据的当前状态,同时允许你对当前数据做出修改。快照包含的是如何将当前数据还原到快照创建时状态的信息。快照不会像完整备份那样创建数据的多份副本。

说明

虽然你可以为根子卷创建快照,但建议为你的数据创建一个新的子卷,然后再使用快照功能。这只是管理大量快照时的一种偏好。

  1. 创建子卷(或使用根子卷,见上文)并将数据放入这些子卷,例如:

    [admin@MikroTik] > /file/print 
     # NAME   
     0 BtrfsDisk
     1 BtrfsDisk/Documents
     2 BtrfsDisk/Photos 
     3 BtrfsDisk/Documents/document1.txt
     4 BtrfsDisk/Photos/photo1.jpg
    
  2. 在本示例中,我们创建了 /BtrfsDisk/Documents 和 /BtrfsDisk/Photos/ 子卷,你可以使用以下命令查看它们:

    /disk/btrfs/subvolume/print
    
  3. 为了让快照更有条理,创建一个名为 Snapshots 的新子卷:

    /disk/btrfs/subvolume/add name=Snapshots fs=BtrfsDisk
    
  4. 为 Documents 和 Photos 创建快照:

    /disk/btrfs/subvolume/add read-only=yes parent=Documents fs=BtrfsDisk  name=Snapshots/Documents-22012025
    /disk/btrfs/subvolume/add read-only=yes parent=Photos fs=BtrfsDisk  name=Snapshots/Photos-22012025
    
  5. 现在你应该有了只读且包含你文件的新子卷:

    [admin@MikroTik] > /file/print 
     # NAME      
     0 BtrfsDisk
     1 BtrfsDisk/Documents
     2 BtrfsDisk/Photos
     3 BtrfsDisk/Snapshots
     4 BtrfsDisk/Documents/document1.txt
     5 BtrfsDisk/Photos/photo1.jpg
     6 BtrfsDisk/Snapshots/Documents-22012025
     7 BtrfsDisk/Snapshots/Photos-22012025
     8 BtrfsDisk/Snapshots/Documents-22012025/document1.txt
     9 BtrfsDisk/Snapshots/Photos-22012025/photo1.jpg
    
  6. 为了测试,你可以向子卷中添加更多数据,你会注意到新添加的文件不会出现在快照中,只会出现在子卷中:

    [admin@infra1.mikrotikls.lv] > /file/print 
     # NAME   
     0 BtrfsDisk
     1 BtrfsDisk/Documents
     2 BtrfsDisk/Photos
     3 BtrfsDisk/Snapshots
     4 BtrfsDisk/Documents/document1.txt
     5 BtrfsDisk/Documents/document2.txt
     6 BtrfsDisk/Photos/photo1.jpg
     7 BtrfsDisk/Photos/photo2.jpg 
     8 BtrfsDisk/Snapshots/Photos-22012025
     9 BtrfsDisk/Snapshots/Documents-22012025
    10 BtrfsDisk/Snapshots/Documents-22012025/document1.txt
    11 BtrfsDisk/Snapshots/Photos-22012025/photo1.jpg
    
  7. 现在你可以创建一个新快照:

    /disk/btrfs/subvolume/add read-only=yes parent=Documents fs=BtrfsDisk  name=Snapshots/Documents-23012025 
    /disk/btrfs/subvolume/add read-only=yes parent=Photos fs=BtrfsDisk  name=Snapshots/Photos-23012025 
    
  8. 创建新快照后,每个子卷都会有 2 个快照。一个包含较旧的文件,另一个包含较旧和较新的文件:

    [admin@MikroTik] > /file/print 
     # NAME   
     0 BtrfsDisk
     1 BtrfsDisk/Documents
     2 BtrfsDisk/Photos
     3 BtrfsDisk/Snapshots
     4 BtrfsDisk/Documents/document1.txt
     5 BtrfsDisk/Documents/document2.txt
     6 BtrfsDisk/Photos/photo1.jpg
     7 BtrfsDisk/Photos/photo2.jpg
     8 BtrfsDisk/Snapshots/Photos-22012025
     9 BtrfsDisk/Snapshots/Documents-22012025
    10 BtrfsDisk/Snapshots/Documents-23012025
    11 BtrfsDisk/Snapshots/Photos-23012025
    12 BtrfsDisk/Snapshots/Documents-22012025/document1.txt 
    13 BtrfsDisk/Snapshots/Documents-23012025/document1.txt
    14 BtrfsDisk/Snapshots/Documents-23012025/document2.txt
    15 BtrfsDisk/Snapshots/Photos-22012025/photo1.jpg
    16 BtrfsDisk/Snapshots/Photos-23012025/photo1.jpg
    17 BtrfsDisk/Snapshots/Photos-23012025/photo2.jpg
    

    :::note

    多个快照不会为每个文件创建多份副本,但如果某个文件已被删除但仍存在于快照中,那么被删除的文件会占用空间。如果某个文件存在于多个快照中,它也只占用一个文件的空间。

    :::

  9. 如果你不再需要某个较旧的快照,可以将其删除:

    /disk/btrfs/subvolume/remove [find where name=Documents-22012025]
    /disk/btrfs/subvolume/remove [find where name=Photos-22012025]
    

传输你的快照

Btrfs 允许你在两台使用 Btrfs 的设备之间轻松发送快照。在本示例中,我们将使用两台运行 Storage 软件包的 RouterOS 设备。包含需要备份快照的 RouterOS 设备称为 RouterA,接收备份的 RouterOS 设备称为 RouterB。

信息

本指南仅展示如何在 RouterOS 设备之间使用 Btrfs 传输,但你也可以在 RouterOS 和 Linux 设备之间传输快照。如果你需要此类功能,请务必查阅你所使用的 Linux 发行版的文档,了解如何在其上使用 Btrfs 传输。

提示

本指南将使用 SSH 主机密钥作为同一 RouterOS 设备上 SSH 用户的密钥。如果你希望为自己的 SSH 用户使用自有密钥,可以在 Linux 计算机上使用以下命令,之后将密钥对导入到 /user/ssh-keys 下:

openssl genpkey -outform PEM -out btrfstransfer_key.pem -algorithm ED25519
openssl pkey -in btrfstransfer_key.pem -pubout -out btrfstransfer_key_pub.pem
  1. 可选:提高 SSH 服务器的安全级别,在 RouterA 和 RouterB 上运行以下命令:

    /ip/ssh/set host-key-type=ed25519 strong-crypto=yes
    /ip/ssh/regenerate-host-key
    

    :::warning

    重新生成主机密钥后,下次你尝试使用 SSH 连接到 RouterOS 设备时会收到错误消息。你需要调整 SSH 客户端的配置(通常在 ~/.ssh/known_hosts 中)以信任新的主机密钥。

    :::

  2. 在 RouterA 上导出 SSH 私钥和公钥:

    /ip/ssh/export-host-key key-file-prefix=admin
    
  3. 在 RouterA 上为用户 admin 导入 SSH 私钥:

    /user/ssh-keys/private/import private-key-file=admin_ed25519.pem user=admin
    
  4. 将 SSH 公钥从 RouterA 上传到 RouterB:

    /file/sync/add local-path=admin_ed25519_pub.pem remote-address=RouterB user=admin mode=upload
    /file/sync/remove [find where local-path=admin_ed25519_pub.pem]
    
  5. 在 RouterB 上创建一个新用户,例如 btrfstransfer,并为其设置一个安全密码:

    /user/add name=btrfstransfer group=write
    

    :::warning

    虽然该密码不会用于 Btrfs 传输功能,但你仍然需要使用安全密码来防止对设备的未授权访问。

    :::

  6. 在 RouterB 上导入已上传的 SSH 公钥,并将其设置为用户 btrfstransfer 的密钥:

    /user/ssh-keys/import public-key-file=admin_ed25519_pub.pem user=btrfstransfer
    
  7. 在 RouterA 上设置类型 send:

    /disk/btrfs/transfer/add type=send fs=BtrfsDisk ssh-address=RouterB send-subvolumes=Documents-23012025 ssh-user=btrfstransfer ssh-receive-mount=BackupBtrfsDisk/Snapshots
    

    其中:

    • BtrfsDisk 是在 RouterA 上 /disk/btrfs/filesystem/print 中找到的 Btrfs 磁盘标签。
    • Documents-23012025 是快照名称(不是路径)。
    • btrfstransfer 是 RouterB 上的 SSH 用户。
    • BackupBtrfsDisk 是在 RouterB 上 /disk/btrfs/filesystem/print 中找到的 Btrfs 磁盘标签。
    • Snapshots 是 BackupBtrfsDisk 下用于存放快照的子卷。
  8. 在 RouterB 上设置类型 receive:

    /disk/btrfs/transfer/add fs=BackupBtrfsDisk type=receive file=BackupBtrfsDisk/Snapshots
    

    其中:

    • BackupBtrfsDisk 是在 RouterB 上 /disk/btrfs/filesystem/print 中找到的 Btrfs 磁盘标签
    • BackupBtrfsDisk/Snapshots 是 Snapshots 子卷的挂载路径。