LVM (Logicl Volume Manager) はブロックデバイスを VG (Volume Group) という単位で束ねた上で、そこから LV (Logical Volume) という論理的なボリュームで切り出して使うことで柔軟性の高い管理を実現できる機能。 今回は、その LVM の基本的な使い方について確認してみる。
検証に使う環境は CentOS7 にした。
$ cat /etc/redhat-release CentOS Linux release 7.1.1503 (Core) $ uname -r 3.10.0-229.14.1.el7.x86_64
LVM をインストールする
LVM のユーティリティが入っていない場合には、インストールした上で再起動しておく。
$ sudo yum -y install lvm2 $ sudo shutdown -r now
ブロックデバイスを用意する
LVM の検証のためにハードディスクを用意するのは面倒なので、今回はループデバイスで代用することにする。 ループデバイスは通常のファイルをブロックデバイスとして読み書きできるようにする機能。 詳細は以下に書いた。
あらかじめ 100MB の容量を持ったループデバイスをふたつ用意しておく。
$ dd if=/dev/zero of=/var/tmp/loopfile0 bs=1M count=100 $ dd if=/dev/zero of=/var/tmp/loopfile1 bs=1M count=100 $ sudo losetup /dev/loop0 /var/tmp/loopfile0 $ sudo losetup /dev/loop1 /var/tmp/loopfile1 $ losetup -a /dev/loop0: []: (/var/tmp/loopfile0) /dev/loop1: []: (/var/tmp/loopfile1)
PV (Physical Volume) を作る
LVM では物理的なハードディスクなどを PV という単位で管理する。 今回は先ほど作ったブロックデバイスを丸ごとそのまま PV として使ってるけど、特定のパーティションだけを LVM の PV として扱うこともできるっぽい。
pvcreate コマンドでブロックデバイスを PV として扱えるようにする。
$ sudo pvcreate -v /dev/loop0 /dev/loop1 Set up physical volume for "/dev/loop0" with 204800 available sectors Zeroing start of device /dev/loop0 Writing physical volume data to disk "/dev/loop0" Physical volume "/dev/loop0" successfully created Set up physical volume for "/dev/loop1" with 204800 available sectors Zeroing start of device /dev/loop1 Writing physical volume data to disk "/dev/loop1" Physical volume "/dev/loop1" successfully created
PV の情報は pvdisplay コマンドで確認できる。
$ sudo pvdisplay /dev/loop0 /dev/loop1 "/dev/loop0" is a new physical volume of "100.00 MiB" --- NEW Physical volume --- PV Name /dev/loop0 VG Name PV Size 100.00 MiB Allocatable NO PE Size 0 Total PE 0 Free PE 0 Allocated PE 0 PV UUID CDt1W3-ErgE-TB97-BqOl-7FSZ-Txzi-i7o5Ow "/dev/loop1" is a new physical volume of "100.00 MiB" --- NEW Physical volume --- PV Name /dev/loop1 VG Name PV Size 100.00 MiB Allocatable NO PE Size 0 Total PE 0 Free PE 0 Allocated PE 0 PV UUID Kia26d-4T5B-dnqn-6AYU-Wz2Q-lmnq-Q9uLxa
VG (Volume Group) を作る
作成した PV は VG という単位で束ねて使う。 もちろん、別に束ねなくても問題はない。
vgcreate コマンドで先ほど作った PV を束ねた新しい VG を作る。
$ sudo vgcreate -v vg0 /dev/loop0 /dev/loop1 Adding physical volume '/dev/loop0' to volume group 'vg0' Adding physical volume '/dev/loop1' to volume group 'vg0' Archiving volume group "vg0" metadata (seqno 0). Creating volume group backup "/etc/lvm/backup/vg0" (seqno 1). Volume group "vg0" successfully created
作成した VG は vgscan コマンドで確認できる。
$ sudo vgscan Reading all physical volumes. This may take a while... Found volume group "vg0" using metadata type lvm2
VG の情報は vgdisplay コマンドで確認できる。
$ sudo vgdisplay -v vg0 Using volume group(s) on command line. --- Volume group --- VG Name vg0 System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 Cur LV 0 Open LV 0 Max PV 0 Cur PV 2 Act PV 2 VG Size 192.00 MiB PE Size 4.00 MiB Total PE 48 Alloc PE / Size 0 / 0 Free PE / Size 48 / 192.00 MiB VG UUID HEXmQd-eBbN-geXc-bMHA-PCow-E8Q3-L7LNTS --- Physical volumes --- PV Name /dev/loop0 PV UUID CDt1W3-ErgE-TB97-BqOl-7FSZ-Txzi-i7o5Ow PV Status allocatable Total PE / Free PE 24 / 24 PV Name /dev/loop1 PV UUID Kia26d-4T5B-dnqn-6AYU-Wz2Q-lmnq-Q9uLxa PV Status allocatable Total PE / Free PE 24 / 24
上記の vgdisplay コマンドの表示の中には PE という表示があって、何やら容量を表しているっぽいように見える。 これは PE (Physical Extend) というもので、LVM では VG をこの PE という単位を使って容量の管理をしている。
ひとつの VG の中には最大で 64k 個の PE が入る。 VG の中身が PE という均一の大きさで仕切られていて、その仕切りの数の最大が 64k 個というのをイメージするといい。
ひとつの PE のサイズは可変で、デフォルトでは 4MiB に設定されている。 つまり、デフォルトではひとつの VG で扱える最大のサイズは 4MiB * 64k PE = 256GiB ということになる。 この値は vgcreate コマンドの -s オプションで変更することができる。 簡単に計算するには PE のサイズ 1MiB 毎に 64GiB ずつ扱えるサイズが大きくなると覚えておけばよさそう。 例えば -s 32m とすれば、PE のサイズが 32MiB なので扱える最大サイズは 32 * 64 = 2048GiB (2TiB) になる。
pvdisplay コマンドを使うと PV で使われている PE のサイズが確認できる。
$ sudo pvdisplay /dev/loop0 /dev/loop1 --- Physical volume --- PV Name /dev/loop0 VG Name vg0 PV Size 100.00 MiB / not usable 4.00 MiB Allocatable yes PE Size 4.00 MiB Total PE 24 Free PE 24 Allocated PE 0 PV UUID CDt1W3-ErgE-TB97-BqOl-7FSZ-Txzi-i7o5Ow --- Physical volume --- PV Name /dev/loop1 VG Name vg0 PV Size 100.00 MiB / not usable 4.00 MiB Allocatable yes PE Size 4.00 MiB Total PE 24 Free PE 24 Allocated PE 0 PV UUID Kia26d-4T5B-dnqn-6AYU-Wz2Q-lmnq-Q9uLxa
LV (Logical Volume) を作る
さて、VG まで作ることができたので、そこから論理的なボリュームである LV を切り出すことができる。 これが従来のパーティションに相当すると考えればいいかな。
lvcreate コマンドを使ってサイズを指定した上で VG から LV を切り出す。
$ sudo lvcreate -L 16M -n lv0 vg0
Logical volume "lv0" created.
すると LV のデバイスができる。
$ ls /dev/vg0/lv0 /dev/vg0/lv0
LV の情報は lvdisplay コマンドで確認できる。
$ sudo lvdisplay /dev/vg0/lv0 --- Logical volume --- LV Path /dev/vg0/lv0 LV Name lv0 VG Name vg0 LV UUID vzd56T-b6uU-v8pY-ysNn-Y6EH-pY7w-etAinX LV Write Access read/write LV Creation host, time localhost.localdomain, 2015-09-21 22:16:10 +0900 LV Status available # open 0 LV Size 16.00 MiB Current LE 4 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 8192 Block device 253:0
vgdisplay コマンドを確認すると、LV を切り出した分だけ /dev/loop0 から利用可能な PE が減っている。
$ sudo vgdisplay -v vg0 | tail -n 12 Using volume group(s) on command line. --- Physical volumes --- PV Name /dev/loop0 PV UUID CDt1W3-ErgE-TB97-BqOl-7FSZ-Txzi-i7o5Ow PV Status allocatable Total PE / Free PE 24 / 20 PV Name /dev/loop1 PV UUID Kia26d-4T5B-dnqn-6AYU-Wz2Q-lmnq-Q9uLxa PV Status allocatable Total PE / Free PE 24 / 24
LV を使うために、まずは XFS でフォーマットする。
$ sudo mkfs.xfs /dev/vg0/lv0 meta-data=/dev/vg0/lv0 isize=256 agcount=1, agsize=4096 blks = sectsz=512 attr=2, projid32bit=1 = crc=0 finobt=0 data = bsize=4096 blocks=4096, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=0 log =internal log bsize=4096 blocks=853, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0
あとは適当な場所にマウントするだけ。
$ mkdir /tmp/mnt0 $ sudo mount -t xfs /dev/vg0/lv0 /tmp/mnt0
df コマンドでマウントされていることが確認できる。
$ df | grep mnt /dev/mapper/vg0-lv0 12972 880 12092 7% /tmp/mnt0
VG に PV を追加する
例えば VG の容量が足りなくなってきた場合などには、ハードディスクを新たに追加する必要がありそう。
まずは先ほどと同様に、追加するための PV をループデバイスで作っておく。
$ dd if=/dev/zero of=/var/tmp/loopfile2 bs=1M count=100 100+0 レコード入力 100+0 レコード出力 104857600 バイト (105 MB) コピーされました、 0.0550698 秒、 1.9 GB/秒 $ sudo losetup /dev/loop2 /var/tmp/loopfile2 $ sudo pvcreate /dev/loop2 Physical volume "/dev/loop2" successfully created
既存の VG に PV を追加する場合は vgextend コマンドを使う。
$ sudo vgextend vg0 /dev/loop2
Volume group "vg0" successfully extended
これで VG に PV が追加された。
$ sudo vgdisplay -v vg0 | tail -n 16 Using volume group(s) on command line. --- Physical volumes --- PV Name /dev/loop0 PV UUID CDt1W3-ErgE-TB97-BqOl-7FSZ-Txzi-i7o5Ow PV Status allocatable Total PE / Free PE 24 / 20 PV Name /dev/loop1 PV UUID Kia26d-4T5B-dnqn-6AYU-Wz2Q-lmnq-Q9uLxa PV Status allocatable Total PE / Free PE 24 / 24 PV Name /dev/loop2 PV UUID gqsmNX-v23C-F7IU-IsCa-qlfX-wsQ2-ywIvzy PV Status allocatable Total PE / Free PE 24 / 24
LV のサイズを増やす
LV の容量を増やすには lvextend コマンドを使う。 これはもちろん VG に空きがなければいけない。
$ sudo lvextend -L +16MB /dev/vg0/lv0 Size of logical volume vg0/lv0 changed from 16.00 MiB (4 extents) to 32.00 MiB (8 extents). Logical volume lv0 successfully resized
vgdisplay コマンドを確認すると、おかわりした分だけ /dev/loop0 から利用可能な PE が減っている。
$ sudo vgdisplay -v vg0 | tail -n 16 Using volume group(s) on command line. --- Physical volumes --- PV Name /dev/loop0 PV UUID CDt1W3-ErgE-TB97-BqOl-7FSZ-Txzi-i7o5Ow PV Status allocatable Total PE / Free PE 24 / 16 PV Name /dev/loop1 PV UUID Kia26d-4T5B-dnqn-6AYU-Wz2Q-lmnq-Q9uLxa PV Status allocatable Total PE / Free PE 24 / 24 PV Name /dev/loop2 PV UUID gqsmNX-v23C-F7IU-IsCa-qlfX-wsQ2-ywIvzy PV Status allocatable Total PE / Free PE 24 / 24
LV の情報をみてもサイズが 16MiB から 32MiB に倍増している。
$ sudo lvdisplay /dev/vg0/lv0 --- Logical volume --- LV Path /dev/vg0/lv0 LV Name lv0 VG Name vg0 LV UUID vzd56T-b6uU-v8pY-ysNn-Y6EH-pY7w-etAinX LV Write Access read/write LV Creation host, time localhost.localdomain, 2015-09-21 22:16:10 +0900 LV Status available # open 1 LV Size 32.00 MiB Current LE 8 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 8192 Block device 253:0
よーし、ばっちりだーと思って df しても、実はこの時点ではまだ容量は増えていない。 ファイルシステム的には、まだ使える領域が増えたことを認識できていない。
$ df | grep mnt0 /dev/mapper/vg0-lv0 12972 880 12092 7% /tmp/mnt0
この LV は XFS でフォーマットしてあるので、サイズを増やすには xfs_growfs コマンドを使う。
$ sudo xfs_growfs /tmp/mnt0 meta-data=/dev/mapper/vg0-lv0 isize=256 agcount=1, agsize=4096 blks = sectsz=512 attr=2, projid32bit=1 = crc=0 finobt=0 data = bsize=4096 blocks=4096, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=0 log =internal bsize=4096 blocks=853, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 data blocks changed from 4096 to 8192
これでやっと空き容量が増えた。
$ df | grep mnt0 /dev/mapper/vg0-lv0 29356 912 28444 4% /tmp/mnt0
尚、ファイルシステムに ext* を使っている場合は resize2fs コマンドを使うようだ。
PV のデータを移動する
メンテナンスなどで、ある PV のデータを別の PV に移すことも考えられる。
そうした場合には pvmove コマンドを使って PV から PV にデータを移動できる。
$ sudo pvmove /dev/loop0 /dev/loop2 /dev/loop0: Moved: 75.0% /dev/loop0: Moved: 100.0%
データが移ったので /dev/loop0 が空いた代わりに /dev/loop2 の利用可能 PE が減った。
$ sudo vgdisplay -v vg0 | tail -n 16 Using volume group(s) on command line. --- Physical volumes --- PV Name /dev/loop0 PV UUID CDt1W3-ErgE-TB97-BqOl-7FSZ-Txzi-i7o5Ow PV Status allocatable Total PE / Free PE 24 / 24 PV Name /dev/loop1 PV UUID Kia26d-4T5B-dnqn-6AYU-Wz2Q-lmnq-Q9uLxa PV Status allocatable Total PE / Free PE 24 / 24 PV Name /dev/loop2 PV UUID gqsmNX-v23C-F7IU-IsCa-qlfX-wsQ2-ywIvzy PV Status allocatable Total PE / Free PE 24 / 16
使わなくなった PV は vgreduce コマンドで外すことができる。
$ sudo vgreduce vg0 /dev/loop0 Removed "/dev/loop0" from volume group "vg0"
これで VG に参加している PV が 2 台に戻った。
$ sudo vgdisplay -v vg0 | tail -n 12 Using volume group(s) on command line. --- Physical volumes --- PV Name /dev/loop1 PV UUID Kia26d-4T5B-dnqn-6AYU-Wz2Q-lmnq-Q9uLxa PV Status allocatable Total PE / Free PE 24 / 24 PV Name /dev/loop2 PV UUID gqsmNX-v23C-F7IU-IsCa-qlfX-wsQ2-ywIvzy PV Status allocatable Total PE / Free PE 24 / 16
データを冗長化する
VG が複数の PV を束ねて使う場合、そのままでは耐障害性という意味でソフトウェア RAID0 に近いように思える。 そのため LVM には PV の片系故障でデータが消えるのを防ぐため、複数の PV にデータをミラーリングする機能があるようだ。 ソフトウェア RAID1 に近い機能かな。
lvcreate コマンドで LV を作る際に、-m オプションを付けた上でミラーリングする先の PV を指定する。
$ sudo lvcreate -L 16M -m 1 -n lv1 vg0 /dev/loop1 /dev/loop2 Logical volume "lv1" created.
容量を確認すると、両方の PV から均等に利用可能な PE が減っている。
$ sudo vgdisplay -v vg0 | tail -n 12 Using volume group(s) on command line. --- Physical volumes --- PV Name /dev/loop1 PV UUID Kia26d-4T5B-dnqn-6AYU-Wz2Q-lmnq-Q9uLxa PV Status allocatable Total PE / Free PE 24 / 19 PV Name /dev/loop2 PV UUID gqsmNX-v23C-F7IU-IsCa-qlfX-wsQ2-ywIvzy PV Status allocatable Total PE / Free PE 24 / 11
LV の情報を見ると Mirrored Volumes という項目が増えて、データが複数の PV に冗長化されていることがわかる。
$ sudo lvdisplay /dev/vg0/lv1 --- Logical volume --- LV Path /dev/vg0/lv1 LV Name lv1 VG Name vg0 LV UUID 6ArEdr-EDSx-JAr0-xFkB-MTx5-7nO7-Infe4Y LV Write Access read/write LV Creation host, time localhost.localdomain, 2015-09-21 22:31:50 +0900 LV Status available # open 0 LV Size 16.00 MiB Current LE 4 Mirrored volumes 2 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 8192 Block device 253:5
とはいえ個人的にはハードウェア RAID で冗長化したボリュームの上で LVM を使いたいかな。
まとめ
今回は CentOS7 とループデバイスを使って簡単に LVM の動作を試してみた。 物理的なブロックデバイスを LVM というレイヤーを挟んで使うのは確かに便利だけど、上手に使うためには事前知識やノウハウがたくさん必要になりそうだと感じた。