Step by Step: LVM RAID logical volumeでソフトウェアRAID 1 (Fedora 33)

(2014.11)

Red Hat Enterprise Linux 6.3から, LVM がRAID logical volumeをサポートした。RHEL7 (Fedora 18~19相当) でも、サポートされている。RAID logical volume機能は, LV (=ファイルシステム) を複数の物理ディスクにミラーして配置できる。

/bootについては LVM化できないが、それ以外の領域については、全部をLVMに載せることで冗長性と柔軟性を得ることができる。

できあがりイメージはこんな感じ。

Volume Group (VG) を、物理ディスクをまたいで一つだけ作る。その上でミラー化された RAID logical volumeを作る。

swap領域は、ミラーリングしなくていいので、別々のLV にすればOK.

/boot については, mdカーネルドライバを使って RAID 1構成にする。その手順はこちら; Step by Step: シングルHDDをRAID 1に変換; LVM on RAID編 (Fedora 20)

注意!

parted は、コマンドを打つたびにディスクに書き込む。途中で取消しが効かない。

LVM で RAIDを組む場合, LV の "外側" にメタデータを置く領域が必要。LV を PV とピッタリの大きさで作ると詰む。特に XFS ファイルシステムは切り詰めることができないので、作り直しになる。

Step by Step

[[注意]] 私(堀川)の手元の環境ではできましたが、同じことをしても失敗するリスクがあります。データを失ったとしても,私は責任を負えません。事前に必ず, データをバックアップしてください。

1. 現況

lvsコマンドで現況を表示。-o オプションで表示する列を指定。

大きさについては, 何もオプションを指定しないと g (ギガ) / t (テラ) が自動で付く。--units g などとすると単位が揃う。大きさの単位が小文字のときは 1,024が基数, --units G などと大文字を与えると 1,000が基数になる. 1024基数のほうは MiB/GiB とも呼ばれる。

# lvs -a -o vg_name,name,copy_percent,devices,size
  VG      LV      Copy%  Devices         LSize 
  vg_mypc lv_home        /dev/sda2(186)  92.69g
  vg_mypc lv_root        /dev/sda2(3152) 50.00g
  vg_mypc lv_swap        /dev/sda2(0)     5.81g

LVについて表示したときに、どの物理ディスクに置かれているかが透けて見える。

いったん PCの電源を切り、HDD を追加する。新しいドライヴの場合は, cfdisk などで, 必要なパーティションを切る。

2. 新しいドライヴの場合, partition を切る

[2021-01] 2TB 超えで parted コマンドを使うように書き換えた。

2TB を超えるドライヴの場合は, GPT にしなければならない。partedgdisk コマンドを使う。

parted は途中で取消しが効かないので、別のドライヴと取り違えないよう、入ったら必ず print して確認すること! gdiskfdisk に似て, 抜けるときに書き込む。

# parted /dev/sdc
GNU Parted 3.3
/dev/sdc を使用
GNU Parted へようこそ! コマンド一覧を見るには 'help' と入力してください。
(parted) print
Error: /dev/sdc: unrecognised disk label
Model: ATA ST4000VN008-2DR1 (scsi)                                        
Disk /dev/sdc: 4001GB
Sector size (logical/physical): 512B/4096B
Partition Table: unknown
Disk Flags: 

新品なら, 単純に, 1台目と2台目とでまったく同じに作る。

mklabel gpt で GPT にする (他方は msdos)。GPT の場合は MBR がないので、先頭に grub 用の領域が必要。

mkpart コマンドでパーティションを切る。引数は名前, 開始位置, 終了位置. ※msdos にした場合は引数が異なる。ほかの解説ページではゴッチャになっていることも。

大きさは mb などとすると1000が基数で, 1024基数にするには mib などとする。

(parted) mkpart grub 1mib 3mib
(parted) set 1 bios_grub on   
(parted) mkpart boot 4mib 500mib
(parted) set 2 boot on

終了位置に -1 のようにマイナス値を指定すると、後ろから数える。-1 で最後までピッタリ。

(parted) mkpart rootfs 501mib -1
(parted) set 3 lvm on

確認。

