Skip to content

Commit 8aa2423

Browse files
committed
Add a post about a ZFS incident
1 parent 993b2c9 commit 8aa2423

File tree

2 files changed

+228
-0
lines changed

2 files changed

+228
-0
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#+OPTIONS: ^:nil
2+
#+BEGIN_EXPORT html
3+
---
4+
layout: default
5+
title: 如何“杀死”一个ZFS Pool
6+
tags: [ZFS, storage]
7+
nav_order: {{ page.date }}
8+
sync_wexin: 0
9+
---
10+
#+END_EXPORT
11+
12+
* 如何“杀死”一个ZFS Pool
13+
14+
** 起因
15+
16+
我家里有一个NAS服务器,存储空间由一个ZFS Pool提供。因为平常只是存一些共享的文档数据,数据增长不快,且ZFS一直工作得很稳定,我也不需要经常折腾这个设备。但是最近我多了一块空闲磁盘,我觉得空放着挺可惜,想将这块磁盘用起来。一个危险的想法就生成了,我想把这个磁盘加到ZFS Pool中去。
17+
18+
** 事件经过
19+
20+
我查了zpool的文章,有个zpool add和zpool attach的命令。我感觉zpool attach应该是追加磁盘的,但是试了几个命令都是失败的。
21+
22+
#+begin_src txt
23+
root@my-server:/home/user# zpool attach pool_name sdb sdd
24+
invalid vdev specification
25+
use '-f' to override the following errors:
26+
/dev/sdd1 contains a filesystem of type 'ntfs'
27+
root@my-server:/home/user# zpool attach -f pool_name sdb sdd
28+
cannot attach sdd to sdb: no such device in pool
29+
root@my-server:/home/user# zpool attach -f pool_name raidz1-0 sdd
30+
cannot attach sdd to raidz1-0: can only attach to mirrors and top-level disks
31+
#+end_src
32+
33+
我的磁盘是sdd,ZFS的报错信息感觉很没有头绪,什么“no such device in pool”,难道我需要先将我的盘加到pool里面么?attach命令不行,不是还有add命令么?我还没有意识到,存储系统是不能随便胡乱操作的,也没有思考失败其实是不支持的缘故。我就执行add命令,这个命令失败了。
34+
35+
#+begin_src txt
36+
root@my-server:/home/user# zpool add pool_name sdd
37+
invalid vdev specification
38+
use '-f' to override the following errors:
39+
mismatched replication level: pool uses raidz and new vdev is disk
40+
#+end_src
41+
42+
我看到了“use '-f' to override the following errors”,但没有理解下面一行的意思。可以用“-f”太好了,加上“-f”果然可以了。查看pool的状态。
43+
44+
#+begin_src txt
45+
root@my-server:/home/user# zpool status
46+
pool: pool_name
47+
state: ONLINE
48+
status: Some supported and requested features are not enabled on the pool.
49+
The pool can still be used, but some features are unavailable.
50+
action: Enable all features using 'zpool upgrade'. Once this is done,
51+
the pool may no longer be accessible by software that does not support
52+
the features. See zpool-features(7) for details.
53+
scan: scrub repaired 0B in 02:38:28 with 0 errors on Sun Apr 13 03:02:29 2025
54+
config:
55+
56+
NAME STATE READ WRITE CKSUM
57+
pool_name ONLINE 0 0 0
58+
raidz1-0 ONLINE 0 0 0
59+
sdc ONLINE 0 0 0
60+
sde ONLINE 0 0 0
61+
sdb ONLINE 0 0 0
62+
sdd ONLINE 0 0 0
63+
#+end_src
64+
65+
sdd已经在pool里了,但是没有加到原来的raid组里。我想sdd已经在pool里了,应该可以使用attach命令了吧。再次执行attach命令。
66+
67+
#+begin_src txt
68+
root@my-server:/home/user# zpool attach pool_name sdc sdd
69+
/dev/sdd is in use and contains a unknown filesystem.
70+
#+end_src
71+
72+
什么意思?难道是因为sdd原来的数据没有清空,事后回过神来才知道这个“a unknown filesystem”是因为sdd已经加到pool里面了。我在错误的道路上继续狂奔,是不是需要用dd将原来的数据清除掉?因为觉得这个sdd是个空闲的盘,觉得不会有什么问题,但其实并不是。我用dd命令把整个盘都写了一遍零。这个时候已经打错特错了。在我重启了服务器之后,啊...,pool不见了。使用“zpool import”命令也失败了。第一次import告诉我sdd是UNAVAIL状态,使用“-f”也不行,最后直接让我重建存储池了,可惜我并没有备份啊。
73+
74+
#+begin_src txt
75+
root@my-server:/home/user# zpool import
76+
pool: pool_name
77+
id: 16650549184859894038
78+
state: UNAVAIL
79+
status: One or more devices contains corrupted data.
80+
action: The pool cannot be imported due to damaged devices or data.
81+
see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-5E
82+
config:
83+
84+
pool_name UNAVAIL insufficient replicas
85+
raidz1-0 ONLINE
86+
sdc ONLINE
87+
sde ONLINE
88+
sdb ONLINE
89+
sdd UNAVAIL
90+
root@my-server:/home/user# zpool import -f -F pool_name
91+
cannot import 'pool_name': no such pool or dataset
92+
Destroy and re-create the pool from
93+
a backup source.
94+
#+end_src
95+
96+
这个时候我已经头皮发麻了。赶紧上网搜索解决方案,原来“zfs add”是给pool增加vdev,这样这个sdd和原来raidz1-0会形成一个raid0的存储池,数据会在两个设备间打散开来。好家伙,这样子整个存储池基本就没有冗余度了,只要sdd挂了,存储池就挂了,而我还来个大杀器。我当时真是欲哭无泪,积攒了十年的数据,好多手机和相机拍的照片,还有很多好看的电影,可能全都没了。
97+
98+
** 一线生机
99+
100+
在我把sdd加到原来的pool之后,并没有写什么数据,原来的数据都应该在之前的几块盘上,我觉得还有恢复数据的可能。我就上网找数据恢复方法,实在不行研究ZFS代码也行。我幸运地找到了一个Github Issue [[https://github.com/openzfs/zfs/issues/852]["Import a pool with missing top-level vdevs"]]。原来对于这种有顶层的磁盘损坏的pool,ZFS支持采用只读的方式导入。只能试一试了,方法并不复杂。先修改OpenZFS配置项,然后使用import命令。
101+
102+
#+begin_src txt
103+
root@my-server:/home/user# echo 1 > /sys/module/zfs/parameters/zfs_max_missing_tvds
104+
root@my-server:/home/user# cat /sys/module/zfs/parameters/zfs_max_missing_tvds
105+
1
106+
root@my-server:/home/user# zpool import -o readonly=on pool_name
107+
#+end_src
108+
109+
成功了!因为sdd上分出去的空间不多,大部分数据都还在,赶紧备份数据。但这个pool没法恢复正常了,只能在数据备份后重建存储池,倒腾一下也没有办法。
110+
111+
** 教训
112+
113+
向ZFS池中添加磁盘和替换磁盘是个危险操作,需要清楚执行的命令的后果是什么再执行。至于attach命令是否支持对raidz追加磁盘,原来OpenZFS 2.3版才开始支持这个特性。我的OpenZFS是2.2.x版,还不支持此特性,而我看的是2.3版本的文档。好吧,这个有点伤心,不过我知道怎么去"杀死"一个ZFS存储池。
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
layout: default
3+
title: 如何“杀死”一个ZFS Pool
4+
tags: [ZFS, storage]
5+
nav_order: {{ page.date }}
6+
sync_wexin: 0
7+
---
8+
9+
10+
# 如何“杀死”一个ZFS Pool
11+
12+
13+
## 起因
14+
15+
我家里有一个NAS服务器,存储空间由一个ZFS Pool提供。因为平常只是存一些共享的文档数据,数据增长不快,且ZFS一直工作得很稳定,我也不需要经常折腾这个设备。但是最近我多了一块空闲磁盘,我觉得空放着挺可惜,想将这块磁盘用起来。一个危险的想法就生成了,我想把这个磁盘加到ZFS Pool中去。
16+
17+
18+
## 事件经过
19+
20+
我查了zpool的文章,有个zpool add和zpool attach的命令。我感觉zpool attach应该是追加磁盘的,但是试了几个命令都是失败的。
21+
22+
```txt
23+
root@my-server:/home/user# zpool attach pool_name sdb sdd
24+
invalid vdev specification
25+
use '-f' to override the following errors:
26+
/dev/sdd1 contains a filesystem of type 'ntfs'
27+
root@my-server:/home/user# zpool attach -f pool_name sdb sdd
28+
cannot attach sdd to sdb: no such device in pool
29+
root@my-server:/home/user# zpool attach -f pool_name raidz1-0 sdd
30+
cannot attach sdd to raidz1-0: can only attach to mirrors and top-level disks
31+
```
32+
33+
我的磁盘是sdd,ZFS的报错信息感觉很没有头绪,什么“no such device in pool”,难道我需要先将我的盘加到pool里面么?attach命令不行,不是还有add命令么?我还没有意识到,存储系统是不能随便胡乱操作的,也没有思考失败其实是不支持的缘故。我就执行add命令,这个命令失败了。
34+
35+
```txt
36+
root@my-server:/home/user# zpool add pool_name sdd
37+
invalid vdev specification
38+
use '-f' to override the following errors:
39+
mismatched replication level: pool uses raidz and new vdev is disk
40+
```
41+
42+
我看到了“use '-f' to override the following errors”,但没有理解下面一行的意思。可以用“-f”太好了,加上“-f”果然可以了。查看pool的状态。
43+
44+
```txt
45+
root@my-server:/home/user# zpool status
46+
pool: pool_name
47+
state: ONLINE
48+
status: Some supported and requested features are not enabled on the pool.
49+
The pool can still be used, but some features are unavailable.
50+
action: Enable all features using 'zpool upgrade'. Once this is done,
51+
the pool may no longer be accessible by software that does not support
52+
the features. See zpool-features(7) for details.
53+
scan: scrub repaired 0B in 02:38:28 with 0 errors on Sun Apr 13 03:02:29 2025
54+
config:
55+
56+
NAME STATE READ WRITE CKSUM
57+
pool_name ONLINE 0 0 0
58+
raidz1-0 ONLINE 0 0 0
59+
sdc ONLINE 0 0 0
60+
sde ONLINE 0 0 0
61+
sdb ONLINE 0 0 0
62+
sdd ONLINE 0 0 0
63+
```
64+
65+
sdd已经在pool里了,但是没有加到原来的raid组里。我想sdd已经在pool里了,应该可以使用attach命令了吧。再次执行attach命令。
66+
67+
```txt
68+
root@my-server:/home/user# zpool attach pool_name sdc sdd
69+
/dev/sdd is in use and contains a unknown filesystem.
70+
```
71+
72+
什么意思?难道是因为sdd原来的数据没有清空,事后回过神来才知道这个“a unknown filesystem”是因为sdd已经加到pool里面了。我在错误的道路上继续狂奔,是不是需要用dd将原来的数据清除掉?因为觉得这个sdd是个空闲的盘,觉得不会有什么问题,但其实并不是。我用dd命令把整个盘都写了一遍零。这个时候已经打错特错了。在我重启了服务器之后,啊…,pool不见了。使用“zpool import”命令也失败了。第一次import告诉我sdd是UNAVAIL状态,使用“-f”也不行,最后直接让我重建存储池了,可惜我并没有备份啊。
73+
74+
```txt
75+
root@my-server:/home/user# zpool import
76+
pool: pool_name
77+
id: 16650549184859894038
78+
state: UNAVAIL
79+
status: One or more devices contains corrupted data.
80+
action: The pool cannot be imported due to damaged devices or data.
81+
see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-5E
82+
config:
83+
84+
pool_name UNAVAIL insufficient replicas
85+
raidz1-0 ONLINE
86+
sdc ONLINE
87+
sde ONLINE
88+
sdb ONLINE
89+
sdd UNAVAIL
90+
root@my-server:/home/user# zpool import -f -F pool_name
91+
cannot import 'pool_name': no such pool or dataset
92+
Destroy and re-create the pool from
93+
a backup source.
94+
```
95+
96+
这个时候我已经头皮发麻了。赶紧上网搜索解决方案,原来“zfs add”是给pool增加vdev,这样这个sdd和原来raidz1-0会形成一个raid0的存储池,数据会在两个设备间打散开来。好家伙,这样子整个存储池基本就没有冗余度了,只要sdd挂了,存储池就挂了,而我还来个大杀器。我当时真是欲哭无泪,积攒了十年的数据,好多手机和相机拍的照片,还有很多好看的电影,可能全都没了。
97+
98+
99+
## 一线生机
100+
101+
在我把sdd加到原来的pool之后,并没有写什么数据,原来的数据都应该在之前的几块盘上,我觉得还有恢复数据的可能。我就上网找数据恢复方法,实在不行研究ZFS代码也行。我幸运地找到了一个Github Issue ["Import a pool with missing top-level vdevs"](https://github.com/openzfs/zfs/issues/852)。原来对于这种有顶层的磁盘损坏的pool,ZFS支持采用只读的方式导入。只能试一试了,方法并不复杂。先修改OpenZFS配置项,然后使用import命令。
102+
103+
```txt
104+
root@my-server:/home/user# echo 1 > /sys/module/zfs/parameters/zfs_max_missing_tvds
105+
root@my-server:/home/user# cat /sys/module/zfs/parameters/zfs_max_missing_tvds
106+
1
107+
root@my-server:/home/user# zpool import -o readonly=on pool_name
108+
```
109+
110+
成功了!因为sdd上分出去的空间不多,大部分数据都还在,赶紧备份数据。但这个pool没法恢复正常了,只能在数据备份后重建存储池,倒腾一下也没有办法。
111+
112+
113+
## 教训
114+
115+
向ZFS池中添加磁盘和替换磁盘是个危险操作,需要清楚执行的命令的后果是什么再执行。至于attach命令是否支持对raidz追加磁盘,原来OpenZFS 2.3版才开始支持这个特性。我的OpenZFS是2.2.x版,还不支持此特性,而我看的是2.3版本的文档。好吧,这个有点伤心,不过我知道怎么去"杀死"一个ZFS存储池。

0 commit comments

Comments
 (0)