我在 RAID10 中有一个带有 6 个驱动器的 ZFS 池——嗯,它曾经是。
我试图将 146GB 驱动器升级到 1TB 驱动器,但搞砸了。
root@x7550:~# zpool status
pool: stuffpool
state: ONLINE
scan: scrub repaired 0 in 0h6m with 0 errors on Mon May 9 15:26:39 2016
config:
NAME STATE READ WRITE CKSUM
stuffpool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1 ONLINE 0 0 0
ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1 ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
ata-HGST_HTS541010A9E680_JA1000102MG9UR-part1 ONLINE 0 0 0
ata-HGST_HTS541010A9E680_JA1009C03158BP-part1 ONLINE 0 0 0
scsi-35000c50016ebcdfb-part1 ONLINE 0 0 0
ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1 ONLINE 0 0 0
Run Code Online (Sandbox Code Playgroud)
scsi-35000c50016ebcdfb-part1
ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1
曾经在 mirror-2 中,并且是我试图添加到 mirror-2 的驱动器。
我能做些什么来解决这个问题吗?
我在 ubuntu 16.04 上运行
root@x7550:~# zpool history stuffpool | tail -n50
History for 'stuffpool':
2016-03-27.01:56:12 zpool create stuffpool mirror ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1 ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1 -f
2016-03-27.01:57:41 zpool add stuffpool mirror /dev/disk/by-id/ata-HGST_HTS541010A9E680_JA1000102MG9UR-part1 /dev/disk/by-id/ata-HGST_HTS541010A9E680_JA1009C03158BP-part1 -f
2016-03-27.01:59:25 zpool add stuffpool mirror /dev/disk/by-id/scsi-35000c50016ebcdfb-part1 /dev/disk/by-id/scsi-35000c50017675203-part1 -f
2016-03-27.02:12:38 zpool import -c /etc/zfs/zpool.cache -aN
2016-03-27.23:48:32 zfs create stuffpool/stuff
2016-03-27.23:54:47 zpool import -c /etc/zfs/zpool.cache -aN
2016-03-28.00:02:23 zfs create stuffpool/backup
2016-03-30.23:18:04 zpool scrub stuffpool
2016-04-03.01:06:06 zpool import -c /etc/zfs/zpool.cache -aN
2016-04-03.01:15:33 zfs create -p -o mountpoint=/var/lib/lxd/images/f96b6b5d7587150b880e96f872393b7fee53741046b40a76c6db22ed40886bc9.zfs stuffpool/images/f96b6b5d7587150b880e96f872393b7fee53741046b40a76c6db22ed40886bc9
2016-04-03.01:15:53 zfs set readonly=on stuffpool/images/f96b6b5d7587150b880e96f872393b7fee53741046b40a76c6db22ed40886bc9
2016-04-03.01:15:54 zfs snapshot -r stuffpool/images/f96b6b5d7587150b880e96f872393b7fee53741046b40a76c6db22ed40886bc9@readonly
2016-04-03.01:16:00 zfs clone -p -o mountpoint=/var/lib/lxd/containers/ux-1.zfs stuffpool/images/f96b6b5d7587150b880e96f872393b7fee53741046b40a76c6db22ed40886bc9@readonly stuffpool/containers/ux-1
2016-04-08.01:31:47 zpool import -c /etc/zfs/zpool.cache -aN
2016-04-08.01:43:48 zpool import -c /etc/zfs/zpool.cache -aN
2016-04-19.00:00:30 zpool import -c /etc/zfs/zpool.cache -aN
2016-04-21.18:14:15 zfs create -p -o mountpoint=/var/lib/lxd/images/9b03bacc30bcfbe3378e8803daa48ca2d32baa99d111efada484876750e5cc20.zfs stuffpool/images/9b03bacc30bcfbe3378e8803daa48ca2d32baa99d111efada484876750e5cc20
2016-04-21.18:14:35 zfs set readonly=on stuffpool/images/9b03bacc30bcfbe3378e8803daa48ca2d32baa99d111efada484876750e5cc20
2016-04-21.18:14:36 zfs snapshot -r stuffpool/images/9b03bacc30bcfbe3378e8803daa48ca2d32baa99d111efada484876750e5cc20@readonly
2016-04-21.18:14:36 zfs set mountpoint=none stuffpool/images/f96b6b5d7587150b880e96f872393b7fee53741046b40a76c6db22ed40886bc9
2016-04-21.18:14:41 zfs rename -p stuffpool/images/f96b6b5d7587150b880e96f872393b7fee53741046b40a76c6db22ed40886bc9 stuffpool/deleted/images/f96b6b5d7587150b880e96f872393b7fee53741046b40a76c6db22ed40886bc9
2016-04-24.22:54:03 zpool scrub stuffpool
2016-05-07.22:55:42 zpool import -c /etc/zfs/zpool.cache -aN
2016-05-09.15:20:27 zpool scrub stuffpool
2016-05-17.22:56:53 zfs create -p -o mountpoint=/var/lib/lxd/images/4f7a1fe6b71446eba6ee56f49698bd6592f193f731f1c0d9d51b1d199b9b75a5.zfs stuffpool/images/4f7a1fe6b71446eba6ee56f49698bd6592f193f731f1c0d9d51b1d199b9b75a5
2016-05-17.22:57:12 zfs set readonly=on stuffpool/images/4f7a1fe6b71446eba6ee56f49698bd6592f193f731f1c0d9d51b1d199b9b75a5
2016-05-17.22:57:13 zfs snapshot -r stuffpool/images/4f7a1fe6b71446eba6ee56f49698bd6592f193f731f1c0d9d51b1d199b9b75a5@readonly
2016-05-17.22:57:18 zfs destroy -r stuffpool/images/9b03bacc30bcfbe3378e8803daa48ca2d32baa99d111efada484876750e5cc20
2016-05-21.16:47:49 zpool import -c /etc/zfs/zpool.cache -aN
2016-06-09.22:59:47 zpool import -c /etc/zfs/zpool.cache -aN
2016-06-13.20:59:10 zpool import -c /etc/zfs/zpool.cache -aN
2016-06-13.20:59:34 zfs create -p -o mountpoint=/var/lib/lxd/images/49fc7d0d6f01a7639129308b73ad27f5fb7b9d3bb783d905393b6b9e9c4bf1c5.zfs stuffpool/images/49fc7d0d6f01a7639129308b73ad27f5fb7b9d3bb783d905393b6b9e9c4bf1c5
2016-06-13.20:59:54 zfs set readonly=on stuffpool/images/49fc7d0d6f01a7639129308b73ad27f5fb7b9d3bb783d905393b6b9e9c4bf1c5
2016-06-13.20:59:54 zfs snapshot -r stuffpool/images/49fc7d0d6f01a7639129308b73ad27f5fb7b9d3bb783d905393b6b9e9c4bf1c5@readonly
2016-06-13.21:00:00 zfs destroy -r stuffpool/images/4f7a1fe6b71446eba6ee56f49698bd6592f193f731f1c0d9d51b1d199b9b75a5
2016-06-18.02:18:55 zpool import -c /etc/zfs/zpool.cache -aN
2016-06-18.02:27:08 zpool offline stuffpool 1759097636360003165
2016-06-18.02:33:28 zpool detach stuffpool 1759097636360003165
2016-06-18.12:23:26 zpool export stuffpool
2016-06-18.12:24:38 zpool import stuffpool
2016-06-18.12:27:34 zpool add -f stuffpool ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1
2016-06-18.12:31:05 zpool export stuffpool
2016-06-18.13:19:17 zpool import stuffpool
Run Code Online (Sandbox Code Playgroud)
所有 ATA 驱动器均为 1tb,SCSI 驱动器为 146GB
这是使用信息
root@x7550:~# zpool list
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
stuffpool 2.85T 162G 2.69T - 2% 5% 1.00x ONLINE -
Run Code Online (Sandbox Code Playgroud)
这是我的个人服务器,所以停机不是问题。
好吧,你把自己搞得一团糟,但看起来它是可以修复的。
您犯的第一个错误是zpool add
新驱动器,而不是zpool attach
(将附加设备附加到镜像),甚至更好zpool replace
的是旧设备仍然存在于池元数据中。更换设备的正确方法是
# zpool replace stuffpool 1759097636360003165 ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1
Run Code Online (Sandbox Code Playgroud)
或者甚至更好,如果你有物理能力,zpool replace
旧设备和新设备都连接(在整个过程中保持池冗余)。
此时,您的旧池基本上已损坏无法修复:添加后无法从池中删除 vdev(不匹配的 vdev 冗余级别可能是您需要-f
将新磁盘放入池的原因),并且您没有没有将两个非冗余 vdev 变成双向镜像的硬件。
但是,您可以利用现有资源创建一个新池。
在您采取任何行动之前通读所有这些内容,并确保您了解每个步骤的内容和原因。你真的不想再搞砸了。
首先,绝对确保您拥有最新的、可靠的数据备份。鉴于您只存储了 160 GB 多一点,这应该不是什么大问题。我还非常强烈建议您zpool scrub
确保池中存储的所有数据都没有任何错误。使用 160 GB,并且如您之前的清理所示,应该不需要很长时间即可完成。
然后,将一个驱动器与镜像分离,释放它。例如,要将 mirror-0 分开并使用那里的驱动器之一,您可能
# zpool detach stuffpool ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1
Run Code Online (Sandbox Code Playgroud)
这将为您留下stuffpool
由三个单设备 vdev 和一个双向镜像 vdev (mirror-1) 组成。然后清除与镜像分离的驱动器上的所有 ZFS 标签,以便您可以重新利用它:
# zpool labelclear /dev/disk/by-id/ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1
Run Code Online (Sandbox Code Playgroud)
此时,ZFS 不会将该驱动器识别为旧池的一部分。您可能需要-f
到zpool labelclear
,但是不要盲目添加它; 确保您了解您可能需要它的原因。
重命名旧池(假设您要保留名称,否则根据需要在下面进行调整):
# zpool export stuffpool
# zpool import stuffpool stuffpoolold
Run Code Online (Sandbox Code Playgroud)
在释放的驱动器上创建一个新池:
# zpool create -o ashift=12 -O checksum=sha256 -m none -f stuffpool /dev/disk/by-id/ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1
Run Code Online (Sandbox Code Playgroud)
我建议使用 SHA-256 进行校验和,但如果您不想,可以省略该-O checksum=sha256
部分。-o ashift=12
告诉 ZFS 使用 4,096 字节块作为最小分配单元,这在较小的存储空间成本下与“高级格式”驱动器配合使用效果更好。
如果您不使用池上的根文件系统来存储数据,则某些故障情况更容易恢复。我建议你在池上创建一个代理根文件系统:
# zfs create -o mountpoint=/mnt/stuffpoolnew stuffpool/data
Run Code Online (Sandbox Code Playgroud)
现在,将所有内容从旧池转移到新池。首先创建旧池当前状态的快照:
# zfs snapshot stuffpoolold@transfer -r
Run Code Online (Sandbox Code Playgroud)
确保快照创建成功。然后:
# zfs send -R stuffpoolold@transfer | zfs receive -uvF stuffpool/data
Run Code Online (Sandbox Code Playgroud)
这将需要一段时间。让它运行到完成,然后抓住在此期间改变的任何东西:
# zfs snapshot stuffpoolold@transfer2 -r
# zfs send -I stuffpoolold@transfer stuffpoolold@transfer2 -Rv | zfs receive stuffpool/data -uv
Run Code Online (Sandbox Code Playgroud)
在这一点上,池上的数据在所有意图和目的上都应该是相同的。如果您有 cron 作业或类似的东西在运行写入池,请考虑制作第二个快照和zfs send -I ...
来自单用户模式,以降低将数据添加到池中的风险。
设置新池以代替旧池:
# zfs get mountpoint stuffpoolold
... this will give you a mountpoint directory ...
# zpool export stuffpoolold
# zfs set mountpoint=...mountpoint_directory_from_above... stuffpool/data
# zpool export stuffpool
# zpool import stuffpool
Run Code Online (Sandbox Code Playgroud)
此时,您的新 zpool 只包含一个设备。擦洗它以确保数据正常:
# zpool scrub stuffpool
Run Code Online (Sandbox Code Playgroud)
当它完成而没有发现任何错误时,继续将旧磁盘迁移到新池。从旧的剩余镜像 1 对的第二个驱动器开始(因为我们使用了上面镜像 0 的第二个驱动器),以尽可能长时间地保持旧池的可导入性:
# zpool labelclear /dev/disk/by-id/ata-HGST_HTS541010A9E680_JA1009C03158BP-part1
# zpool attach stuffpool /dev/disk/by-id/ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1 /dev/disk/by-id/ata-HGST_HTS541010A9E680_JA1009C03158BP-part1
Run Code Online (Sandbox Code Playgroud)
检查zpool status stuffpool
以确保您现在拥有一个由单个双向镜像 vdev 组成的池,如下所示:
root@x7550:~# zpool status stuffpool
pool: stuffpool
state: ONLINE
scan: scrub repaired 0 in 0h6m with 0 errors on ...
config:
NAME STATE READ WRITE CKSUM
stuffpool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1 ONLINE 0 0 0
ata-HGST_HTS541010A9E680_JA1009C03158BP-part1 ONLINE 0 0 0
Run Code Online (Sandbox Code Playgroud)
现在继续添加两个镜像 vdev,首先按照您想要的方式添加它们。您需要先标记清除设备(否则 ZFS 会抱怨它们已经是导出池的一部分)。同样,你可能需要-f
到zpool labelclear
,但绝对不盲目添加-f
到zpool add
。(如果你必须这样做,那么我在某个地方犯了一个错误。)
# zpool labelclear /dev/disk/by-id/ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1
# zpool labelclear /dev/disk/by-id/ata-HGST_HTS541010A9E680_JA1000102MG9UR-part1
# zpool labelclear /dev/disk/by-id/scsi-35000c50016ebcdfb-part1
# zpool labelclear /dev/disk/by-id/ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1
# zpool add stuffpool mirror /dev/disk/by-id/ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1 /dev/disk/by-id/ata-HGST_HTS541010A9E680_JA1000102MG9UR-part1
# zpool add stuffpool mirror /dev/disk/by-id/scsi-35000c50016ebcdfb-part1 /dev/disk/by-id/ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1
Run Code Online (Sandbox Code Playgroud)
再次擦洗(因为每个人都喜欢干净整洁的游泳池):
# zpool scrub stuffpool
Run Code Online (Sandbox Code Playgroud)
此时,您的池应该看起来像您从一开始就想要的:
root@x7550:~# zpool status
pool: stuffpool
state: ONLINE
scan: scrub repaired 0 in 0h6m with 0 errors on ...
config:
NAME STATE READ WRITE CKSUM
stuffpool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1 ONLINE 0 0 0
ata-HGST_HTS541010A9E680_JA1009C03158BP-part1 ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1 ONLINE 0 0 0
ata-HGST_HTS541010A9E680_JA1000102MG9UR-part1 ONLINE 0 0 0
mirror-2 ONLINE 0 0 0
scsi-35000c50016ebcdfb-part1 ONLINE 0 0 0
ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1 ONLINE 0 0 0
Run Code Online (Sandbox Code Playgroud)
您的池现在是不平衡的(几乎所有的数据是上镜0,并且将一直保留,直到改写;虽然ZFS没有任何类似的btrfs rebalance
,你仍然可以解决这个问题,如果使用得当的zfs send ... | zfs receive
),但它的布局和冗余你当你开始的时候打算。
这是一个漫长的过程,有很多步骤,但如果你慢慢来,仔细想想每一步你在做什么,它并不是特别危险。
优点是池上的数据比任何一个驱动器都填满的数据要少得多。如果您的池几乎已满,则情况会复杂得多。