【AWS】EC2のディスクI/Oを確認する【EBS】

# はじめに
ITシステムを開発していく中で、システムのパフォーマンスが問題になるケースは多々あると思います。
PoC、開発、負荷試験、本番運用のいずれのフェイズであってもこのような課題は発生し、そのたびにボトルネックの分析と解決は必要になります。

大体において最初は原因がつかめないため、サーバであればCPU利用率、メモリ利用量、ネットワーク帯域、ディスクI/Oなど、およそ考えられうる個所を一通りチェックする必要があります。

AWSのEC2を利用している場合、単純に「念のためEC2のディスクI/Oも確認しといて」と指示しただけでは、十中八九、「EC2のディスクI/Oの値が取れてないんですが」と返ってきます。

毎回口頭で説明するのも効率が悪いので、「これ読んどいて」で済ませるためにこの記事を書きました。

# TL;DR
- **殆どの環境において、EC2のディスクとしてEBSが使われている**
- **CloudWatchにおいて、EBSはEBSとしてのメトリクスが記録される。EC2のメトリクスには含まれない**
- **※重要：「[AWSマイスターシリーズ] Instance Store & Elastic Block Store」[^1]はとても良くまとまっているのでちゃんと読もう**


# EC2で利用できるディスク
EC2ではローカルディスク領域として以下の2種類のものが利用できます。

- Ephemeral Volume
- EBS(Elastic Block Store)

EC2リリース当初はEphemeral Volumeしか利用できなかったのですが、その後EBSが利用できるようになりました。
そしてEBSがルートボリューム（つまり「/」）として利用できるようになり、現在ではEphemeral Volumeは限られた用途でしか使われなくなりました。

## Ephemeral Volume
一部のインスタンスサイズでのみ利用できる領域です。
AWS公式ドキュメントでは、**"Instance Store"（インスタンスストア）**とも呼ばれることもあります。

仮想サーバであるEC2が稼働している物理サーバの、ローカルディスクの一部を間借りするようなイメージです。
EC2インスタンスを停止するとデータは消えます。
詳細は「[AWSマイスターシリーズ] Instance Store & Elastic Block Store」[^1]に詳しいです。

これを利用するためには以下の条件を満たす必要があります。

- InstanceのLaunch時に、Instance Storageが利用できるものを選択する
- "Step 4: Add Storage"の際に、明示的に"Instance Store"を追加する

具体的な画面イメージは下記の通りです。

