あの日見たストレージの性能を僕達はまだ知らない。

MEGAZONE 株式会社 のテック陣「MEGAZONEのゆかいな仲間たち」がおくる、Megazone Japan Advent Calendar 2023 の2日目のエントリーです。

## ご存じですか？インスタンスストア
AWSでEC2インスタンスを利用する時、EC2インスタンスにアタッチするDisk(ブロックストレージ)はEBSを利用することが多いと思います。

しかしAWSのドキュメントを見るとEC2のストレージ項目に「[インスタンスストア](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/InstanceStorage.html "インスタンスストア")」なるものがあります。

インスタンスストア……こいつはナニモノなのか……

## 高性能なストレージなんだ！
一言でいうと「EBSより高性能」だけど「データの長期保存には向かない」ストレージです。
※ここではNVMe SSDのインスタンスストアを前提にします(HDDもあります)

EC2インスタンスにログインしてEBSボリュームを確認すると、物理Diskがアタッチされているようにみえます。しかし実際にはEC2インスタンスとEBSはネットワークで接続されています。
それに対してインスタンスストアはEC2のホストコンピュータに物理的にアタッチされたDiskを使うことができるので、比べると非常に高性能です。

物理サーバを触っていた人なんかは「そうだ……キミが欲しかったんだ！」という気持ちになるかもしれませんね。

## でも弱点がある
EC2を長く使っている人ならホストコンピューターの問題でEC2インスタンスが正常に利用できなくなる、といった事象に遭遇したことがあると思います。そういう時はEC2インスタンスを一度停止して、再び起動すれば正常なホストが利用されるようになり、当然EBSボリュームも今までと同じものがアタッチされるので、停止前のEC2インスタンス環境と同じ状態で利用できます。

インスタンスストアはどうでしょう？

ホストコンピューターに物理的にアタッチされているDiskなので、ホストコンピューターが変わると別のDiskとなってしまうため、それまで利用していたインスタンスストアボリュームは使えなくなります。

[インスタンスストアに関するドキュメント](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/InstanceStorage.html)に「一時的なストレージ」や「一時データを保存」といった長期保存を前提としない記載があるのはこのためなんですね。

## どんな用途に使える？
[インスタンスストアに関するドキュメント](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/InstanceStorage.html)には以下のような記載があります。

> インスタンスストアは、バッファ、キャッシュ、スクラッチデータ、その他の一時的データのように頻繁に変化する情報の一時的なストレージに最適です。また、負荷分散されたウェブサーバーのプールなど、インスタンスのフリート全体で複製する一時データを保存するためにも使用できます。

より高いIOPSやスループットを必要とするケースですね。
計算処理などで膨大なファイルを扱わなければならない場合にもパフォーマンスを発揮します。

