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