(parted) print
Model: ATA ST4000VN008-2DR1 (scsi)
Disk /dev/sdc: 4001GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name     Flags
 1      1049kB  3146kB  2098kB               grub     bios_grub
 2      4194kB  524MB   520MB                boot     boot, esp
 3      525MB   4001GB  4000GB               rootfs   lvm

名前はただの区別のため何でもよい。名前を変えるには name 2 boot のようにする。

quit で抜ける。

3. 新しい1台目のドライヴ

RAID構成にするドライヴが2台とも新しい場合, 新しくVG (Volume Group) を作る。既存のドライヴ構成に HDD を追加した場合は, 既存の VG に新しいドライヴを追加する。

新しく VG を作るには vgcreate コマンド。--test オプションを付けると実行しない。確認したうえで --test を外して実行。

少なくとも一つ, PVが必要。

~# vgcreate --verbose vg_orange3 /dev/sdc3
  Wiping signatures on new PV /dev/sdc3.
  Adding physical volume '/dev/sdc3' to volume group 'vg_orange3'
  Archiving volume group "vg_orange3" metadata (seqno 0).
  Creating volume group backup "/etc/lvm/backup/vg_orange3" (seqno 1).
  Volume group "vg_orange3" successfully created

vgdisplay コマンドで確認。

PE Size (Physical Extent size) 4.00 MiBで作られた。以前のは 32.00 MiBだった。PE size の異なる VG は合体できない。

次に, LV を作っていく。将来、こちらから boot するかもしれないので, root, swap, home と3つ作る。

lvcreate コマンドの引数として VolGrpName PhysicalVolName として, PVを指定することもできる。PV を指定しない場合は適当に選ばれる。

~# lvcreate vg_orange3 --size 50g --name lv3_root
  Logical volume "lv3_root" created.
~# lvcreate vg_orange3 --size 4g --name lv3_swap
  Logical volume "lv3_swap" created.

とりあえずピッタリで作る。--extents Number[PERCENT] オプションで指定。

~# lvcreate vg_orange3 -v --extents 100%FREE --name lv3_home
  Converted 100% of FREE (939912) extents into 939912 (with mimages 1 and stripes 1 for segtype striped).
  Archiving volume group "vg_orange3" metadata (seqno 3).
  Creating logical volume lv3_home
  Creating volume group backup "/etc/lvm/backup/vg_orange3" (seqno 4).
  Activating logical volume vg_orange3/lv3_home.
  activation/volume_list configuration setting not defined: Checking only host tags for vg_orange3/lv3_home.
  Creating vg_orange3-lv3_home
  Loading table for vg_orange3-lv3_home (253:7).
  Resuming vg_orange3-lv3_home (253:7).
  Wiping known signatures on logical volume vg_orange3/lv3_home.
  Initializing 4.00 KiB of logical volume vg_orange3/lv3_home with value 0.
  Logical volume "lv3_home" created.

実際のファイルシステムが格納される領域の外側で, metadata subvolume をデヴァイスに格納できるよう, ここで LV を縮めておく <- ★これが重要!! 下の例では 1GB 縮めているが、こんなに縮めなくてよい。1メタデータサブヴォリューム当たり1エクステント(=4 MiB) で十分。後ろの手順で, lv3_home_rmeta_0, lv3_home_rmeta_1 の2つが作られる。

~# lvreduce -v --size -1g vg_orange3/lv3_home
  WARNING: Reducing active logical volume to 3.58 TiB.
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce vg_orange3/lv3_home? [y/n]: y
  Accepted input: [y]
  Archiving volume group "vg_orange3" metadata (seqno 4).
  Reducing logical volume vg_orange3/lv3_home to 3.58 TiB
  Size of logical volume vg_orange3/lv3_home changed from <3.59 TiB (939912 extents) to 3.58 TiB (939656 extents).
  Loading table for vg_orange3-lv3_home (253:7).
  Suspending vg_orange3-lv3_home (253:7) with device flush
  Resuming vg_orange3-lv3_home (253:7).
  Creating volume group backup "/etc/lvm/backup/vg_orange3" (seqno 5).
  Logical volume vg_orange3/lv3_home successfully resized.

