LVM シンプロビジョニングボリューム

LVM のシンプロビジョニングボリュームを使ってみました。

VirtualBox に CentOS 7 をインストールした後に 5G のディスクを追加して試しています。

----

追加ディスクで PV を作成します（いきなり `vgcreate` しても大丈夫なようです）

```
pvcreate /dev/sdb
```

ボリュームグループを作成します。`-s` は物理エクステントのサイズを指定しているのですが詳細は割愛します。

```
vgcreate -s 32MB vg0 /dev/sdb
```

ボリュームグループにシンプールを作成します。

`lvcreate` に `--thin` を付け、`VolumeGroupName/ThinPoolName` の形式でプール名を指定します。`-L 512M` はシンプールに割り当てるサイズです。

```
lvcreate --thin -L 512M vg0/thin
```

次のように作成しても同じです。

```
lvcreate --thinpool thin -L 512M vg0
```

作成したシンプールにシンプロビジョニングされたボリュームを作成します。

`lvcreate` に `--thin` を付け、`-V 10G` でボリュームのサイズ、`-n vol` でボリュームの名前、`vg0/thin` は↑で作成したシンプールの名前です。

```
lvcreate --thin -V 10G -n vol vg0/thin
```

シンプールには 512MB しか割り当てていませんが、シンプロビジョニングなので 10GB のボリュームでも作成できます。

ボリュームにファイルシステムを作成してマウントしてサイズを確認します。

```
mkfs.xfs /dev/vg0/vol
mount -t xfs /dev/vg0/vol /mnt
df -h /mnt/
```

10G となっています。

```
Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/vg0-vol   10G   33M   10G   1% /mnt
```

256MB ほど書き込みます。

```
dd if=/dev/zero of=/mnt/data bs=256M count=1
```

シンプールは 50% 程度消費されていることがわかります。

```
lvs
  LV   VG   Attr       LSize   Pool Origin Data%  Move Log Cpy%Sync Convert
  thin vg0  twi-a-tz-- 512.00m              52.17
  vol  vg0  Vwi-aotz--  10.00g thin          2.61
```

さらに 512 MB 書き込んでみます。

```
dd if=/dev/zero of=/mnt/data2 bs=512M count=1
```

応答がなくなりました・・・

lvs で見てみるとシンプールを 100% 使いきっています。

```
lvs
  LV   VG   Attr       LSize   Pool Origin Data%  Move Log Cpy%Sync Convert
  thin vg0  twi-a-tz-- 512.00m             100.00
  vol  vg0  Vwi-aotz--  10.00g thin          5.00
```

シンプールのサイズを増やします。

```
lvresize -L 1G /dev/vg0/thin
```

dd はエラーで終わりました。

```
dd if=/dev/zero of=/mnt/data2 bs=512M count=1
dd: error writing ‘/mnt/data2’: Input/output error
1+0 records in
0+0 records out
480530432 bytes (481 MB) copied, 47.777 s, 10.1 MB/s
```

/mnt は I/O エラーになります。

```
ls /mnt
  ls: cannot access /mnt: Input/output error
```

マウントしなおすとアクセスできるようになりました。

```
umount /mnt
mount -t xfs /dev/vg0/vol /mnt
ll /mnt
```

ボリュームの削除は普通の論理ボリュームと同じです。

```
umount /mnt
lvremove /dev/vg0/vol
```

# シンプロビジョニングスナップショット

シンプロビジョニングされたボリュームからは、シンプロビジョニングされたスナップショットを作成することができます。

（シンプロビジョニングではない）通常のスナップショットボリュームのようにあらかじめサイズを決める必要がありません。

先ほどと同じようにシンプロビジョニングされたボリュームを作成します。

```
lvcreate --thin -V 1G -n vol1 vg0/thin
```

ファイルシステムを作成＆マウントして適当に書き込みます。

```
mkfs.xfs /dev/vg0/vol1
mount -t xfs /dev/vg0/vol1 /mnt
touch /mnt/test1
umount /mnt
```

シンプロビジョニングされたスナップショットを作成します。

普通のスナップショットなら `-L 1G` のようにサイズを指定するところですが、シンプロビジョニングされたスナップショットではサイズは指定しません。

```
lvcreate -s -n vol2 vg0/vol1
```

lvs で見てみると次のように表示されます。Origin の箇所をみれば vol2 が vol1 のスナップショットであることがわかります。

```
lvs
  LV   VG   Attr       LSize Pool Origin Data%  Move Log Cpy%Sync Convert
  thin vg0  twi-a-tz-- 1.00g               1.04
  vol1 vg0  Vwi-a-tz-- 1.00g thin          1.04
  vol2 vg0  Vwi---tz-k 1.00g thin vol1
```

元ボリューム(vol1)に追加で書き込みます。

```
mount -t xfs /dev/vg0/vol1 /mnt
touch /mnt/test2
umount /mnt
```

vol1 をスナップショットに戻してみます。

`lvconvert` に `--merge` を付け、`/dev/vg0/vol2` のようにスナップショットを指定すると、そのスナップショットが元ボリュームに書き戻されます。

```
lvconvert --merge /dev/vg0/vol2
```

マウントして内容を確認すると、スナップショットの時点に戻っていることがわかります。

```
mount -t xfs /dev/vg0/vol1 /mnt
ls /mnt/
  test1

umount /mnt/
```

# 元ボリュームを削除

↑の手順ではスナップショットから元ボリュームに復元しましたが、元ボリュームを削除すればスナップショットが通常のボリュームに変わります。

先ほどの手順と同じようにスナップショットを作成します。

```
lvcreate -s -n vol2 vg0/vol1
```

元ボリュームをマウントして適当に書き込みます。

