RHEL 中級 #2 LVM — PV/VG/LV、スナップショット、拡張
基礎 #6 の自動パーティショニングで出会った /dev/mapper/rhel-root が LVM でした。この記事ではその LVM を直接扱ってみます。PV / VG / LV の構造をまず押さえ、新しいディスクを付けて LV を拡張するフロー、スナップショットでバックアップ直前の状態を捕まえる方法、そして thin provisioning と RAID オプションまで順番に整理します。運用でディスクを柔軟に扱う方法を整理する記事です。
RHEL 中級 シリーズでこの記事の位置:
- #1 SELinux 入門 — Enforcing/Permissive、ラベル、トラブルシューティング
- #2 LVM — PV/VG/LV、スナップショット、拡張 ← この記事
- #3 ストレージ深化 — Stratis、NFS、Samba
- #4 ネットワーキング — NetworkManager (nmcli)、bonding、teaming
- #5 ログ管理 — journald、rsyslog、log rotation
- #6 ジョブスケジューリング — cron、systemd timer、at
- #7 コンテナ入門 — Podman/Buildah/Skopeo (Docker との違い)
LVM が解く問題 #
伝統的なパーティションは一度切ったらサイズが固定されます。/home がいっぱいなのに /var は空いていたら? ディスクを丸ごとバックアップし、パーティションテーブルを引き直し、復元するという大きな作業が必要です。運用マシンはその間止めなければなりません。
LVM (Logical Volume Manager) は 物理ディスクとファイルシステムの間にもう 1 層挟むことで この限界を解きます。ディスクがいっぱいになったら新しいディスクを 1 枚追加し、コマンド 2、3 行で LV を伸ばし、ファイルシステムをそのまま拡張します。ダウンタイムなしで。
/dev/sdb1 /dev/sdc1 /dev/sdd1 ← 物理パーティション
│ │ │
▼ ▼ ▼
[PV] [PV] [PV] ← Physical Volume
└───────────┼───────────┘
▼
┌─────────────┐
│ VG │ ← Volume Group (プール)
│ data_vg │
└──┬───┬───┬──┘
│ │ │
▼ ▼ ▼
[LV] [LV] [LV] ← Logical Volume
│ │ │
▼ ▼ ▼
xfs ext4 swap ← ファイルシステム / swap
│ │
▼ ▼
/data /home3 層の役割:
| 層 | 略称 | 意味 |
|---|---|---|
| Physical Volume | PV | ディスク / パーティション 1 枚を LVM 用にマークしたもの |
| Volume Group | VG | PV 複数枚をまとめたプール。「使用可能なストレージプール」 |
| Logical Volume | LV | VG から切り出した論理ボリューム。ここにファイルシステムを乗せる |
要は VG が抽象化レイヤー だということ。VG の総容量は PV の合計で、LV はその中で自由に切って使い、ディスクを追加すれば VG が大きくなり、LV を伸ばせばそこから持ってきます。
直接作ってみる — PV → VG → LV #
基礎 #6 で追加した空のディスク /dev/vdb を LVM で改めて扱ってみます。
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
vda ... 40G 0 disk
├─vda1 ...
└─vda2 ...
├─rhel-root ...
└─rhel-swap ...
vdb 252:16 0 20G 0 disk ← 空のディスク 1 枚1) PV 作成 — pvcreate
#
$ sudo pvcreate /dev/vdb
Physical volume "/dev/vdb" successfully created.
$ sudo pvs
PV VG Fmt Attr PSize PFree
/dev/vda2 rhel lvm2 a-- 39.00g 0
/dev/vdb lvm2 --- 20.00g 20.00gpvs は PV の 1 行サマリ、もっと詳しく見るなら pvdisplay /dev/vdb。ディスクを丸ごと PV にしましたが、パーティション単位でも可能です (pvcreate /dev/vdb1)。
2) VG 作成 — vgcreate
#
$ sudo vgcreate data_vg /dev/vdb
Volume group "data_vg" successfully created
$ sudo vgs
VG #PV #LV #SN Attr VSize VFree
data_vg 1 0 0 wz--n- <20.00g <20.00g
rhel 1 2 0 wz--n- <39.00g 0data_vg という名前の新しい VG ができ、PV を 1 枚 (/dev/vdb) 抱えています。命名は自由ですが、用途が見える名前 (data_vg、app_vg、db_vg) が運用には良いです。
3) LV 作成 — lvcreate
#
VG から LV を切り出します。一部だけ、あるいは全部を。
# 10GB の LV を 1 つ
$ sudo lvcreate -L 10G -n data_lv data_vg
Logical volume "data_lv" created.
$ sudo lvs
LV VG Attr LSize ...
data_lv data_vg -wi-a----- 10.00g
home rhel -wi-ao---- <10.00g
root rhel -wi-ao---- 25.00g
swap rhel -wi-ao---- 4.00gオプションの読み方:
-L 10G— 絶対サイズ。-l 100%FREEで VG の残り全部、-l 50%VGで VG 全体の 50% といった比率指定も可能。-n data_lv— LV 名。- 末尾の
data_vg— どの VG から切り出すか。
4) ファイルシステムを作ってマウント #
LV は通常のブロックデバイスのように /dev/<VG>/<LV> または /dev/mapper/<VG>-<LV> でアクセスします。
$ sudo mkfs.xfs /dev/data_vg/data_lv
$ sudo mkdir -p /data
$ sudo mount /dev/data_vg/data_lv /data
$ df -hT /data
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/data_vg-data_lv xfs 10G 175M 10G 1% /data基礎 #6 のフローと同様に /etc/fstab に UUID で永続登録します:
$ sudo blkid /dev/data_vg/data_lv
/dev/mapper/data_vg-data_lv: UUID="..." TYPE="xfs"UUID=... /data xfs defaults,nofail 0 0ここまでが 新しいディスクを LVM で運用する標準フロー です。一度覚えておけば同じパターンが繰り返されます。
LV 拡張 — 運用の日常 #
LVM の本当の価値はここで出てきます。/data が 80% 埋まったとしましょう。
1) 新しい PV を追加 #
新しいディスク /dev/vdc (10GB) をマシンに付けたとします。
$ sudo pvcreate /dev/vdc
Physical volume "/dev/vdc" successfully created.2) VG に PV を組み込む — vgextend
#
$ sudo vgextend data_vg /dev/vdc
Volume group "data_vg" successfully extended.
$ sudo vgs data_vg
VG #PV #LV #SN Attr VSize VFree
data_vg 2 1 0 wz--n- 29.99g 19.99g ← 20G + 10GVG の総容量が増えました。まだ LV はそのまま (10GB) です。
3) LV 拡張 — lvextend
#
$ sudo lvextend -L +10G /dev/data_vg/data_lv
Size of logical volume data_vg/data_lv changed from 10.00 GiB to 20.00 GiB.
Logical volume data_vg/data_lv successfully resized.-L +10G は「現在より 10GB 多く」、-L 20G は「最終的に 20GB に」です。+ の差を取り違えないでください。全部にしたいなら -l +100%FREE。
4) ファイルシステム拡張 — xfs_growfs
#
LV は伸びましたが、その上のファイルシステムはまだ古いサイズです。XFS なら:
$ sudo xfs_growfs /data
$ df -hT /data
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/data_vg-data_lv xfs 20G 175M 20G 1% /data ← 20G に増えたext4 なら sudo resize2fs /dev/data_vg/data_lv。マウントされた状態で拡張可能なこと が要点です。ダウンタイムなしでディスクが増えます。
lvextend の便利オプション —
-r(または--resizefs) を付ければ LV 拡張 + ファイルシステム拡張を一度に行います。$ sudo lvextend -r -L +10G /dev/data_vg/data_lv運用ではほぼ常にこちらを使います。ただし fs が認識可能な種類でなければなりません (XFS、ext2/3/4、reiserfs など)。
縮小 — XFS は不可、ext4 は可能 #
基礎 #6 で押さえた落とし穴。XFS は縮小不可。ext4 は縮小可能です。
# 1. アンマウント必須 (XFS と違う点 — ext4 も縮小は unmount が必要)
$ sudo umount /data
# 2. ファイルシステム検査
$ sudo e2fsck -f /dev/data_vg/data_lv
# 3. ファイルシステム縮小
$ sudo resize2fs /dev/data_vg/data_lv 8G
# 4. LV 縮小 (必ず fs と同じか大きいサイズで)
$ sudo lvreduce -L 8G /dev/data_vg/data_lv
# 5. 再マウント
$ sudo mount /dev/data_vg/data_lv /data順番が要点 — fs を先に縮めて LV を縮める。 逆にやるとデータが切り取られます。危険な作業なので運用ではバックアップ後にだけ進め、できれば新しい LV を作ってデータを移す方が安全 です。
スナップショット — 1 つの時点を丸ごとロック #
LVM の最も強力な機能です。ある LV のある時点を ほぼ即座に 切り取って、その後の変更は別途管理することで原本をそのまま保ちます。
原本 LV (data_lv) ─── 時間 →
│
├── スナップショット時点 (T0) — lvcreate -s
│
T0 │ T0 以降変更されたブロックはスナップショットに別途保管
│ 原本を読めば現在、スナップショットを読めば T0 時点作る #
# data_lv の T0 時点スナップショット、1GB の変更量を収容
$ sudo lvcreate -L 1G -s -n data_snap /dev/data_vg/data_lv
Logical volume "data_snap" created.
$ sudo lvs
LV VG Attr LSize Origin Data%
data_lv data_vg owi-aos--- 20.00g
data_snap data_vg swi-a-s--- 1.00g data_lv 0.01-s がスナップショットフラグ。-L 1G は 変更量 (COW) 領域のサイズ — 原本全体のサイズではなく、T0 以降原本で変更されるデータを収容する空間です。変更が多いと予想されるなら大きめに取ります。
バックアップパターン #
スナップショットが最もよく使われる役割です。
# 1. スナップショット (即時、原本は止まらない)
$ sudo lvcreate -L 5G -s -n data_snap /dev/data_vg/data_lv
# 2. スナップショットをマウントしてバックアップ
$ sudo mkdir -p /mnt/snap
$ sudo mount -o ro,nouuid /dev/data_vg/data_snap /mnt/snap
$ sudo tar czf /backup/data-$(date +%F).tar.gz -C /mnt/snap .
# 3. アンマウントしてスナップショット削除
$ sudo umount /mnt/snap
$ sudo lvremove /dev/data_vg/data_snap原本はバックアップの間に一度も止まらず、バックアップは T0 時点の一貫したデータです。原本を stop せずに一貫したバックアップ — 運用の標準パターンです。
-o nouuid— XFS は同じ UUID の fs を 2 回マウントできないように制限しています。スナップショットは原本と同じ UUID を持つのでこのオプションが必要です。ext4 では不要です。
復旧 (ロールバック) #
T0 時点に原本を戻したいなら:
# 1. 原本 LV がマウントされていればアンマウント
$ sudo umount /data
# 2. スナップショットを原本にマージ
$ sudo lvconvert --merge /dev/data_vg/data_snap
Merging of volume data_vg/data_snap started.
Merge of snapshot into logical volume data_vg/data_lv has finished.
# 3. 再マウントすれば T0 状態
$ sudo mount /dev/data_vg/data_lv /data--merge がスナップショットを原本に吸収させて T0 に戻します。マージ後はスナップショットは自動で消えます。
アクティブな LV のマージ — 原本が使用中で unmount できないなら、マージは次回のアクティベーション (次回起動) 時に起こります。つまり再起動すれば自動ロールバック。運用ではこれを意識して作業しなければなりません。
スナップショットの限界 #
- 変更量領域が埋まるとスナップショットが無効化 されます。
-Lを小さく取りすぎるとバックアップ中に壊れる可能性があります。通常は原本の 10〜20% が安全線。 - 長期保管用ではありません。 スナップショットはバックアップ / 一時テスト / ロールバックに使い、永久保管には別途バックアップ (
tar、rsync、AWS S3 など) に移す必要があります。
もう 1 段 — Thin Provisioning #
伝統的な LV は作成時に決めたサイズを VG から即座に切り取ります。100GB の LV を 2 つ作れば VG から 200GB が即座に差し引かれます。実際の使用データが少なくても。
Thin LV は「必要なときだけ持ってくる」方式です。VG に 100GB しかなくても、thin pool の上で 200GB の thin LV を 2 つ作れます。(実使用量がプール容量を超えなければ。)
# 100GB の thin pool
$ sudo lvcreate -L 100G -T data_vg/thin_pool
# pool の上に 200GB の thin LV を 2 つ (overprovisioning)
$ sudo lvcreate -V 200G -T data_vg/thin_pool -n thin_a
$ sudo lvcreate -V 200G -T data_vg/thin_pool -n thin_b
$ sudo lvs
LV VG Attr LSize Pool Data%
thin_pool data_vg twi-aotz-- 100.00g
thin_a data_vg Vwi-a-tz-- 200.00g thin_pool 0.01
thin_b data_vg Vwi-a-tz-- 200.00g thin_pool 0.01長所: ディスク割り当ての柔軟性 + 即時作成 + 効率的なスナップショット (変更量を別途取らなくて良い)。
短所: pool が満杯になるとすべての thin LV が止まります。 モニタリング (lvs、アラート) が必須。
運用ではコンテナワークロード / 仮想マシンディスクのように動的に伸びる役割でよく使います。詳細な設計は 上級シリーズ の役割です。
別のオプション — Striping と RAID #
Striping (RAID 0) #
複数の PV にデータを分けて書き込み IO を分散。速度は速いですが、1 つの PV が死ぬと全データ消失。
$ sudo lvcreate -L 10G -i 2 -I 64 -n stripe_lv data_vg
# -i 2: 2 つの PV にストライプ
# -I 64: 64KB チャンクMirroring (RAID 1) #
2 つの PV に同じデータを同期複製。1 つの PV が死んでもデータ安全。
$ sudo lvcreate -L 10G -m 1 -n mirror_lv data_vg
# -m 1: 1 つの追加コピーRAID5 / RAID6 #
$ sudo lvcreate -L 10G --type raid5 -i 3 -n raid5_lv data_vg
# -i 3: データ PV 3 つ + 自動でパリティ 1 つ = PV 4 つが必要運用では ハードウェア RAID または mdadm をより頻繁に使いますが、LVM RAID はディスク 2 枚だけで簡単なミラーを構成するときに有用です。
モニタリング / 点検 #
容量と状態 #
$ sudo pvs # PV 一覧
$ sudo vgs # VG 一覧
$ sudo lvs # LV 一覧
$ sudo lvs -a # 隠れた内部 LV まで (スナップショット、thin metadata など)$ sudo pvdisplay /dev/vdb
$ sudo vgdisplay data_vg
$ sudo lvdisplay /dev/data_vg/data_lv自動アクティベーション #
$ sudo vgchange -a y data_vg # アクティベーション
$ sudo vgchange -a n data_vg # 非アクティベーション (アンマウント後)起動時の自動アクティベーションは /etc/lvm/lvm.conf の auto_activation_volume_list で制御します。一般運用はデフォルトで十分です。
よく出会う落とし穴 #
「lvextend したのに df が変わらない」
#
LV だけ伸ばしてファイルシステム拡張 (xfs_growfs / resize2fs) をしていない場合です。-r オプションで一度に行く方が安全。
「スナップショットが急に消えた」 #
スナップショットの変更量領域が満杯になると 自動で invalidate されます。lvs の Data% が 100% に近づいたら即座にもっと大きいスナップショットへ移すか、バックアップを終えて削除しなければなりません。
「VG に PV が入らない — ‘already in volume group’」 #
すでに別の VG に属している PV です。pvs でどこに属しているか確認。本当に使っていないなら、その VG から vgreduce で外して持ってきます。
「ディスク丸ごと PV にしたが起動後に認識されない」 #
/etc/fstab にデバイス名 (/dev/vdb) で登録した場合です。デバイス名は起動ごとに変わる可能性があります。VG/LV 名 (/dev/data_vg/data_lv) または UUID で登録すれば問題ありません。
「thin pool が満杯になった — すべての thin LV が read-only」 #
thin provisioning 最大のリスクです。pool 80% アラートを必ずモニタリング し、満杯になる前に lvextend で pool 自体を伸ばさなければなりません。
AlmaLinux / Rocky の違い #
この記事のすべてのコマンドが そのまま動作します。LVM はカーネルと lvm2 パッケージの上で動作し、そのパッケージは RHEL のものをそのまま持ってきます。
よく使うコマンド一覧 #
| コマンド | やること |
|---|---|
pvcreate <device> | PV 作成 |
pvs / pvdisplay <pv> | PV 一覧 / 詳細 |
vgcreate <vg> <pv>... | VG 作成 |
vgs / vgdisplay <vg> | VG 一覧 / 詳細 |
vgextend <vg> <pv> | VG に PV 追加 |
vgreduce <vg> <pv> | VG から PV 除外 |
lvcreate -L <size> -n <lv> <vg> | LV 作成 (絶対サイズ) |
lvcreate -l 100%FREE -n <lv> <vg> | VG の残り全部で LV 作成 |
lvcreate -L <size> -s -n <snap> <orig> | スナップショット作成 |
lvcreate -L <size> -T <vg>/<pool> | thin pool 作成 |
lvcreate -V <size> -T <vg>/<pool> -n <lv> | thin LV 作成 |
lvextend [-r] -L +<size> <lv> | LV 拡張 (+ fs も同時) |
lvreduce -L <size> <lv> | LV 縮小 (危険) |
lvconvert --merge <snap> | スナップショットを原本にマージ (ロールバック) |
lvremove <lv> | LV 削除 |
vgchange -a y/n <vg> | VG アクティベーション / 非アクティベーション |
xfs_growfs <mount> | XFS 拡張 |
resize2fs <device> | ext4 拡張 / 縮小 |
lvs / lvs -a | LV 一覧 (+ 内部 LV まで) |
まとめ #
この記事で整理したフロー:
- LVM は PV (物理) → VG (プール) → LV (論理) の 3 層でディスク運用を抽象化します。
- 新しいディスク追加の標準:
pvcreate→vgcreate/vgextend→lvcreate→mkfs.xfs→ mount。 - LV 拡張は
lvextend -r -L +<size>の 1 行で (LV + fs 同時)、マウントされた状態で安全。 - XFS 縮小不可、ext4 は縮小可能だが危険。できれば新しい LV へ移す。
- スナップショット は
lvcreate -sで即座に生成、バックアップ / ロールバックの標準パターン。変更量領域のサイズに注意。 - Thin provisioning で over-provisioning が可能だが、pool 満杯モニタリングが必須。
- Striping / Mirroring / RAID は LVM 自体がサポートするが、運用では hw RAID / mdadm がより一般的。
次 — ストレージ深化 #
LVM は依然として RHEL の標準ですが、RHEL 8 からはその次世代として Stratis も入りました。単一マシンを越えてネットワークでディスクを共有する NFS / Samba も運用でよく出会う領域です。
#3 ストレージ深化 — Stratis、NFS、Samba では、Stratis が LVM + XFS の上でどんな管理モデルを提供するか、NFS サーバー / クライアントの設定フロー、そして Windows 互換の Samba まで見ていきます。ローカルディスクを越えてネットワークストレージを扱う方法を整理する記事です。