フォーマット。ファイルシステムはLVと同じ大きさ。

~# mkfs.xfs /dev/mapper/vg_orange3-lv3_home
meta-data=/dev/mapper/vg_orange3-lv3_home isize=512    agcount=4, agsize=240551936 blks
         =                       sectsz=4096  attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=962207744, imaxpct=5
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=469828, version=2
         =                       sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

swap領域のフォーマットは mkswap コマンド

4-1. 新しい2台目のドライヴを追加の場合: VGに追加

既存の VG に新しい物理デヴァイスを追加する場合は、新しいドライヴはパーティションを切るだけ。

~# vgextend vg_orange3 /dev/sdd3
  Volume group "vg_orange3" successfully extended

2台目のほうには, わざわざ LV はつくらない。(1台目のLVをミラーするので)

4-2. フォーマット済みのドライヴを追加の場合: VGを合体

新しく接続したHDDにすでにPV, VGがあった場合、VGを一つに統合する。

一つのVG上で LV 名が被ってはいけないので、RAID化しない生かす LVは名前を変える。

vgchangeコマンドで、アクティブ/非アクティブの切替え。-a nオプションで非アクティブにする。

# vgchange -a n vg_newhdd

lvrenameコマンドで, LVの名前変更. 例えば, 'root' LVが被っているとして, root2に変更。

いらないLVなら lvremove で単に削除してもOK.

# lvrename vg_newhdd lv_root lv_root2

vgmergeコマンドで, VGを連結して一つにする。コマンド引数は, dest srcの順。

# vgmerge -v vg_mypc vg_newhdd
    Checking for volume group "vg_newhdd"
    Checking for volume group "vg_mypc"
  Extent sizes differ: 65536 (vg_mypc) and 8192 (vg_newhdd)

上のケースは失敗. 単一のVGには異なる大きさの物理エクステント (Physical Extent; PE) を混ぜることができない.

物理エクステントは, (PV/物理デヴァイスではなく) VGの属性で, VGの大きさの単位.

vgdisplayコマンドでPE sizeを確認できる. vgchange コマンドでPE sizeを変更できることになっているが、実際には成功しない.

この場合は, VGを作りなおすしかない. 当然, そのVG上のLV, データはすべて失われる. vgremove コマンドで VGを削除し, vgextend コマンドで VGに PVを追加する.

話を戻して, vgmerge コマンドが成功したら, 新しいHDDのほうの不要なLVを削除。

# lvremove vg_mypc/lv_root2

5. いよいよ RAIDデバイスに変換

Linear LV (RAIDでないLV) を, lvconvertコマンドで RAIDデバイスに変換する.

--type オプション... linear | striped | mirror | raidn n はraidレベル | thin | cache | thin-pool | cache-pool | vdo-pool | snapshot

-mオプション (--mirrors) ... ミラーの数. -m 1 だと 2-sides.

# lvconvert -v --type raid1 -m 1 vg_mypc/lv_root
    Executing: /usr/sbin/modprobe dm-raid
    Archiving volume group "vg_mypc" metadata (seqno 6).
  Insufficient free space: 1 extents needed, but only 0 available

おや? 空き領域はあるのに。

理由: LVの領域のほかに metadataの領域が必要。VGに metadata分の空きがない場合, LVを縮めてやる必要がある。

metadata は 4MB~32MBぐらいあればいい。

LVを切り詰める

VGにmetadata分の空きがあれば、当然, このステップは不要。ファイルシステムがXFSだと, どうしようもない。xfsdump & xfsrestore しかない。

コラム: 各ファイルシステムが拡張・縮小可能か

Fedora 32 では, ファイルシステムは次のいずれか。Btrfs はLVM上に載せる意味がない (Btrfs側がRAID機能も持つ)。ReiserFS ははるか昔に選択肢から外れた.

Red Hat Enterprise Linux 8 だと, XFS, ext4, GFS2, および XFS+LVM 上の Stratis ボリュームマネジャー.

File system サイズ変更可能?
拡張 縮小
ext4 on-line resize2fs ※1 off-line resize2fs
ext3 on-line resize2fs ※1 off-line resize2fs
XFS on-line xfs_growfs 不能(!)