```
mount -t xfs /dev/vg0/vol1 /mnt
touch /mnt/test2
umount /mnt
```

元ボリュームを削除します。

```
lvremove /dev/vg0/vol1
```

vol2 をアクティブ化します。これをやっておかないと vol2 が /dev/vg0/ に現れずマウントできません。

```
lvchange -kn -ay vg0/vol2
```

vol2 をマウントして内容を確認すると、スナップショットを作成した時点の内容になっていることがわかります。

```
mount -t xfs /dev/vg0/vol2 /mnt
ls /mnt
  test1

umount /mnt
```

# スナップショットに書き込む

通常の LVM スナップショットと同じように、スナップショットをマウントして書き込むこともできます。

vol2 からスナップショットを作成します。

```
lvcreate -s -n vol3 vg0/vol2
```

vol3 をアクティブ化します。

```
lvchange -kn -ay vg0/vol3
```

vol3 をマウントして書き込みます。

```
mount -t xfs /dev/vg0/vol3 /mnt
touch /mnt/test3
umount /mnt
```

さらに、vol3 からスナップショットを作成してアクティブ化します。

```
lvcreate -s -n vol4 vg0/vol3
lvchange -kn -ay vg0/vol4
```

vol4 をマウントして書き込みます。

```
mount -t xfs /dev/vg0/vol4 /mnt
touch /mnt/test4
umount /mnt
```

次のように階層的なスナップショットになっています。

```
lvs
  LV   VG   Attr       LSize Pool Origin Data%  Move Log Cpy%Sync Convert
  thin vg0  twi-a-tz-- 1.00g               1.46
  vol2 vg0  Vwi-a-tz-- 1.00g thin          1.04
  vol3 vg0  Vwi-a-tz-- 1.00g thin vol2     1.04
  vol4 vg0  Vwi-a-tz-- 1.00g thin vol3     1.04
```

それぞれのボリュームをマウントして内容を確認してみます。

```
mount -t xfs /dev/vg0/vol2 /mnt

ls /mnt
  test1

umount /mnt
mount -t xfs /dev/vg0/vol3 /mnt

ls /mnt
  test1 test3

umount /mnt
mount -t xfs /dev/vg0/vol4 /mnt

ls /mnt
  test1 test3 test4

umount /mnt
```

ここで階層の中間である vol3 を削除すると。

```
lvremove /dev/vg0/vol3
```

vol4 の親が vol2 になるかと思ったのですが、vol4 は独立したボリュームになりました。

```
lvs
  LV   VG   Attr       LSize Pool Origin Data%  Move Log Cpy%Sync Convert
  thin vg0  twi-a-tz-- 1.00g               1.25
  vol2 vg0  Vwi-a-tz-- 1.00g thin          1.04
  vol4 vg0  Vwi-a-tz-- 1.00g thin          1.04
```

# ボリュームから複数回スナップショットを作成

1つのボリュームに 100MB ずつファイルを書き込みつつ複数回スナップショットを作成してみます。

```
lvcreate --thin -V 1G -n vol1 vg0/thin
mkfs.xfs /dev/vg0/vol1

mount -t xfs /dev/vg0/vol1 /mnt
dd if=/dev/zero of=/mnt/data1 bs=100M count=1
umount /mnt

lvcreate -s -n vol2 vg0/vol1

mount -t xfs /dev/vg0/vol1 /mnt
dd if=/dev/zero of=/mnt/data2 bs=100M count=1
umount /mnt

lvcreate -s -n vol3 vg0/vol1

mount -t xfs /dev/vg0/vol1 /mnt
dd if=/dev/zero of=/mnt/data3 bs=100M count=1
umount /mnt

lvcreate -s -n vol4 vg0/vol1

mount -t xfs /dev/vg0/vol1 /mnt
dd if=/dev/zero of=/mnt/data4 bs=100M count=1
umount /mnt
```

lvs で見てみると、次のようにシンプールとボリュームのサイズがほとんど変わらないことがわかります。

```
lvs
  LV   VG   Attr       LSize Pool Origin Data%  Move Log Cpy%Sync Convert
  thin vg0  twi-a-tz-- 1.00g              40.74
  vol1 vg0  Vwi-a-tz-- 1.00g thin         40.10
  vol2 vg0  Vwi---tz-k 1.00g thin vol1
  vol3 vg0  Vwi---tz-k 1.00g thin vol1
  vol4 vg0  Vwi---tz-k 1.00g thin vol1
```

複数のスナップショットがある状態で元ボリュームに書き込みが発生すると、CoW で複数のスナップショットに同じデータの書き込みが発生するかと思ったのですが（つまりスナップショットの数だけシンプールを消費する）、そんなこともないようです。

# 参考

- [2.3.4. シンプロビジョニングされた論理ボリューム (シンボリューム)](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Logical_Volume_Manager_Administration/thinprovisioned_volumes.html "2.3.4. シンプロビジョニングされた論理ボリューム (シンボリューム)")
- [2.3.6. シンプロビジョニングされたスナップショットボリューム](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Logical_Volume_Manager_Administration/thinly-provisioned_snapshot_volumes.html "2.3.6. シンプロビジョニングされたスナップショットボリューム")
- [4.4.4. シンプロビジョニングされた論理ボリュームの作成](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Logical_Volume_Manager_Administration/thinly_provisioned_volume_creation.html "4.4.4. シンプロビジョニングされた論理ボリュームの作成")
- [4.4.6. シンプロビジョニングされたスナップショットボリュームの作成](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Logical_Volume_Manager_Administration/thinly_provisioned_snapshot_creation.html "4.4.6. シンプロビジョニングされたスナップショットボリュームの作成")