## 実際に使ってみよう
インスタンスストアは一部のEC2インスタンスのみ利用可能です。
[インスタンスタイプ一覧](https://aws.amazon.com/jp/ec2/instance-types/)に「インスタンスストレージ」の項目に「NVMe SSD」や「HDD」といった物理Diskの名称が記載されているEC2インスタンスを選ぶ必要があります。

今回はストレージ最適化インスタンスの中の「i3.8xlarge」+「EBS 500GB(gp3)」+「Amazon Linux 2023」のEC2インスタンスを利用します。「NVMe SSD 1900GB」が4つ付いてきます。

「i3.8xlarge」のインスタンスストアはEC2インスタンスを作成しただけでは利用できず、ファイルシステムの作成とマウントが必要です。
[AWSのドキュメント](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/add-instance-store-volumes.html#making-instance-stores-available-on-your-instances)を参考に試してみましょう。

### [1] EC2インスタンスへログイン
SSHやInstance Connectなどを利用してEC2インスタンスにログインします。

### [2] マウント確認

```
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        4.0M     0  4.0M   0% /dev
tmpfs           120G     0  120G   0% /dev/shm
tmpfs            48G  8.6M   48G   1% /run
/dev/xvda1      500G  5.0G  496G   1% /
tmpfs           120G     0  120G   0% /tmp
/dev/xvda128     10M  1.3M  8.7M  13% /boot/efi
tmpfs            24G     0   24G   0% /run/user/1000
```
インスタンスストアである1900GBのストレージは表示されていません。

### [3] ブロックデバイスを表示

```
$ lsblk
NAME      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
xvda      202:0    0  500G  0 disk 
├─xvda1   202:1    0  500G  0 part /
├─xvda127 259:0    0    1M  0 part 
└─xvda128 259:1    0   10M  0 part /boot/efi
nvme1n1   259:2    0  1.7T  0 disk 
nvme0n1   259:3    0  1.7T  0 disk 
nvme2n1   259:4    0  1.7T  0 disk 
nvme3n1   259:5    0  1.7T  0 disk
```
nvme0n1~nvme3n1の4つが1.7Tと表示されているので、これらがインスタンスストアですね。

### [4] ファイルシステムの作成

```
$ sudo mkfs -t xfs /dev/nvme0n1
meta-data=/dev/nvme0n1           isize=512    agcount=4, agsize=115966797 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=463867187, imaxpct=5
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=226497, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
Discarding blocks...Done.
```
nvme0n1だけxfsのファイルシステムを作成します。

### [5] マウントディレクトリの作成

```
$ sudo mkdir /data
```
インスタンスストアボリュームを/dataにマウントするので、マウントディレクトリを作成します。

### [6] インスタンスストアボリュームをマウント

```
$ sudo mount /dev/nvme0n1 /data
```

### [7] マウント確認

```
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        4.0M     0  4.0M   0% /dev
tmpfs           120G     0  120G   0% /dev/shm
tmpfs            48G  8.6M   48G   1% /run
/dev/xvda1      500G  5.0G  496G   1% /
tmpfs           120G     0  120G   0% /tmp
/dev/xvda128     10M  1.3M  8.7M  13% /boot/efi
tmpfs            24G     0   24G   0% /run/user/1000
/dev/nvme0n1    1.8T   13G  1.8T   1% /data
```
「/dev/nvme0n1」の行がマウントされたインスタンスストアボリュームですね。

### [8] 所有者変更

```
$ sudo chown ec2-user:ec2-user /data
```

Amazon Linux 2023のデフォルトのLinux User(ec2-user)で読み書きできるよう/dataの所有者を変更します。
これで/dataとしてインスタンスストアボリュームが利用できます。

## EBSとの比較
EBSとインスタンスストアでどのくらいの差があるのか。
ベンチマークソフトなどで計るのもよいですが、今回は大量のダミーファイル作成コマンドを実行して、完了までの時間を比べてみます。

* start.txtを作成する
* 1MBファイルを10万ファイル作成する
* complete.txtを作成する

こんな感じでお手軽にいきましょう。

### EBSボリュームにダミーファイル作成

```
$ mkdir ~/ebs-data
$ cd ~/ebs-data/
$ touch start.txt && for i in {1..100000}; do dd if=/dev/zero of="dummy_file_$i" bs=1M count=1; done && touch complete.txt
```
ホームディレクトリにダミーファイル作成用の「ebs-data」ディレクトリを作成します。
そのディレクトリに移動して、ダミーファイル作成コマンドを実行します。

```
$ stat ~/ebs-data/start.txt |grep "Birth"
 Birth: 2023-12-01 20:15:22.346223031 +0000

$ stat ~/ebs-data/complete.txt |grep "Birth"
 Birth: 2023-12-01 20:23:30.909140621 +0000
```
処理が完了したらstart.txtとcomplete.txtのタイムスタンプを確認。
8分8秒ですね。

### インスタンスストアボリュームでダミーファイル作成

```
$ cd /data/
$ touch start.txt && for i in {1..100000}; do dd if=/dev/zero of="dummy_file_$i" bs=1M count=1; done && touch complete.txt
```
インスタンスストアボリュームである/dataへ移動して、ダミーファイル作成コマンドを実行します。

```
$ stat /data/start.txt |grep "Birth"
 Birth: 2023-12-01 20:25:48.039948920 +0000

$ stat /data/complete.txt |grep "Birth"
 Birth: 2023-12-01 20:30:40.611511271 +0000
```
4分52秒なので、インスタンスストアの方が分単位で早く完了していますね。

今回は10万ファイルでしたが、これが100万、1000万とファイルが増えた場合、完了までの時間差もドンドン広がります。

ここまでシンプルな処理はあまりないとは思いますが、特定の状況下でDisk I/Oの性能が必要という場合にはインスタンスストアを持つEC2インスタンスの利用を検討するのもよいかもしれません。

## おわりに
インスタンスストアは「i3.large」や「m6id.large」など、largeタイプから用意されています。

もしDisk I/Oの性能が必要なったら思い出してあげて下さい。

インスタンスストアという名を……