Step 2: Choose Instance Typeにて、「Instance Storage」に「? x ?? (SSD)」と表示されているものを選択します。
![2017-11-27_01h58_29.png](https://qiita-image-store.s3.amazonaws.com/0/137777/f31ab422-b568-b0ec-27ee-5aee66cd97da.png)

Step 4: Add Storageにて、「Add New Volume」を押してパーティションを追加した後、「Instance Store 0」を選択します。
![2017-11-26_22h47_14.png](https://qiita-image-store.s3.amazonaws.com/0/137777/4d5ae0eb-530b-d45f-3794-c0e2c84a08b0.png)


## EBS(Elastic Block Store)
通常、デフォルトで利用される領域です。

詳細は末尾のリンクにある「[AWSマイスターシリーズ] Instance Store & Elastic Block Store」に詳しいです。
本稿では詳細は割愛します。


# CloudWatchから確認する
CloudWatchのメトリクス上、Ephemeral VolumeはEC2のメトリクスの一部として記録されますが、EBSはEC2とは別のNamespaceで記録されます。
それぞれ下記から参照することができます。

- Ephemeral Volume:
    - EC2->Per-Instance Metrics
- EBS:
    - EBS->Per-Volume Metrics


両方のディスク領域に負荷をかけ、どちらのメトリクスに変化が表れるか確認していきます。

## 検証した環境
Instance Size: m3.medium
OS: Amazon Linux AMI 2017.09

dfとmountの実行結果は下記の通りです。

```bash:dfコマンド
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        1.9G   60K  1.9G   1% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
/dev/xvda1      7.8G 1021M  6.7G  14% /
/dev/xvdb       3.9G  8.1M  3.7G   1% /media/ephemeral0
```

```bash:mountコマンド
$ mount
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
devtmpfs on /dev type devtmpfs (rw,relatime,size=1918920k,nr_inodes=479730,mode=755)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /dev/shm type tmpfs (rw,relatime)
/dev/xvda1 on / type ext4 (rw,noatime,data=ordered)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620,ptmxmode=000)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
/dev/xvdb on /media/ephemeral0 type ext3 (rw,relatime,data=ordered)
```

## 事前準備
以下の2つの作業を実施します。

- Bonnie++をインストールする
- メモリ消費スクリプトを作成する

今回は、ディスクに負荷をかけるためにBonnie++を利用します。
操作するディスク容量に対して空きメモリ容量が大きいと、キャッシュが利用されてしまい、ディスクに最大負荷をかけることができません。

通常、物理メモリの2倍の容量のファイルに対して操作を行う必要がありますが、Ephemeral Volumeでは小さすぎます。
\# m3.mediumの物理メモリは4GB、Ephemeral Volumeも4GBです。

そこで今回は、強制的にメモリを消費した状態でBonnie++を実行させます。
メモリ消費スクリプトは下記に載せておきました。

https://qiita.com/tmiki/items/314103598ba192c26528

上記スクリプトを実行し、メモリを大量に消費している状態にしておきます。
freeコマンド、/proc/meminfo等から確認しておきましょう

```bash:freeコマンド例
$ free
             total       used       free     shared    buffers     cached
Mem:       3855812    3361812     494000         60       9196      98832
-/+ buffers/cache:    3253784     602028
Swap:            0          0          0
```

## Ephemeral VolumeのディスクI/Oを確認
### Bonnie++の実行(Ephemeral Volume)
以下のコマンドでEphemeral Volumeに負荷をかけます。
ローカルのSSDはパフォーマンスが良く、すぐに終わってしまうので、10回連続で実行することにします。

```bash:bonnie++
# bonnie++ -u root -d /media/ephemeral0 -r 1536
```

### CloudWatchメトリクスの確認(Ephemeral Volume)
以下の操作で、Ephemeral VolumeのディスクI/Oを確認することができます。[^2]

- AWS Management ConesoleからCloudWatchを開く。
- 「Metrics」→「EC2」→「Per-Instance Mertrics」をたどり、対象のInstanceIdでフィルタをかける。
- 以下の4つの項目をにチェックを入れ、グラフを表示させる。なお、*Opsは左軸、*Bytesは右軸に表示させると見やすい。
    - DiskReadOps
    - DiskWriteOps
    - DiskReadBytes
    - DiskWriteBytes

![2017-11-27_01h33_57.png](https://qiita-image-store.s3.amazonaws.com/0/137777/91179bce-4a81-cdeb-bb9c-fb20e3f7a0a3.png)



## EBSのディスクI/Oを確認する
### Bonnie++の実行(EBS)
以下のコマンドでEphemeral Volumeに負荷をかけます。
これも10回連続で実行することにします。
今回検証した構成ではそれほどパフォーマンスが良くないので、しばらく時間がかかると思います。

```bash:bonnie++
# bonnie++ -u root -d / -r 1536
```

### EBS ID(EBS Volume ID)を確認する
まず、対象のEBSのEBS IDを調べます。
この例では、EC2にアタッチしているEBSは1つであり、またこれがルートデバイスとなっています。

- AWS Management ConesoleからECを開く
- 「Instances」から、対象のEC2インスタンスを選択する
- 「Root device」のリンクをクリックし、ポップアップを表示させる
- EBS ID（vol-?????????????????）が確認できる

![2017-11-26_22h56_54.png](https://qiita-image-store.s3.amazonaws.com/0/137777/d54257ac-7adb-9fd5-d505-f0f9c10bedb6.png)


### CloudWatchメトリクスの確認(EBS)
EBS IDを確認したら、CloudWatchメトリクスから確認できます。[^3]
ここでは取り急ぎ主要な項目のみ確認します。

- AWS Management ConesoleからCloudWatchを開く。
- 「Metrics」→「EBS」→「Per-Volume Mertrics」をたどり、上記で確認したEBS IDでフィルタをかける。
- 以下の4つの項目をにチェックを入れ、グラフを表示させる。なお、*Opsは左軸、*Bytesは右軸に表示させると見やすい。
    - VolumeReadOps
    - VolumeWriteOps
    - VolumeReadBytes
    - VolumeWriteBytes

![2017-11-27_01h34_04.png](https://qiita-image-store.s3.amazonaws.com/0/137777/997902ac-fea1-7607-b9c7-4a0c0726d607.png)

# まとめ
Ephemeral VolumeおよびEBSに負荷をかけた時間帯と、CloudWatchメトリクスで確認できるグラフの時間帯が一致していることが確認できたかと思います。
殆どのケースではEC2のローカルディスクとしてEBSを利用していると思います。
CloudWatchメトリクスを確認する際は、間違えないように気をつけましょう。

なお本題とは関係ありませんが、ローカルのSSDはやっぱり速いですね。
バッチ処理等で巨大な一時ファイルの生成が必要な場合は、Ephemeral Volumeが必須かと思います。


# 参考URL
[^1]: [[AWSマイスターシリーズ] Instance Store & Elastic Block Store](https://www.slideshare.net/AmazonWebServicesJapan/aws-instance-store-e)

[^2]: [Amazon EC2 のメトリクスとディメンション](http://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/ec2-metricscollected.html)

[^3]: [Amazon EBS のメトリクスとディメンション](http://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/ebs-metricscollected.html)