Raid

ZFS 弄亂了鏡像

  • September 28, 2016

我在 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

scsi-35000c50016ebcdfb-part1用於在 mirror-2 中,並且ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1是我試圖添加到 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

所有 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  -

這是我的個人伺服器,所以停機時間不是問題。

幸運的是,您的池中只有 160GB 的數據。

如果您在另一個文件系統上有一個目錄,該目錄有足夠的可用空間來儲存大約 160GB 的備份數據,或者壓縮後更少(我將 /var/backup/在我的範例中使用),您可以:

首先,殺死任何可能正在向stuffpool. 如果有任何 cron 等作業可以crond寫入.atd``stuffpool

創建stuffpoolwith的完整備份zfs send -R,將其保存到文件中:

zfs snapshot stuffpool@fullbackup
zfs send -R stuffpool@fullbackup | gzip > /var/backup/stuffpool.zfs.send.gz

順便說一句,壓縮備份不僅佔用更少的磁碟空間,備份和恢復所需的時間也更短……所使用的任何 CPU 時間gzip幾乎總是遠遠少於通過讀取/寫入顯著減少的數據所節省的時間磁碟。磁碟 I/O 是瓶頸,通常比壓縮需要更多時間。

接下來,使用 銷毀目前池zfs destroy stuffpool

使用以下命令重新創建素材池:

zpool create -o ashift=12 -o checksum=sha256 -f \
 mirror \
   ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1 \
   ata-HGST_HTS541010A9E680_JA1009C03158BP-part1 \
 mirror \
   ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1 \
   ata-HGST_HTS541010A9E680_JA1000102MG9UR-part1 \
 mirror \
   scsi-35000c50016ebcdfb-part1 \
   ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1

最後,恢復stuffpool

zcat /var/backup/stuffpool.zfs.send.gz | zfs receive stuffpool -v -d

如果需要,您可以通過刪除fullbackup快照來整理池:

zfs destroy stuffpool@fullbackup

或者您可以將其保留為您必須重建池的時間點快照。

/var/backup/stuffpool.zfs.send.gz可以刪除。


如果現有文件系統上沒有足夠的備用磁碟空間,則可以從現有的​​資料池中分離其中一個鏡像磁碟,對其進行格式化並使用它來臨時儲存stuffpool.zfs.send.gz文件。

使用ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1為例:

zpool detach stuffpool ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1

mkfs.ext4 /dev/disk/by-id/ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1
mount /dev/disk/by-id/ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1 /mnt

zfs snapshot stuffpool@fullbackup
zfs send -R stuffpool@fullbackup | gzip > /mnt/stuffpool.zfs.send.gz

zfs destroy stuffpool

zpool create -o ashift=12 -o checksum=sha256 -f \
   ata-HGST_HTS541010A9E680_JA1009C03158BP-part1 \
 mirror \
   ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1 \
   ata-HGST_HTS541010A9E680_JA1000102MG9UR-part1 \
 mirror \
   scsi-35000c50016ebcdfb-part1 \
   ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1

zcat /mnt/stuffpool.zfs.send.gz | zfs receive stuffpool -v -d

umount /mnt

zpool attach -f stuffpool \
   ata-HGST_HTS541010A9E680_JA1009C03158BP-part1 \
   ata-HGST_HTS721010A9E630_JR10004M0LGN6E-part1 

好吧,你給自己弄得有點亂,但它看起來是可以修復的。

您犯的第一個錯誤是zpool add在新驅動器上,而不是zpool attach(將附加設備附加到鏡像),甚至更好zpool replace的是舊設備仍然存在於池元數據中。更換設備的正確方法是

# zpool replace stuffpool 1759097636360003165 ata-HGST_HTS541010A9E680_JA109NDW206MAS-part1

甚至更好,如果您有物理能力,zpool replace則舊設備與新設備都連接(這將在整個過程中保持池冗餘)。

此時您的舊池基本上已損壞,無法修復:添加後您無法從池中刪除 vdev(不匹配的 vdev 冗餘級別可能是您需要-f將新磁碟放入池中的原因),而您不需要沒有將兩個非冗餘 vdev 變成雙向鏡像的硬體。

