EBS 初期化を高速化するツールを作ってみましたので公開します。fio でやる場合より3倍ぐらい速く動作します。
EBS 初期化とは?
EBS は AWS の標準的な仮想ストレージです。EBS の魅力のひとつにスナップショット機能がありますが、構造上、スナップショットの利用開始直後はパフォーマンスがかなり悪くなります。これはスナップショットの実体が S3 にあり、アクセスがあったブロックから順次ダウンロードされるためです。この構造のため EBS スナップショットからボリュームを作成するとすぐに完了しますが、一度目のアクセスは非常に重いという特性があります。
この問題を回避するためには、一度 dd 等を利用して全ブロックを読み込んでしまえばオーケーです。これを「EBS の初期化」と言います。ただし dd では遅いため、ベンチマークツールの fio を利用して初期化する方法が公式ページで紹介されています。
初期化の無駄をなくすには?
EBS 初期化は全データを読み込まなくてはならたいため、大きなスナップショットだと数時間かかります。しかし、S3 のチャンクサイズはどうやら 512KiB のようであり、1ブロック中の一部でも読み込めばそのブロックの初期化は完了します。この性質を利用すると、数バイトだけ読み込んで 512KiB シークする事を繰り返し、高速に初期化が可能です。これを応用したワンライナーが、stak overflow にポストされていました。
状況にも依存するのですが、fio で初期化するより高速に動作する場合も多いです。
さらに速くするためには?
上記のワンライナーはとても優秀でお世話になったのですが、読み込み毎に dd を起動したり、/dev/null
に出力したりしている等、シェルスクリプトであるが故の無駄が多いのも事実です。そこでこのアルゴリズムを C言語で実装したのが今回のツールです。システムコールは io_submit(2) を利用しており、シングルスレッドで高速に IO を同時発行できるようになりました。
ソースファイルとライセンス
github に置きました。MIT ライセンスです。
ダウンロードとインストール
RPM パッケージを用意しましたので、以下のコマンドでダウンロード・インストールができます。
rpm -ivh https://github.com/matsumoto-sp/ebsinit/releases/download/1.0.3/ebsinit-1.0.3-Linux.rpm
利用方法
コマンドラインに初期化したいデバイスを指定するだけです。以下のように利用します。
ebsinit /dev/nvme2n1
その他、以下の通りいくつかのオプションがあります。
オプション | 機能 |
---|---|
-s, --silent | 進捗表示を行わない |
-l, --syslog | syslog に進捗を出力する |
-h, --help | ヘルプメッセージを表示する |
-v, --version | バージョン番号の表示 |
ベンチマーク
400GiB中、67% 程度を利用している gp2 のボリュームでテストをした所、以下のような結果になりました。
初期化方法 | 時間 |
---|---|
fio | 147m |
上記のワンライナー | 156m |
ebsinit | 41m |
ストライピングとの併用でさらに高速化
LVM 等を利用してストライピングを行うとそれぞれのデバイスを同時に処理できますので、さらに速くなります。120GiB の gp2 のボリュームを8台つなげてストライピングした 950GiB のドライブ(使用率50%程度)は、わずか7分で初期化が終了しました。
なお、ストライピングドライブに適用する場合には、/dev/mapper/
以下のボリュームグループではなく、個々のボリュームそれぞれで実行して下さい。そうしないとストライプサイズの関係で特定のボリュームに偏って読み込みされてしまう場合があり、結果として初期化が正しく行えません。 ebsinit は複数のボリュームを同時に初期化する機能は今はありませんので、ボリュームの数だけ同時起動して下さい。
FSR もお忘れなく!
最後になりましたが、先日公開された AWS の新機能 Fast Snapshot Restore (FSR) は、EBS スナップショットの初期化を不要にする魅力的な機能です。料金が結構掛かる事や初めて利用する時に時間がかかる等の問題がありますが、EBS 初期化の新しい方法だと思います。EBS 初期化で困っている人は、是非 FSR も検討してみて下さい。