この度、RAID1のmd上のファイルシステムをオンラインで拡張したので、備忘録を残しておきます。
前提
- 環境はArchLinux、SATA上の6TBHDD2台でmdadmを使い、RAID1を組んでいます。
- 筆者の環境では、mdデバイス上に複数のパーティションを切るのではなく、物理ディスク2台に同じサイズの複数のパーティションを切って、複数のmdデバイスを作っています。
- もし一つの大きなmdデバイス上に複数のパーティションを切りたい場合は、LVMを活用することで拡張性を確保する設計にすることをおすすめします。
- 一つの大きなmdデバイス上に複数のパーティションを切っており、内側からパーティションを拡張したい場合は、1台のHDDのパーティション用の手順を参考に出来ると思いますので、探してみてください。多分GParted等を使う手順が見つかります。
- 当たり前ですが、ディスクに空きがあることを前提としています。空きがない場合はディスクを買い直すなり追加するなりしてください。
発端
容量不足の顕在化
当初からvarは10GB、homeは100GBと現代のメインマシンとしては少々小さめで、正直ちょっとしんどい感じではあったものの、あまりハードは使い方はしないので特に問題はありませんでした。
しかし、この度とあるゲームをインストールしようとしたところ、40GBほど求められ、一瞬で詰んだので、致し方なくめんどくさいながらパーティションを切り直すことにしました。
計画
コンセプト
- /varは2倍、/homeは3倍、/shareは2倍にする
- めんどくさいのは嫌だ!
- なのでバックアップは取らないしシングルユーザモードもやだ!
- でも安全を期したい
- お参りは済ませているしお守りも完備している
現状
メインマシンはArch Linuxで、/はNVMeのSSD上、/var、/home、/home/share(ファイルサーバ領域)がHDDのRAID1上にあります。
今回、/homeの拡張が必要になりましたが、この際RAID1上のパーティションをまとめて拡張したいと思います。
課題
RAID1を使っている場合、容量を増やそうと思うと、通常のパーティション拡張と違い、かなり手順が面倒です。
1.RAID1の2台のHDDの内、1台を切り離す。
2.切り離したHDDのパーティションを切り直す。
3、切り離したHDDをRAID1に復帰する。
4、同期させる。
5、もう1台のHDDを切り離す。
6、以下2〜4を繰り返し
とてもめんどくさそうです。。。
実施
まず現状を把握する
// デバイス状況
$ ls -l /dev/disk/by-uuid/
lrwxrwxrwx 1 root root 10 Mar 20 11:02 xxxxxxxxxxxx -> ../../sdb1
lrwxrwxrwx 1 root root 9 Mar 20 11:02 xxxxxxxxxxxx -> ../../md1
lrwxrwxrwx 1 root root 9 Mar 20 11:02 xxxxxxxxxxxx -> ../../md0
lrwxrwxrwx 1 root root 15 Mar 20 11:02 xxxxxxxxxxxx -> ../../nvme0n1p2
lrwxrwxrwx 1 root root 9 Mar 20 11:02 xxxxxxxxxxxx -> ../../md2
lrwxrwxrwx 1 root root 15 Mar 20 11:02 xxxxxxxxxxxx -> ../../nvme0n1p1
lrwxrwxrwx 1 root root 10 Mar 20 11:02 xxxxxxxxxxxx -> ../../sda1
// sda1とsdb1はswapにあてています。
// 物理パーティション
# parted -a opt /dev/sda
(parted) u MiB
(parted) p
Number Start End Size File system Name Flags
1 1.00MiB 32769MiB 32768MiB linux-swap(v1) swap
2 32769MiB 43009MiB 10240MiB var1 raid
3 43009MiB 145409MiB 102400MiB home1 raid
4 145409MiB 1193985MiB 1048576MiB share1 raid
(parted) q
# parted -a opt /dev/sdb
(parted) u MiB
(parted) p
Number Start End Size File system Name Flags
1 1.00MiB 32769MiB 32768MiB linux-swap(v1) swap
2 32769MiB 43009MiB 10240MiB var2 raid
3 43009MiB 145409MiB 102400MiB home2 raid
4 145409MiB 1193985MiB 1048576MiB share2 raid
(parted) q
//mdデバイス
$ cat /proc/mdstat
md0 : active raid1 sdb2[1] sda2[0]
10476544 blocks super 1.2 [2/2] [UU]
md2 : active raid1 sda4[0] sdb4[1]
1073609728 blocks super 1.2 [2/2] [UU]
bitmap: 0/8 pages [0KB], 65536KB chunk
md1 : active raid1 sda3[0] sdb3[1]
104791040 blocks super 1.2 [2/2] [UU]
# mdadm --detail --scan
ARRAY /dev/md2 metadata=1.2 name=myhost:2 UUID=xxxxxxxxxxxxxxxx
ARRAY /dev/md1 metadata=1.2 name=myhost:1 UUID=xxxxxxxxxxxxxxxx
ARRAY /dev/md0 metadata=1.2 name=myhost:0 UUID=xxxxxxxxxxxxxxxx
//ファイルシステム
$ mount
/dev/nvme0n1p2 on / type ext4 (rw,noatime)
/dev/nvme0n1p1 on /boot type vfat (rw,noatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro)
/dev/md0 on /var type ext4 (rw,noatime)
/dev/md1 on /home type ext4 (rw,noatime)
/dev/md2 on /home/share type ext4 (rw,noatime)
// 大分はしょってます。
今回、拡張したいのはmd0、md1、md2で、それぞれsda/bの2,3,4番のパーティションで構成されています。
RAIDのチェック
RAIDの状態をチェックし、実はエラーがあって復旧出来なかった、みたいな惨事を出来うる限り避けます。
// かなり時間がかかりますので、本を読むなり用事を片付けるなりしておくとよいと思います。
# echo check > /sys/block/md0/md/sync_action
# echo check > /sys/block/md1/md/sync_action
# echo check > /sys/block/md2/md/sync_action
RAIDの解除
満を持してRAIDを解除します。
今回は副ボリューム(sdb側)から切り離します。
# mdadm --manage /dev/md0 --fail /dev/sdb2
# mdadm --manage /dev/md1 --fail /dev/sdb3
# mdadm --manage /dev/md2 --fail /dev/sdb4
# cat /proc/mdstat // 間違ってない事を確認
# mdadm --manage /dev/md0 --remove /dev/sdb2
# mdadm --manage /dev/md1 --remove /dev/sdb3
# mdadm --manage /dev/md2 --remove /dev/sdb4
# cat /proc/mdstat // RAIDから切り離されたことを確認
superblockの削除
これをやっておかないとパーティションが作り直せませんので、必ず実行しておいてください。
実施前に深呼吸して対象パーティションが間違っていないことを確認してください。
mdadm --misc --zero-superblock /dev/sdb2 /dev/sdb3 /dev/sdb4
パーティションの再作成
切り離した方のディスクのパーティションを切り直します。
こちらは間違えると多分エラーが出ますが、やはり深呼吸してからのほうが良いかと思います。
# parted -a opt /dev/sdb
(parted) u MiB
(parted) p
1 1.00MiB 32769MiB 32768MiB linux-swap(v1) swap
2 32769MiB 43009MiB 10240MiB var2 raid
3 43009MiB 145409MiB 102400MiB home2 raid
4 145409MiB 1193985MiB 1048576MiB share2 raid
(parted) rm 2
(parted) rm 3
(parted) rm 4
(parted) mkpart PRIMARY 32769 53249
(parted) mkpart PRIMARY 53249 360449
(parted) mkpart PRIMARY 360449 2457601
(parted) name 2 var2
(parted) name 3 home2
(parted) name 4 share2
(parted) toggle 2 raid
(parted) toggle 3 raid
(parted) toggle 4 raid
(parted) p
1 1.00MiB 32769MiB 32768MiB linux-swap(v1) swap
2 32769MiB 53249MiB 20480MiB var2 raid
3 53249MiB 360449MiB 307200MiB home2 raid
4 360449MiB 2457601MiB 2097152MiB share2 raid
(parted) q
パーティションが無事拡張されました。
RAIDの回復
これも相当時間がかかります。同期完了までの間は冗長性がありませんのでおすすめはしませんが、電源をオフすることも可能です。
電源オンすると自動的に同期が再開します。
mdadm --manage /dev/md0 --add /dev/sdb2
mdadm --manage /dev/md1 --add /dev/sdb3
mdadm --manage /dev/md2 --add /dev/sdb4
下記コマンドで進捗状況を監視することが可能です。
$ watch cat /proc/mdstat
同期速度を上げたい場合は、こんなふうにパラメータをいじれます。(単位はKB/S)
# echo 400000 >/proc/sys/dev/raid/speed_limit_max
終わったらctrl-cで終了します。
反対側ディスクでRAID解除からRAID回復までを実施
mdデバイスは最小のパーティションに合わせたサイズになりますので、現状ではまだボリュームのサイズは変わっていません。
上記の例では/dev/sdb側からやったので、同じ操作を今度は/dev/sda側でやります。
結局めんどくさいじゃないか、と言われそうですが、多分これ以上は無理なので許してください。
以下デバイス違いの同じ手順なので省略
RAIDボリュームの拡張
ここまで来てやっとRAIDボリュームが拡張出来ます。
# mdadm --grow /dev/md0 --size=max
# mdadm --grow /dev/md1 --size=max
# mdadm --grow /dev/md2 --size=max
ファイルシステムの拡張
ここまで来たらあと一歩、と言いたいところですが、実は拡張したパーティションに対しても再同期が走るので、結構時間がかかります。
前の再同期と同様、電源オフすることも可能です。冗長性はありませんが、夜中遅くて耐えられない人は電源オフして寝るのも一手です。
resize2fs /dev/md2
resize2fs /dev/md1
resize2fs /dev/md0
進捗状況を眺めたい人は前と同様下記で眺められます。
$ watch cat /proc/mdstat
事後確認
お疲れ様でした。ここまでエラーなく終わっていたら、目的が達成されているはずですが、念の為状況を確認しておきましょう。
$ ls -l /dev/disk/by-uuid/
lrwxrwxrwx 1 root root 10 Mar 20 11:02 xxxxxxxxxxxx -> ../../sdb1
lrwxrwxrwx 1 root root 9 Mar 20 11:02 xxxxxxxxxxxx -> ../../md1
lrwxrwxrwx 1 root root 9 Mar 20 11:02 xxxxxxxxxxxx -> ../../md0
lrwxrwxrwx 1 root root 15 Mar 20 11:02 xxxxxxxxxxxx -> ../../nvme0n1p2
lrwxrwxrwx 1 root root 9 Mar 20 11:02 xxxxxxxxxxxx -> ../../md2
lrwxrwxrwx 1 root root 15 Mar 20 11:02 xxxxxxxxxxxx -> ../../nvme0n1p1
lrwxrwxrwx 1 root root 10 Mar 20 11:02 xxxxxxxxxxxx -> ../../sda1
// うまくいっていれば何も変わっていないはずです。
$ cat /proc/mdstat
md0 : active raid1 sda2[3] sdb2[2]
20962304 blocks super 1.2 [2/2] [UU]
md2 : active raid1 sda4[3] sdb4[2]
2147351552 blocks super 1.2 [2/2] [UU]
bitmap: 2/8 pages [8KB], 131072KB chunk
md1 : active raid1 sda3[3] sdb3[2]
314506240 blocks super 1.2 [2/2] [UU]
# mdadm --detail --scan
ARRAY /dev/md2 metadata=1.2 name=myhost:2 UUID=xxxxxxxxxxxxxxxx
ARRAY /dev/md1 metadata=1.2 name=myhost:1 UUID=xxxxxxxxxxxxxxxx
ARRAY /dev/md0 metadata=1.2 name=myhost:0 UUID=xxxxxxxxxxxxxxxx
// うまくいっていれば何も(略
$ mount
/dev/nvme0n1p2 on / type ext4 (rw,noatime)
/dev/nvme0n1p1 on /boot type vfat (rw,noatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro)
/dev/md0 on /var type ext4 (rw,noatime)
/dev/md1 on /home type ext4 (rw,noatime)
/dev/md2 on /home/share type ext4 (rw,noatime)
// うまくいって(ry
終わりに
大体半日くらいの作業でした。
まあ思ったよりは楽だったかな、ということで、一応記録を残しておきます。
なお、今回mdデバイス上にパーティションを切らず、物理パーティション上にmdデバイスを切っているので、動的な拡張が出来ましたが、もしこれがmdデバイス上にパーティションを切る形だとこの作業は出来なかったと思います。