但是,您可以用現有的資源創建一個新池。

在您採取任何行動之前,請通讀所有這些內容,並確保您了解每個步驟的內容和原因。你真的不想再搞砸了。

首先,請絕對確保您擁有最新、可靠的數據備份。鑑於您只儲存了超過 160 GB 的空間,這應該不是什麼大問題。我還強烈建議zpool scrub確保池中的所有儲存數據都沒有任何錯誤。使用 160 GB,並且正如您之前的擦洗所示,它應該不需要很長時間才能完成。

然後,通過從鏡像中分離一個驅動器來釋放它。例如,要將 mirror-0 分開並使用其中的一個驅動器,您可以

# zpool detach stuffpool ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1

這將為您留下stuffpool三個單設備 vdev 和一個雙向鏡像 vdev (mirror-1)。然後清除從鏡像中分離出來的驅動器上的所有 ZFS 標籤,以便重新調整它的用途:

# zpool labelclear /dev/disk/by-id/ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1

此時,ZFS 不會將該驅動器辨識為舊池的一部分。你可能需要-fzpool labelclear但不要盲目添加;確保您了解您可能需要它的原因。

重命名舊池(假設您要保留名稱,否則根據需要在下面進行調整):

# zpool export stuffpool
# zpool import stuffpool stuffpoolold

在釋放的驅動器上創建一個新池:

# zpool create -o ashift=12 -O checksum=sha256 -m none -f stuffpool /dev/disk/by-id/ata-HGST_HTS721010A9E630_JR10004M0M17TE-part1

我建議對校驗和使用 SHA-256,但如果您不想這樣做,可以省略該-O checksum=sha256部分。-o ashift=12告訴 ZFS 使用 4,096 字節塊作為最小分配單元,這與“高級格式化”驅動器一起工作得更好,而且儲存空間成本很小。

如果您不使用池中的根文件系統來儲存數據,則某些故障情況更容易恢復。我建議您在池上創建一個代理根文件系統:

# zfs create -o mountpoint=/mnt/stuffpoolnew stuffpool/data

現在,將舊池中的所有內容轉移到新池中。首先創建舊池目前狀態的快照:

# zfs snapshot stuffpoolold@transfer -r

確保快照創建成功。然後:

# zfs send -R stuffpoolold@transfer | zfs receive -uvF stuffpool/data

這需要一段時間。讓它執行完成,然後抓取同時發生的任何變化:

# zfs snapshot stuffpoolold@transfer2 -r
# zfs send -I stuffpoolold@transfer stuffpoolold@transfer2 -Rv | zfs receive stuffpool/data -uv

在這一點上,池上的數據在所有意圖和目的上都應該是相同的。如果您正在執行寫入池的 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

此時,您擁有僅由一個設備組成的新 zpool。擦洗它以確保數據正常:

# zpool scrub stuffpool

當它完成且未發現任何錯誤時,繼續將舊磁碟遷移到新池。從舊的剩餘 mirror-1 對的第二個驅動器開始(因為我們在上面使用了 mirror-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

檢查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

現在繼續按照您最初想要的方式再添加兩個鏡像 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

再次擦洗(因為每個人都喜歡乾淨整潔的泳池):

# zpool scrub stuffpool

此時,您的池應該看起來像您從一開始就想要的那樣:

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

您的池現在是不平衡的(幾乎所有數據都在 mirror-0 上,並且將一直保留在那裡直到被重寫;儘管 ZFS 缺少任何類似的東西btrfs rebalance,您仍然可以通過明智地使用來修復它zfs send ... | zfs receive),但它具有您所需要的佈局和冗餘當你開始的時候。

這是一個漫長的過程,有很多步驟,但如果你慢慢來,並仔細考慮每一步你在做什麼,這並不是特別危險。

可取之處在於,池中的數據比任何一個驅動器都少得多。如果您的游泳池幾乎已滿,這將更加複雜。

引用自:https://unix.stackexchange.com/questions/290615