2014年7月にEC2のインスタンスファミリーにt2系のインスタンスが追加されました。一つ前の世代のインスタンスであるt1系のインスタンスの価格よりも安く、スペックは上がっているお得なインスタンスです。
こうなるとt1系のインスタンスを使い続ける理由は無いので、t1.micro → t2.micro へインスタンスをアップデートしたくなります。ただこのt2系のインスタンスを使用するには以下の制約があります。
- EC2-VPCのみサポート
EC2-Classicのプラットフォームはサポートしてないので、EC2-Classicの環境ではVPCを作成してそのVPCでインスタンスを起動する必要があります。 - サポートしている仮想化方式はHVMのみ
t2系のインスタンスはHVM AMIからしか起動できません。仮想化方式がPVのAMIからインスタンスを起動することはできません。
EC2-VPCの制約はVPCを作成すればいいので特に問題にはなりませんが、仮想化方式の方がネックになります。t1.microで起動しているインスタンスがPVのAMIであれば、そのままではt2系のインスタンスへ変更することはできません。AWSからも現時点では公式にPV→HVMの変換機能やツールは提供されていません。
ということで、今回は pv2hvm というツールを使って移行してみました。pv2hvmは作業用のインスタンスに元のAMIのスナップショットと新規に作成した移行先のディスクボリュームをマウントし、データのコピー、grubのインストール等を行い、HVMなAMIの作成を一括で行ってくれるツールです。
要件と制約
pv2hvmを使用するにあたり以下の要件を満たす必要があります。
- 必ずEC2インスタンスで動かすこと
- AWS SDK for Rubyが必要
- EC2の管理権限を持つインスタンスプロファイルを持ってること
- 元のAMIは自分のものかスナップショットの作成が許可されたものであること
- 元のAMIにgrubがインストールされていること
- テストは最近のAmazon Linuxでしか行われていない
- マーケットプレイスのAMIは変換できない
では早速マイグレーション!
1. grubのインストール
移行対象のインスタンスにgrubをインストールします。
$ sudo yum install grub
2. AMIの作成
移行対象のインスタンスを停止し、AMIを作成します。作成したAMIのIDをメモしときます。
3. 変換処理
変換処理を行うインスタンスを新しく起動します。起動の際にEC2のPower User権限を持ったIAM Roleを適用しておきます。
インスタンスが起動したらAWS SDK for Rubyをインストールします。
$ sudo yum groupinstall "Development Tools" $ sudo yum install ruby-devel $ sudo gem install nokogiri $ sudo gem install aws-sdk
pv2hvmをダウンロードして変換処理を実行。
$ wget https://raw.githubusercontent.com/j3tm0t0/pv2hvm/master/pv2hvm.rb
※変換処理を行う際にpv2hvm内部でddコマンドが発行されますが、bsオプションが付加されてない状態で実行されるのでddの実行に結構時間がかかります。そのため↓のようにddコマンドを発行する際にbsオプションを渡すよう変更しました。
"dd if=/dev/xvdm of=/dev/xvdo1", ↓ "dd if=/dev/xvdm of=/dev/xvdo1 bs=256M",
変換処理実行。
$ sudo ruby pv2hvm.rb 2で作ったAMIのID source ami=ami-XXXXXXXX -- prepare volume creating source volume from snapshot : snap-b3f5a535 vol-a5a8d8af created and attached to /dev/sdm creating target volume with size : 31 vol-48a9d942 created and attached to /dev/sdo -- copy disk # parted /dev/xvdo --script 'mklabel msdos mkpart primary 1M -1s print quit' モデル: Xen Virtual Block Device (xvd) ディスク /dev/xvdo: 33.3GB セクタサイズ (論理/物理): 512B/512B パーティションテーブル: msdos 番号 開始 終了 サイズ タイプ ファイルシステム フラグ 1 1049kB 33.3GB 33.3GB primary # partprobe /dev/xvdo # udevadm settle # dd if=/dev/xvdm of=/dev/xvdo1 bs=256M -- install grub # mount /dev/xvdo1 /mnt # cp -a /dev/xvdo /dev/xvdo1 /mnt/dev/ # rm -f /mnt/boot/grub/*stage* # cp /mnt/usr/*/grub/*/*stage* /mnt/boot/grub/ # rm -f /mnt/boot/grub/device.map # printf "device (hd0) /dev/xvdo\nroot (hd0,0)\nsetup (hd0)\n" | chroot /mnt grub --batch Probing devices to guess BIOS drives. This may take a long time. GNU GRUB version 0.97 (640K lower / 3072K upper memory) [ Minimal BASH-like line editing is supported. For the first word, TAB lists possible command completions. Anywhere else TAB lists the possible completions of a device/filename.] grub> device (hd0) /dev/xvdo grub> root (hd0,0) Filesystem type is ext2fs, partition type 0x83 grub> setup (hd0) Checking if "/boot/grub/stage1" exists... yes Checking if "/boot/grub/stage2" exists... yes Checking if "/boot/grub/e2fs_stage1_5" exists... yes Running "embed /boot/grub/e2fs_stage1_5 (hd0)"... 29 sectors are embedded. succeeded Running "install /boot/grub/stage1 (hd0) (hd0)1+29 p (hd0,0)/boot/grub/stage2 /boot/grub/grub.conf"... succeeded Done. grub> # cat /mnt/boot/grub/menu.lst | tee /dev/stderr > /mnt/boot/grub/menu.lst.bak # created by imagebuilder default=0 timeout=1 hiddenmenu title Amazon Linux 2014.09 (3.14.23-22.44.amzn1.x86_64) root (hd0) kernel /boot/vmlinuz-3.14.23-22.44.amzn1.x86_64 root=LABEL=/ console=hvc0 LANG=en_US.UTF-8 KEYTABLE=us initrd /boot/initramfs-3.14.23-22.44.amzn1.x86_64.img title Amazon Linux 2014.09 (3.14.20-20.44.amzn1.x86_64) root (hd0) kernel /boot/vmlinuz-3.14.20-20.44.amzn1.x86_64 root=LABEL=/ console=hvc0 LANG=en_US.UTF-8 KEYTABLE=us initrd /boot/initramfs-3.14.20-20.44.amzn1.x86_64.img title Amazon Linux 2014.09 (3.14.19-17.43.amzn1.x86_64) root (hd0) kernel /boot/vmlinuz-3.14.19-17.43.amzn1.x86_64 root=LABEL=/ console=hvc0 LANG=en_US.UTF-8 KEYTABLE=us initrd /boot/initramfs-3.14.19-17.43.amzn1.x86_64.img # cat /mnt/boot/grub/menu.lst.bak | perl -pe "s/\(hd0\)/\(hd0,0\)/;s/console=\S+/console=ttyS0/" | tee /dev/stderr > /mnt/boot/grub/menu.lst # created by imagebuilder default=0 timeout=1 hiddenmenu title Amazon Linux 2014.09 (3.14.23-22.44.amzn1.x86_64) root (hd0,0) kernel /boot/vmlinuz-3.14.23-22.44.amzn1.x86_64 root=LABEL=/ console=ttyS0 LANG=en_US.UTF-8 KEYTABLE=us initrd /boot/initramfs-3.14.23-22.44.amzn1.x86_64.img title Amazon Linux 2014.09 (3.14.20-20.44.amzn1.x86_64) root (hd0,0) kernel /boot/vmlinuz-3.14.20-20.44.amzn1.x86_64 root=LABEL=/ console=ttyS0 LANG=en_US.UTF-8 KEYTABLE=us initrd /boot/initramfs-3.14.20-20.44.amzn1.x86_64.img title Amazon Linux 2014.09 (3.14.19-17.43.amzn1.x86_64) root (hd0,0) kernel /boot/vmlinuz-3.14.19-17.43.amzn1.x86_64 root=LABEL=/ console=ttyS0 LANG=en_US.UTF-8 KEYTABLE=us initrd /boot/initramfs-3.14.19-17.43.amzn1.x86_64.img # rm -f /mnt/dev/xvdo /mnt/dev/xvdo1 # umount /mnt -- create snapshot of target volume snapshot ID = snap-531142d5 image Id = 新しく作られたAMIのID -- cleanup deleting volumes vol-a5a8d8af deleted vol-48a9d942 deleted
以上で変換処理は終了です。image Id に記載されている新しく作られたAMIのIDをAMIのリストから選択して、t2系のインスタンスを選択して起動すれば完了です。移行処理はほぼpv2hvmが行ってくれるので簡単です。
※ PVとHVMの違い
- PV(準仮想化)
EC2のサービス開始当初から提供されている仮想化方式で、PV-GRUBと呼ばれる専用のブートローダで起動されます。特別なハードウェアの拡張には対応していません。 - HVM(ハードウェア仮想マシン)
完全に仮想化されたハードウェアを備えており、起動は物理マシンのOSと変りなく、ルートデバイスにあるブートローダからデバイス内のカーネルを起動します。PVと違いホスト上のハードウェアへの高速なアクセスをするためのハードウェア拡張が利用可能で、c3系のインスタンスで利用可能なSR-IOVによるパフォーマンスの向上などのメリットが享受できます。
もともとはPVの方が、IO系のハードウェアエミュレートのオーバーヘッドを回避するドライバを活用することでHVMより性能が優れていたようですが、HVMでもそのPVドライバが利用できるようなり、またHVM自体の機能強化により最近では、PVと同等かそれ以上の性能が出せるようになったようです。