※1 ext3, ext4 のオンラインでの大きさ変更は, ファイルシステムの feature として resize_inode が有効になっている場合。普通は有効になっている。tune2fs -l で表示できる。

resize2fsコマンドはパーティションの大きさは変更しない。まず lvextend してから実行する。というか lvextend コマンドの --resizefs オプションで, LVの大きさ変更の際に, 同時にファイルシステムの大きさ変更が可能。これで一発で変更するのがよい。対応ファイルシステムは ext2, ext3, ext4, ReiserFS と XFS.

Root LVを縮めたいときは, GParted などのLive CDでブートして操作する。

ファイルシステムをアンマウントする.

# umount /home

逆に, Live CDでブートしたときは, LVが有効になっていないので、LVを有効にする。

$ sudo lvchange -a y /dev/vg_mypc/root

いずれの場合も, ファイルチェックを必ずおこなっておく。

# fsck.ext4 -f /dev/mapper/vg_mypc-lv_home

LVの上に載っているファイルシステムを縮める. 最後の引数が大きさ。下の例だと, 150Gにする。resize2fs に与える大きさは, 常に 1024が基数.

# resize2fs /dev/mapper/vg_mypc-lv_home 150G

その後、LVを縮める。このとき, LVは非アクティブでなければならない.

# lvreduce -L 150g /dev/mapper/vg_mypc-lv_home

再マウント。

# mount -t ext4 /dev/mapper/... /home

進捗

領域を空けてから lvconvert したら, 今度は成功。

~# lvconvert -v --type raid1 --mirrors 1 vg_orange3/lv3_home
  Executing: /usr/sbin/modprobe dm-raid
Are you sure you want to convert linear LV vg_orange3/lv3_home to raid1 with 2 images enhancing resilience? [y/n]: y
  Accepted input: [y]
  Archiving volume group "vg_orange3" metadata (seqno 6).
  Creating logical volume lv3_home_rmeta_0
  Creating logical volume lv3_home_rmeta_1
  Creating logical volume lv3_home_rimage_0
  activation/volume_list configuration setting not defined: Checking only host tags for vg_orange3/lv3_home_rmeta_0.
  Creating vg_orange3-lv3_home_rmeta_0
  Loading table for vg_orange3-lv3_home_rmeta_0 (253:5).
  Resuming vg_orange3-lv3_home_rmeta_0 (253:5).
  activation/volume_list configuration setting not defined: Checking only host tags for vg_orange3/lv3_home_rmeta_1.
  Creating vg_orange3-lv3_home_rmeta_1
  Loading table for vg_orange3-lv3_home_rmeta_1 (253:6).
  Resuming vg_orange3-lv3_home_rmeta_1 (253:6).
  Initializing 4.00 KiB of logical volume vg_orange3/lv3_home_rmeta_0 with value 0.
  Initializing 4.00 KiB of logical volume vg_orange3/lv3_home_rmeta_1 with value 0.
  Removing vg_orange3-lv3_home_rmeta_0 (253:5)
  Removing vg_orange3-lv3_home_rmeta_1 (253:6)
  Creating logical volume lv3_home_rimage_0
  Creating vg_orange3-lv3_home_rmeta_0
  Loading table for vg_orange3-lv3_home_rmeta_0 (253:5).
  Resuming vg_orange3-lv3_home_rmeta_0 (253:5).
  Creating vg_orange3-lv3_home_rimage_0
  Loading table for vg_orange3-lv3_home_rimage_0 (253:6).
  Resuming vg_orange3-lv3_home_rimage_0 (253:6).
  Creating vg_orange3-lv3_home_rmeta_1
  Loading table for vg_orange3-lv3_home_rmeta_1 (253:7).
  Resuming vg_orange3-lv3_home_rmeta_1 (253:7).
  Creating vg_orange3-lv3_home_rimage_1
  Loading table for vg_orange3-lv3_home_rimage_1 (253:8).
  Resuming vg_orange3-lv3_home_rimage_1 (253:8).
  Loading table for vg_orange3-lv3_home (253:4).
  Suspending vg_orange3-lv3_home (253:4) with device flush
  Loading table for vg_orange3-lv3_home_rmeta_0 (253:5).
  Suppressed vg_orange3-lv3_home_rmeta_0 (253:5) identical table reload.
  Loading table for vg_orange3-lv3_home_rimage_0 (253:6).
  Suppressed vg_orange3-lv3_home_rimage_0 (253:6) identical table reload.
  Loading table for vg_orange3-lv3_home_rmeta_1 (253:7).
  Suppressed vg_orange3-lv3_home_rmeta_1 (253:7) identical table reload.
  Loading table for vg_orange3-lv3_home_rimage_1 (253:8).
  Suppressed vg_orange3-lv3_home_rimage_1 (253:8) identical table reload.
  Resuming vg_orange3-lv3_home (253:4).
  Monitored LVM-hW3uxpJvh3cRCavkXORcLXwSpBO53RNHVqdOSDq4o6wPYwqF7Zeybvzazy8CX6W3 for events
  Creating volume group backup "/etc/lvm/backup/vg_orange3" (seqno 8).
  Creating volume group backup "/etc/lvm/backup/vg_orange3" (seqno 9).
  Logical volume vg_orange3/lv3_home successfully converted.

