AWS EC2のCentOSをPVからHVMへ移行する

(2年前の下書きを発見したので、時期を外していると思いつつ投稿します)
この記事では、昔から使われていたParaVirtualのEC2インスタンスをHVM対応とし、旧タイプのインスタンスから脱出するための手法を記します。
特に t1.micro で CPU steal に悩んでいる方は早めに t2.micro への移行をおすすめします。CPUクレジットに注意する必要がありますが、早い(CPU/network/storage)安い/うまい(メモリ1GB)と使わない理由がありません。
何度か作業をし、出来るだけ手順化をしてみたのでみなさんと共有します。
可能な限りコマンドライン一撃で終了できるようにしています。

# 先人の知恵
http://qiita.com/cs_sonar/items/21dbb3462708e146a426
実際の作業手順は上記のエントリーそのままですが、出来るだけsedなどのコマンドを利用しコピペで片付くような手順になっています。

# 作業用インスタンスを準備する
t2.micro/Amazon Linux(CentOSなどでも問題ないでしょう)でEC2を起動します。
このインスタンスIDが `i-IIIIIIII` として進めます。

# EBSを準備する
作業用のインスタンスにアタッチするためのEBSが必要になります。
必要なEBSは二種類です。

## 出力先となるEBSを準備する
以下の例では作業の安定性を考慮してio1/PIOPS1000/100GBのEBSを準備します。
移行元のEBSのサイズより大きなものにしましょう。(でないと収まらない)
```
aws ec2 create-volume --size 100 --availability-zone ap-northeast-1a --volume-type io1 --iops 1000
```
ここで作成されたEBSボリュームIDを `vol-DDDDDDDD` として次に進みます。

## 出力先EBSをアタッチする
```
aws ec2 attach-volume --instance-id i-IIIIIIII --device /dev/sdo --volume-id vol-DDDDDDDD
```

## 元となるEBSを準備する
元となるEBSですが、以下の順序で作成します。
以下の例では作業の安定性を考慮してio1/PIOPS1000/100GBのEBSを準備します。
- 移行元のEBSからスナップショットを作成します。
- 作成したスナップショットから作業用EBSを作成します。

```
aws ec2 create-snapshot --volume-id vol-OOOOOOOO
```
ここで作成されたスナップショットのIDを `snap-OOOOOOOO` として次に進みます。

```
aws ec2 create-volume --size 100 --availability-zone ap-northeast-1a --volume-type io1 --iops 1000 --snapshot-id snap-OOOOOOOO
````
作成されたEBSボリュームIDを `vol-SSSSSSSS` として次に進みます

## 元となるEBSをアタッチする
````
aws ec2 attach-volume --instance-id i-IIIIIIII --device /dev/sdm --volume-id vol-SSSSSSSS
```

# 作業用インスタンスでの作業
作業用インスタンスには以下の状態でEBSがマウントされている(はず)です。

|デバイス名|利用用途|
|---|---|
| /dev/xvdm | 移行元EBS |
| /dev/xvdo | 移行先EBS |

## 移行先データ用EBSを準備する
```
yum -y install parted resize2fs
parted /dev/xvdo --script 'mklabel msdos mkpart primary 1M -1s print quit'
partprobe /dev/xvdo
udevadm settle
````

## 移行元データの検査とディスクサイズの(見かけ上の)縮小
```
e2fsck -f /dev/xvdm
resize2fs -M /dev/xvdm
```

## 移行元EBSから移行先EBSへのデータ移設と縮小したディスクサイズの復元
```
dd if=/dev/xvdm of=/dev/xvdo1 bs=4K count=1747941
resize2fs /dev/xvdo1
```

## 移行先EBSのマウントとchrootによる作業準備
```
mount /dev/xvdo1 /mnt
cp -a /dev/xvdo /dev/xvdo1 /mnt/dev/
chroot /mnt
```

## grub導入と設定の調整
```
yum install -y grub
ln -s /boot/grub/menu.lst /boot/grub/grub.conf
ln -s /boot/grub/grub.conf /etc/grub.conf
rm -f /boot/grub/*stage*
cp /usr/*/grub/*/*stage* /boot/grub/
rm -f /boot/grub/device.map
cat <<EOF | grub --batch
device (hd0) /dev/xvdo
root (hd0,0)
setup (hd0)
EOF
```

## menu.lstの調整
menu.lstでの `root` `kernel` を調整します。
- (hd0)ではなく(hd0,0)とする必要があります。
- デバイス名ではなくラベル名でrootを認識させます。
- シリアルコンソールとHVM対応を明示します。

```
sed -i.bak -e 's:root\(.*\)(hd0):root\1(hd0,0):;s:root=.*:root=LABEL=/ console=ttyS0 xen_pv_hvm=enable:' /boot/grub/menu.lst 
```

以下のような形になっているか確認して下さい。 `root` `kernel` あたりが要確認項目です。

```
default=0
timeout=0
hiddenmenu
title SUZ-LAB CentOS 6
root (hd0,0)
kernel /boot/vmlinuz-2.6.32-431.1.2.0.1.el6.x86_64 ro root=LABEL=/ console=ttyS0 xen_pv_hvm=enable
initrd /boot/initramfs-2.6.32-431.1.2.0.1.el6.x86_64.img
```

## fstabの調整
fstabでのroot(/)をラベルで認識するように変更します。

```
sed -i.bak -e 's:.*\(\s\)/\s\(.*\)defaults\(.*\):LABEL=/\1/\2defaults,noatime\3:g' /etc/fstab 
```
以下のような形になっているか確認して下さい。 `LABEL=/ /` あたりが要確認項目です。

```
LABEL=/ /        ext4    defaults,noatime        1 1
none             /proc     proc    defaults        0 0
none             /sys      sysfs   defaults        0 0
none             /dev/pts  devpts  gid=5,mode=620  0 0
none             /dev/shm  tmpfs   defaults        0 0
/mnt/swap/0.img  swap      swap    defaults        0 0
```

## ディスクラベルの調整
```
e2label /dev/xvdo1 /
tune2fs -l /dev/xvdo1 |grep name
```

## chrootを退出して後片付け
chroot状態から元のOSへ戻ります。
```
exit
```

一時的に必要とされたデバイス関連ファイルを削除し、マウントを解除します。

```
rm -f /mnt/dev/xvdo /mnt/dev/xvdo1
sync
umount /mnt
```

# AMIの作成
## AMI作成のもととなるスナップショットを作成する

```
aws ec2 create-snapshot --volume-id vol-b7f1e741
```

## 作成したスナップショットからAMIを作成する