LVMの機能を使ってAWSのEC2インスタンスを稼働させたままEBSディスクを大きなものに付け替える方法とリストアについて


## Motivation

手順の途中までは通常のLVMによるEBSボリューム追加によるディスク容量の増加方法と同じです。この方法についてはQiita上にもたくさんノウハウが上がっています。

このメモでは容量の大きなものにディスクの付け替えをしています。元々接続していたボリュームは破棄してしまいます。１つのパーティションは１つのディスクで運用しているのです。

理由は、LVMで複数のディスク(EBSボリューム)で１つのパーティションを構成していると、ボリュームのスナップショットを取るタイミングが少しでもずれると、パーティションのデータがスナップショットからリストア不能になることを怖れたためです（現実にはそんなにシビアではないかもしれませんが）
LVMならばディスクを統合して大きなパーティションを作れることも利点の一つですが、このメモではサーバーを稼働させたままで容量増加できる、というLVMの柔軟性だけを利用していることになります。

## 前提

+ OSはCentOS6(RHEL互換)を想定しています(CentOS7だとファイルシステムが変わっているので試していません）
+ 容量追加するパーティションは論理ボリューム(LVM)であること
+ 既存のディスクがどのデバイスに割り当ててあるかを```fdisk -l```コマンドなどで把握しておくこと

## 作業内容

1. EBSボリュームの新規作成
	- AWS management consoleのEC2＞Volumes画面にて Create Volumeします。容量は拡張後のサイズ（増分だけではない）を指定します。
1. EBSボリュームのアタッチ
	- AWS management consoleのEC2＞Volumes画面にて、ボリュームを選択し、インスタンスを指定してアタッチします（インスタンスは稼働中でも良い）
	- アタッチの際に、デバイス名を指定できるのですが、CentOSやRHEL互換のOSの場合、指定した名前とOSから見えるデバイス名が異なるので、後で確認する必要があります。
1. インスタンス側では、追加されたボリュームを確認します。
	- sshで接続するなどして、root権限でコマンドを実行します。

	$ fdisk -l
	(この結果、追加されたボリュームが /dev/xvdk として見えたとします）
1. 追加されたボリュームをLVMのボリュームグループ（ここではExtraVol01とする）に組み込む

	$ pvcreate /dev/xvdk
	$ vgextend ExtraVol01 /dev/xvdk

1. 論理ボリューム（この場合は/dev/ExtraVol01/homedata)を拡張
	- ただしサイズの単位としてGBで指定すると微妙に過不足があるので、一度vgdisplay -vコマンドを実施して、容量がおおきなEBSボリュームのサイズをPEの個数として確認し、-l オプションではその個数で指定します。たとえば５GBならPEの個数換算では1279個となります。

	$ vgdisplay -v
	$ lvextend -l 1279 /dev/ExtraVol01/homedata

1. ファイルシステムの拡張
オンラインのままで可能です

	$ resize2fs /dev/mapper/ExtraVol01-homedata

1. パーティションサイズが増加していることの確認
普通のディスク拡張ならここまでで手順は終わりです。

	$ df

1. 容量の小さい元のディスク(/dev/xvdjとする）からのデータの移行
これには10分以上かかることもありますので、screenコマンドが使える場合にはあらかじめ起動しておきます。

	$ screen -L
	$ pvmove -v /dev/xvdj

1. 元のディスクの使用量がゼロであることを確認する
新しく追加されたディスクへすべてのデータが収まっていることも確認できます

	$ vgdisplay -v

1. 古いディスクを論理ボリュームから完全に切り離す

	$ vgreduce ExtraVol01 /dev/xvdj 
	$ pvremove -v /dev/xvdj

1. AWSのコンソールからボリュームをDetachする
	- AWS management consoleのEC2＞Volumes画面にて ボリュームを選択してDetachします。
	- サーバーが起動している時に行う場合は、単なるDetachではなく、Detach forceする必要がありますが、間違えればサーバーがクラッシュしますので慎重に。

## リストア

### リストアについての注意

LVMのボリュームなので、リストアしたボリュームを他のインスタンスにアタッチしてもそのままでは読めません。
さらに、複数のEBSを１つのlogical volumeにまとめて利用した場合は、スナップショットはサーバを停止して取らないといけませんし、リストアはさらに困難になります。

したがって、私はEC2のLVMの運用は「１つのパーティションは１つのEBSボリュームでまかなう」ことにしています。EBSのサイズの上限である1TB以上のパーティションは作れませんが、

### スナップショットからのリストアの手順

参考：https://www.upken.jp/kb/mount_other_lvm_disk.html

1. EBSボリュームを、スナップショットから作成
1. ボリュームをEC2のLinuxインスタンスにアタッチ
1. アタッチされたボリュームのデバイス名を確認
```fdisk -l```でディスクとパーティション一覧を取得し、アタッチされたディスクを確認する。たとえばこの場合は/dev/hdbだったとする
1. ボリュームグループ名を確認する
pvscan でボリュームグループ(VG)名がたとえば VolGroup00 であるとわかる。

	$ pvscan
	PV /dev/hdb2   VG VolGroup00   lvm2 [19.88 GB / 0    free]
	Total: 1 [19.88 GB] / in use: 1 [19.88 GB] / in no VG: 0 [0   ]

1. ボリュームグループ内のロジカルボリューム名を確認する
```lvscan```でVolGroup00 にロジカルボリューム(LV) LogVol01 があることがわかる。

	$ lvscan
	inactive      '/dev/VolGroup00/LogVol01' [19.88 GB] inherit

1. ロジカルボリュームをシステムで利用出来るようにする
ロジカルボリューム(LV)の属性を変更することで、OSから読み書きできるようにします。この結果ロジカルボリュームは```/dev/mapper/VolGroup00-LogVol01```というファイルシステムとして利用できる状態になります。

	$ lvchange --available y /dev/VolGroup00/LogVol01

1. ファイルシステムをマウント
データを復旧するために、適当なディレクトリを作成してそこにマウントします。

	$ mkdir -p /mnt/vol01
	$ mount /dev/mapper/VolGroup00-LogVol01 /mnt/vol01

1. 後は煮るなり焼くなり。

### スナップショット使ってAMI構築するのも手かもしれませんがおすすめしません

AWSのCLIに詳しくて、元々のサーバーのルートパーティションのスナップショットなどがあれば、リストアしたいボリュームのスナップショットを含めたAMIを構築することができるかもしれませんが、LVMの状態が合っていないと、ファイルシステムの破損などが起きる恐れがあるので、おすすめしません。

AWS上でサーバーのバックアップということならば、サーバーを停止した状態でCreate Imageするのが一番安心です。

今後、DockerのようなコンテナシステムやCoreOSのようなImmutableなシステムが一般化したら、また違ったベストプラクティスが生まれるのでしょう。