すぐに完了が返ってくるが, 裏でミラーリングが進行する。lvs コマンドで進捗を見れる。

# watch lvs -a -o vg_name,name,copy_percent,devices,size

Cpy%Sync が増加していくことが分かる。

Trouble shooting

(2014.12.10)

Fedora 20では上に書いた手順でよかったが, 別の機械のFedora 19で同じようにしたところ、ミラー化後の再起動時に, Dracut emergency modeに落ちてしまった。

ここから大嵌まり。

  • /boot はミラー化せず。
  • / (root), /home は、LVM上にあり、両方ともミラー化した。

ミラー化は成功。しかし、/bootをMD RAID化していなかったため、initramfsに明示的にMDカーネルドライバを組込むのを失念していた。

LVM logical volumeでは, MDカーネルドライバを使っている。

Fedora 19では, Fedora 20とは違い, デフォルトでは組込まれないようだ。

こういう状況で、GRUB2から /boot上ののinitramfsを読み込むところまでは動くが、initramfsにMDカーネルドライバが含まれておらず、刺さった。

金庫の鍵が金庫の中状態。

どうするか。

1) インストールディスクでbootして、LVMを認識させる。

とにかく、LVMを認識できれば、後は何とかなる。

2) どこかのディレクトリ以下に各LVをmountして, ディレクトリツリーを再現する。

chrootしたうえで、dracutコマンドで initramfs を再作成。

dracutコマンドでinitramfsを作りなおしてもうまくいかなかった場合は, きちんとLVMが認識できている状態で, kernelのアップデートを行えばいい。アップデート中に, initramfsが裏で作成される。

dracut に与えるオプションが違うのだろうか。

(1) kernel module

/etc/modules.conf ファイルは, もはやない。insmod コマンドも古い.

今は modprobe コマンドを使う。

# /usr/sbin/modprobe dm-raid

名前が紛らわしいが, MDではなく dmやね.

どのカーネルモジュールがインストールされているかは lsmod コマンド。

lsinitrd コマンドで, initramfsファイルの内容を見れる。

usr/lib/modules/<kernel version>/kernel/drivers/md/dm-raid.ko が含まれるかどうかを確認する。

(2) LVM

/etc/sysconfig/lvm という設定ファイルも, もはやない。

/etc/lvm/lvm.conf ファイルに設定がある。

(3) LVが自動認識されない

dracut shellにて,

# vgscan
# vgchange -a y
# blkid
# ln -s /dev/mapper/luks-$UUID /dev/root
# exit

exit コマンドで, bootが再開される。/dev/root が dracutから抜けたときに root になる.

はずだが、今回の件では, root が認識できなかったので, dracut shell でvgscanコマンドなどが実行できなかった。

インストールディスクから boot すればよい。

(4) initramfs を作り直す

動いている状態で,

# dracut /boot/initramfs-raid.img 3.17.3

/etc/dracut.conf ファイルが設定ファイル