はじめに
AWS EC2 のスナップショットからインスタンスのボリューム (volume) を復元して起動させるまでの手順の覚書です。
これは、インスタンスのボリューム (volume) が1つのみのものなのでご注意ください。
昔のラックに収められていたサーバの HDD を差し替えをした人なら、なんとなく感覚がわかるんじゃないか(笑
と思います。
このスクリプトを実行するときは事前に、「インスタンスID」と「スナップショットID」を取得しておく必要があるのでご注意ください。
簡単な手順は以下になります。
- インスタンスを停止
- インスタンスに割り当たっている root デバイス名を取得
- 上記の root デバイス名のボリューム (volume) IDを取得
- インスタンスの root デバイスをデタッチ
- スナップショットからボリューム (volume) を復元
- 復元したボリューム (volume) の ID を取得
- インスタンスの root デバイスにボリューム (volume) をアタッチ
- インスタンスを開始
実際の実行
インスタンスの停止
まずは、復元するインスタンスを停止します。
aws ec2 stop-instances --instance-ids=<<<インスタンスID>>>
インスタンスに割り当たっている root デバイス名を取得
インスタンスに割り当たっている root デバイス名を取得します
※) 物理的な HDD と思えばいいかと
aws ec2 describe-instances \
--instance-ids=<<<インスタンスID>>> \
--query "Reservations[].Instances[].RootDeviceName" --output text
おそらく以下のような値が返ってくるかと思います(違う可能性もあります)
/dev/sda1
インスタンスのボリュームID を取得
root デバイスに割りあっているボリューム (volume) ID を取得します。
※) まぁ、HDD でいくとパーティションみたいなもんです。ここでは 1HDD = 1ボリューム(volume) にして簡単にしています。
`aws ec2 describe-instances \
--instance-id <<<インスタンスID>>>\
--query "Reservations[].Instances[].BlockDeviceMappings[?DeviceName==\<<<上記で出力された root デバイス名 (/dev/sda1 とか)>>>\`].Ebs.VolumeId" --output text`
おそらく、以下のような値が返ってくるかと思います(xxxx は半角英数字)
vol-xxxxxxxxxxxxxxxxx
インスタンスの root デバイスをデタッチ
上記で出力されたボリューム (volume) をデタッチします。 ここでは root デバイスになります
※) デバイスを umount するって言ったらわかりやすいですかね。 root デバイスを umount するので、実行したらインスタンスは 2 度と起動できませんw (マウントすれば、動作するけど)
aws ec2 detach-volume \
--instance-id <<<インスタンスID>>>\
--volume-id <<<上記で取得したインスタンスのボリューム (volume) ID>>>
スナップショットからボリューム (volume) を復元
スナップショットからボリュームを復元します。
availability-zone は、(この文章を読んでいるのは)日本だと思うので ap-northeast-1 ではないでしょうか
リージョンが合わないと復帰できないので、合わせるようにしてください。
まぁ、だいたいは ap-northeast-1a でしょうが。。。
aws ec2 create-volume \
--availability-zone ap-northeast-1a <<<ここはリージョンをあわせてください>>>
--snapshot-id <<<スナップショットID>>>
--tag-specifications "ResourceType=volume,Tags=[{Key=Name,Value=<<<ボリュームの名前をつけるので適当な文字列(あとでこの名前で復帰するボリュームを検索します)>>>]"
復元したボリューム (volume) の ID を取得
上記で復元したボリューム (volume) の ID を取得します。
取得する際、ボリューム (volume) につけた名前で検索をします。
aws ec2 describe-volumes \
--filters Name=tag:Name,Values=<<<ボリュームの名前>>> \
--query "Volumes[].VolumeId" \
--output text
おそらく、以下のような値が返ってくるかと思います(xxxx は半角英数字)
これが、復元したボリューム(のID) です。
vol-xxxxxxxxxxxxxxxxx
復元したボリューム (volume) をインスタンスにアタッチ
※) サーバに HDD をはめ込んでデバイスをマウントするわけですw
aws ec2 attach-volume \
--device <<<root デバイス名>>>
--instance-id <<<インスタンスID>>> \\
--volume-id <<<復元したボリューム (volume) のID>>>
インスタンスの起動
最後にインスタンスを起動します
aws ec2 start-instances --instance-ids=<<<インスタンスID>>>
不要なボリュームを削除
もし、復元するときにデタッチしたボリュームが不要な場合は削除しちゃいましょう
※) どんどんボリュームが増えて、見た目上わけわからんくなるので。。。
aws ec2 delete-volume --volume-id <<<デタッチしたボリューム ID>>>
まとめ
上記を bash スクリプトにすると以下のようになります。
スクリプト内なので「`」をエスケープしないといけないとかあるので「\」が若干増えているとことがありますw
#!/bin/bash
DATE=`date "+%Y%m%d%H%M%S"`
INSTANCE_ID=i-xxxxxxxxxxxxxxxxx
SNAP_SHOT_ID=snap-xxxxxxxxxxxxxxxx
# インスタンスを停止
aws ec2 stop-instances --instance-ids=${INSTANCE_ID}
# インスタンスが停止するまで待機
aws ec2 wait instance-stopped --instance-ids=${INSTANCE_ID}
# root デバイス名取得
INSTANCE_ROOT_DEV=`aws ec2 describe-instances \
--instance-ids=${INSTANCE_ID} \
--query "Reservations[].Instances[].RootDeviceName" \
--output text`
# root デバイスの volume 名を取得
ROOT_DEV_VOLUME=`aws ec2 describe-instances \
--instance-id ${INSTANCE_ID} \
--query "Reservations[].Instances[].BlockDeviceMappings[?DeviceName==\\\`${INSTANCE_ROOT_DEV}\\\`].Ebs.VolumeId" \
--output text`
# root デバイスの volume をデタッチ
aws ec2 detach-volume --instance-id ${INSTANCE_ID} --volume-id ${ROOT_DEV_VOLUME}
# スナップショットから volume 復元
RESTORE_VOLUME_TAG_VALUE="instance_restore_${DATE}"
aws ec2 create-volume \
--availability-zone ap-northeast-1a \
--snapshot-id ${SNAP_SHOT_ID} \
--tag-specifications "ResourceType=volume,Tags=[{Key=Name,Value=$RESTORE_VOLUME_TAG_VALUE}}]"
# volume 復元まで待機
aws ec2 wait volume-available \
--filters Name=tag:Name,Values=${RESTORE_VOLUME_TAG_VALUE}
# root デバイスに vlolume をアタッチ
aws ec2 attach-volume --device ${INSTANCE_ROOT_DEV} --instance-id ${INSTANCE_ID} --volume-id ${RESTORE_VOLUME_ID}
# インスタンスを開始
aws ec2 start-instances --instance-ids=${INSTANCE_ID}
# 不要な volume を削除
aws ec2 delete-volume --volume-id ${ROOT_DEV_VOLUME}
おわりに
インテリジェンスにスナップショットやインスタンスの ID を取得して実行する方法ではないので、事前にある程度、情報をまとめておく必要がありますので、若干めんどくさいです。
そのめんどくさいのは、今後改善していきたいとは思ってます。