EBS スナップショットと仲良くなりたい、と思ったら coldsnap
結論
EBS スナップショットをダウンロードしたり EBS スナップショットとしてアップロードしたかったら coldsnap を使おう。Rust で書かれてて速そう。
coldsnap どうやって使うの?
Rust で書かれてるので cargo install coldsnap
とかするとインストールできる。
$ coldsnap download snapshot-00000000000000000 snapshot-00000000000000000.img
と実行すると snapshot-00000000000000000.img
に snapshot-00000000000000000
の中身が落ちてくる。凄い!
$ coldsnap upload test.img
と実行すると test.img
の内容でスナップショットができる。凄い!
以下蛇足
EBS スナップショットをダウンロード、何や?
EBS direct API というのがあって EBS スナップショットがユーザーにも扱えるようになってます。 Action が 6 つしかなくてとてもシンプル。
- CompleteSnapshot
- GetSnapshotBlock
- ListChangedBlocks
- ListSnapshotBlocks
- PutSnapshotBlock
- StartSnapshot
AWS CLI で試してみる
下準備
インスタンスの上で試してみます。 EBS ボリュームを作ります。1 GiB で十分なのでそれで。
$ volume_id=$(aws --output text ec2 create-volume --availability-zone $AZ --size 1 --query 'VolumeId')
インスタンスにアッタッチして使えるようにしましょう。
$ token=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 10") $ instance_id=$(curl -s -H "X-aws-ec2-metadata-token: $token" http://169.254.169.254/latest/meta-data/instance-id) $ aws ec2 attach-volume --volume-id $volume_id --instance-id $instance_id --device /dev/sdx --query 'State' "attaching"
インスタンスから見えるようになりました。
$ sudo fdisk -l /dev/nvme7n1 Disk /dev/nvme7n1: 1 GiB, 1073741824 bytes, 2097152 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes
空っぽの EBS ボリュームですがとりあえずスナップショット作ってみます。
$ snapshot_id_1=$(aws --output text ec2 create-snapshot --volume-id $volume_id --query 'SnapshotId')
スナップショットの構成を読んでみる
ListSnapshotBlocks
を使うとスナップショットがどのように構成されているかを表示することができます。
$ aws ebs list-snapshot-blocks --snapshot-id $snapshot_id_1 { "Blocks": [], "ExpiryTime": 1663734712.053, "VolumeSize": 1, "BlockSize": 524288 }
524288 B = 512 KiB のブロックが 0 コで構成されているスナップショットだ、という表示が出ました。
何も書いてないので当然ですね。
BlockSize
は現在のところ 512 KiB だけだそうです。
内容がないと面白くないので少しだけ書いてみます。
$ echo -n wozozo | sudo dd of=/dev/nvme7n1 0+1 records in 0+1 records out 6 bytes copied, 0.0215656 s, 0.3 kB/s
スナップショットを再度取って構成を表示してみると?
$ snapshot_id_2=$(aws --output text ec2 create-snapshot --volume-id $volume_id --query 'SnapshotId') $ aws ebs list-snapshot-blocks --snapshot-id $snapshot_id_2 { "Blocks": [ { "BlockIndex": 0, "BlockToken": "ACIBAfD21rcx+g2ieMHO/YtJBM48t3hp4jkczhv3SIk6UU1GHGMbO++vGwlZ" } ], "ExpiryTime": 1664332577.454, "VolumeSize": 1, "BlockSize": 524288 }
ブロック 1 つで構成されているスナップショットであることが確認できました!!
スナップショットのブロックを取得してみる
このブロックを取得してみましょう。
GetSnapshotBlock
が使えます。
ブロックの指定には BlockToken
等を指定します。
$ aws ebs get-snapshot-block --snapshot-id $snapshot_id_2 --block-index 0 --block-token "ACIBAfD21rcx+g2ieMHO/YtJBM48t3hp4jkczhv3SIk6UU1GHGMbO++vGwlZ" wozozo.dat { "DataLength": "524288", "Checksum": "Z8xlnwXWxcayKPxJmnIdw3A+aC7haNio+dC+KgEAJ8U=", "ChecksumAlgorithm": "SHA256" }
wozozo.dat
にブロックが書き込まれたはずなので確認してみましょう。
$ ls -l wozozo.dat -rw-rw-r-- 1 ubuntu ubuntu 524288 Sep 21 04:35 wozozo.dat $ openssl sha256 -binary wozozo.dat | base64 Z8xlnwXWxcayKPxJmnIdw3A+aC7haNio+dC+KgEAJ8U= $ od -c wozozo.dat 0000000 w o z o z o \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 0000020 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 * 2000000
未使用部分はヌル文字で埋められた 512 KiB のブロックがダウンロードできていました。 チェックサムも合っていますね!
差分を確認してみる
AWS CLI は ListChangedBlocks
もサポートしてるので試してみます。
ディスクの冒頭を上書きして、更にちょっと進んだところにも書いてスナップショットを取ります。
$ echo -n dancho | sudo dd of=/dev/nvme7n1 0+1 records in 0+1 records out 6 bytes copied, 0.0192607 s, 0.3 kB/s ubuntu@ip-172-31-0-38:~$ echo -n dancho | sudo dd of=/dev/nvme7n1 bs=512K seek=16 0+1 records in 0+1 records out 6 bytes copied, 0.0176629 s, 0.3 kB/s ubuntu@ip-172-31-0-38:~$ snapshot_id_3=$(aws --output text ec2 create-snapshot --volume-id $volume_id --query 'SnapshotId')
直前のスナップショットと比較してみると
ubuntu@ip-172-31-0-38:~$ aws ebs list-changed-blocks --first-snapshot-id $snapshot_id_2 --second-snapshot-id $snapshot_id_3 { "ChangedBlocks": [ { "BlockIndex": 0, "FirstBlockToken": "ACIBAV721rcx+g2ieMHO/YtJBM48t3hp4jq01Byg+OVf01PvSs1NvFrpHieR", "SecondBlockToken": "ACIBAWW0tZi8nuBpxLyQyWckOBc0xGOU1ovXWL1fhSTVPL2ZjU6iUhTmtZnk" }, { "BlockIndex": 16, "SecondBlockToken": "ACIBAY3+0jkvSBeEojA1fi37tpi2Z/UkctZcE3GqAy2JKI0HmD1gDMAv5IkF" } ], "ExpiryTime": 1664339386.537, "VolumeSize": 1, "BlockSize": 524288 } $ snapshot_id_3=$(aws --output text ec2 create-snapshot --volume-id $volume_id --query 'SnapshotId')
更新と追記で 2 つのエントリーが確認できました。
結論
こんな感じのことをまるっとやってくれる coldsnap すてき!