kickstartを使ってLVM thin provisioningを構成する

# はじめに

http://moriwaka.blogspot.jp/2015/05/rhel7.html を読んでLVM thin provisioning + snapperによるスナップショット作成を試してみたところ非常に良さそうだったので、早速kickstartに組み込んでお試し環境で使用できるようにした。

何が良かったかというと、手動でスナップショットを作成する以外にもsnapperが1時間に1回スナップショットを自動で作成してくれるとか、スナップショットに復元する時にいちいちシャットダウンしなくて良いとか、スナップショットの作成/復元のためにいちいち他のウィンドウで作業しなくて良いとか。
スナップショット周りが良くなると作業が捗るのでとてもありがたい。例えば構成管理ツール使ってミスって戻さないとならない場合とかね。

この記事ではkickstartファイルに追加変更した部分を書き出す。
確認はCentOS 7とFedora 21で行った。
CentOS 6では確認していないがシステムパーティションにLVM thin provisioningは適用できないんじゃないかな。

私のkickstartファイルの使いみちは次のようなもの。
後者についてはそちらにもLVM thin provisioningを適用すべくテスト中。

* [CentOS 7にCobblerをインストールする](http://qiita.com/yunano/items/476c6c060f28dd919740)
* [理想のVagrant Boxを求めて：ストレージ容量を増加できるようにする](http://qiita.com/yunano/items/d940a868b796a89689f9)

# パーティションの作成

```
part /boot --fstype=ext4 --size=512
part pv.1 --size=1 --grow
volgroup vg1 --pesize=4096 pv.1
logvol swap --fstype=swap --name=lv_swap --vgname=vg1 --size=512
logvol none --fstype=None --thinpool --name=pool1 --vgname=vg1 --size=1 --grow --percent=30 --chunksize=64
logvol / --fstype=xfs --name=lv_root --vgname=vg1 --thin --poolname=pool1 --size=1 --grow
```

kickstartファイルの中でパーティションを作成する部分はこの6行。
うち最初の4行は普通にLVMで組む時と何ら変わりはない。

5行目はLVM thin provisioningで使用する[thin pool](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Logical_Volume_Manager_Administration/thinprovisioned_volumes.html)を作成する部分である。

サイズはひとまずVolume Group全体の30%とし、足りなくなったら自動拡張を行うことにした。自動拡張については後述する。
CentOS 7では--percentを指定する時は--sizeと--growも指定しなければならないが、Fedora 21では--percentを指定する時は--sizeと--growは指定してはならないという違いがあった。したがってFedora 21では次のように指定している。

```
logvol none --fstype=None --thinpool --name=pool1 --vgname=vg1 --chunksize=64
```

基本的にはGUIインストーラによるインストール時に生成される/root/anaconda-ks.cfgを参考にして自分用kickstartファイルを作成しているのだが、--chunksizeはanaconda-ks.cfgの中では指定されていないにもかかわらず指定しなければエラーになったので追加している。サイズはGUIインストーラで作ったものを`lvs -o name,chunksize`で調べたら64だったのでそのまま64を指定した。

6行目は通常のrootパーティション作成部分に`--thin --poolname=pool1`を追加した。
--poolnameの値は5行目で--nameに指定したthin poolの名前に合わせる。
`--size=1 --grow`とはしているが、全然サイズが大きくならないので後ほど別途大きくしている。

# パッケージの選択

%packages-%end間にはインストールするパッケージを記述する。
ここでsnapperを追加している。
CentOS 7だと次の通り。私は`@base`も追加しているがこれは`@base`に有用なパッケージが含まれるからなのでお好みで。Fedora 21だと`@base`ではなく`@standard`。

```
%packages
@base
@core
snapper
%end
```

# OSインストール後の処理

kickstartの%post-%end間にはOSインストール後に行う処理を記述する。
ここには以下のような処理を記述している。

## rootパーティションの拡張

```
lvextend -l 60%VG /dev/vg1/lv_root
xfs_growfs /dev/vg1/lv_root
```

lvextendでrootパーティションを拡張して、xfs_growfsでファイルシステムに反映する。
thin provisiningなのでlvextendではディスク本来のサイズを超えた値すら指定可能であるが、ここは安全を見てVolume Groupのサイズの60%となるようにしている。

後からもっと増やしたければ、仮想マシンなら仮想マシンへの割り当てディスクを増やして次のように実行すれば良い（growpartはcloud-utils-growpartパッケージに含まれる。またutil-linuxが2.23.2-21以降でないと2番目以降のパーティションを指定するのはエラーになる）。

```
# LANG=C growpart /dev/sda 2
# pvresize /dev/sda2
# lvextend -l 60%VG /dev/vg1/lv_root
# xfs_growfs /dev/vg1/lv_root
```

## thin poolの自動拡張設定

```
sed -ri 's/(thin_pool_autoextend_threshold = )[0-9]+/\180/' /etc/lvm/lvm.conf
```

/etc/lvm/lvm.conf のthin_pool_autoextend_threshold項の値を80にすることで、thin poolの使用率が80%になった時に自動的にthin poolの拡張が行われるようにする。

thin_pool_autoextend_threshold項の初期値は100であり、初期値のままでは自動拡張は行われない。

なお、使用率についての指針として。
`lvs`を実行するとData%項に各Logical Volumeの使用率が表示される。
Meta%項はメタデータLogical Volumeの使用量だが、これはサイズが小さいうえ（`lsblk`を実行すればわかる）、自動拡張もするので気にする必要はない。
rootパーティションのLSize項（名前の通りサイズを表す）やData%項も気にする必要はない。rootパーティションはthin poolの配下にいるためだ。
自動拡張された結果、thin poolのLSize項がディスクサイズの60%を超えたら割り当てディスクを増やす運用を予定している。

## snapperの差分処理の除外対象の追加

```
echo '/var/log/*' > /etc/snapper/filters/log.txt
```

http://moriwaka.blogspot.jp/2015/05/rhel7.html に書かれている通りに /var/log 以下はsnapperの差分処理対象としないようにする。

## snapperの設定

```
cat > /root/snapper-config.sh <<EOD
#!/bin/bash

snapper create-config -f 'lvm(xfs)' /
snapper set-config TIMELINE_LIMIT_MONTHLY=0
snapper set-config TIMELINE_LIMIT_YEARLY=0
systemctl disable snapper-config.service
EOD

cat > /etc/systemd/system/snapper-config.service <<EOD
[Unit]
Description=snapper config
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/bin/bash /root/snapper-config.sh

[Install]
WantedBy=multi-user.target
EOD

systemctl daemon-reload
systemctl enable snapper-config.service
```

何かまだるっこしいことをやっているが、本来実行したいのは、

```
snapper create-config -f 'lvm(xfs)' /
snapper set-config TIMELINE_LIMIT_MONTHLY=0
snapper set-config TIMELINE_LIMIT_YEARLY=0
```

である。これはsnapper create-configで設定ファイルを生成し、snapper set-configで月の初めてのスナップショットを保持する期間であるTIMELINE_LIMIT_MONTHLYと年の初めてのスナップショットを保持する期間であるTIMELINE_LIMIT_YEARLYを0にしている。
初期値はどちらも10である。つまり初期値だと9年前の1月1日0時過ぎに自動取得されたスナップショットが延々と残り続けることになる。

で、他の部分は何をやっているかというと、この処理内容を記述したシェルスクリプトを実行するsystemdのservice unitを作ってenableにし、ついでにシェルスクリプトが実行されるとdisableにする処理も書いておくことによって、初回起動時にだけこの3行を実行するようにしているのである。

何故こうなったかというと、どうもこの3行はkickstartの%postに書くと`Failure (org.freedesktop.DBus.Error.ServiceUnknown).`とかでエラーになる。
たぶんdbus.serviceが起動していないとエラーになってしまうのではないかと思うのだが、kickstartの%post内では起動できないので初回起動時に実行させようとした、というわけである。

## Fedora 21におけるスナップショット自動実行の有効化

CentOS 7ではスナップショットの自動取得と古いスナップショットを自動削除する処理はcronで実行されるが、Fedora 21ではcronではなくsystemd-timerを使用している上にインストール時点でenableにはなっていないのでenableにする必要がある。

```
systemctl enable snapper-timeline.timer
systemctl enable snapper-cleanup.timer
```

---

以上を追加したkickstartファイルでOSインストールするとLVM thin provisioning + snapper構成のCentOS 7あるいはFedora 21が出来上がることになる。