あけましておめでとうございます!ナスです。
約3か月ぶりの記事になっちゃいました…

さて、皆さんは EBS のプレウォーミングをご存知でしょうか?
普段から AWS で EC2 を運用されてる方ならご存知かもしれませんね。簡単にいうと、イメージバックアップから EC2&EBS を復元した後の初回アクセスはディスクアクセスが異常に遅くなるので、事前に処理して元通りの速度に戻すことです。詳細や実際の対応方法は AWS ドキュメントに書いてますので、読んでみてください。

スナップショットから復元された EBS ボリュームでファーストタッチレイテンシーの増加を回避するには、初期化と呼ばれるプロセスを実行します。

docs.aws.amazon.com

ただ、どのくらい遅くなるのかがいまいちわからないので、プレウォーミングする前とした後でパフォーマンスを比較してみました。

-- テストした環境 --

インフラ環境

インスタンスサイズ:m4.large
EBS サイズ:50 GiB
EBS タイプ:gp2 (汎用 SSD)
OS:Amazon Linux 2.0 (2017.12) LTS Release Candidate
RDBMS:Postgresql 9.2.23(インストールしただけの状態)

パフォーマンス計測用データ

↓この SQL で適当に作りました。

create table testtable as select s, md5(s::text) from generate_series(1,10000000) s;
select datname, pg_size_pretty(pg_database_size(datname)) from pg_database;
  datname  | pg_size_pretty
-----------+----------------
 postgres  | 718 MB

-- 測定結果 --

テスト環境を作った直後

事前に準備されている AMI から作成した EC2 インスタンスはプレウォーミングが必要ないので、ひとまずこれを通常時のパフォーマンスとします。

dd if=/dev/xvda of=/dev/null bs=1M

51200+0 records in
51200+0 records out
53687091200 bytes (54 GB) copied, 952.779 s, 56.3 MB/s

一応、select count(*) も測定しておきます。

select count(*) from testtable;
:
815.960 ms

AMI 作成後に復元した EC2 (1台目)

まずは dd コマンドでプレウォーミングしつつ、かかる時間を計測しましょう。

dd if=/dev/xvda of=/dev/null bs=1M

51200+0 records in
51200+0 records out
53687091200 bytes (54 GB) copied, 1220.06 s, 44.0 MB/s

うーん、通常時のだいたい8割くらいの速度&時間ですかね。

select count(*) from testtable;
:
11139.971 ms

クエリについては 800 ms 前後のものはキャッシュからの応答時間っぽいので、ディスクアクセスのパフォーマンスはこれがベースになりそうです。実際にもう一回同じクエリを投げると、

select count(*) from testtable;
:
808.717 ms

となるので、ディスクアクセスしたクエリのベースの応答時間は約 11 秒です。

AMI 作成後に復元した EC2 (2台目)

今後は dd コマンドを実行せずにクエリを実行してみました。

select count(*) from testtable;
:
103002.002 ms

遅い…最初は WiFi が切れたか固まったかと思いました。が、悩んでいるうちに結果が返ってきたのでよかった…103 秒なので、プレウォーミングした時と比べてざっくり 10 倍の時間がかかっていますね。一応、もう一回クエリを投げると、

select count(*) from testtable;
:
814.876 ms

と 1 秒未満で返ってきたので、ちゃんとキャッシュされたようです。

再起動や停止/起動ではプレウォーミングは必要か

ここまできたらちゃんと確認しないと気がすまないのでやってみました。
まずは dd 実行後の EC2 インスタンスを再起動して、クエリを投げてみました。

select count(*) from testtable;
:
11130.247 ms

dd 実行後の数値とだいたい同じですね。今度は、EC2 インスタンスを停止してから起動してみました。

select count(*) from testtable;
:
11148.881 ms

うん、さっきとだいたい同じ数値ですね。というわけで、EBS プレウォーミングはバックアップ用途で作成した AMI や EBS スナップショットから復元した場合に限りしたほうがいい、ということがなんとなくわかりました。(他にもプレウォーミングが必要な場面はあるかと思いますが、パッとでないので…

まとめ

EBS プレウォーミングをしないと、通常運用時の 10 倍の時間がかかってしまうことが確認できました。10 倍はあくまで今回のテスト結果なので、実際のところは環境やデータサイズ等によって変わると思うので、一回くらいはテストしておきたいところですね。
障害発生時などで EC2 インスタンスを AMI から復元することがあると思いますが、復旧できたと思ったら今度はパフォーマンスが低下しすぎて慌てふためく、なんてことも想像できますね…
そんなことにならないよう、障害からの復旧手順に EBS プレウォーミングを組み込むか、パフォーマンス低下することを見越してなんらかの手を打つか、初回だけだと思ってでんと構えるか、とにかくこれは知っていることが重要だと思いました。頭にこのことが入っていれば、何かあってもなんとかなるんじゃないでしょうか。

元記事はこちら

EBS のプレウォーミングがある時ない時 [cloudpack OSAKA blog]