IDCFクラウドのオールフラッシュストレージって速いの？

この記事は、IDCフロンティアAdvent Calendarの12月22日分の記事となります。


2015年11月10日にIDCFクラウド [西日本リージョンがリリース](http://www.idcf.jp/cloud/spec/region_zone.html#west) され、大きな特徴として「オールフラッシュ　クラウド」と書かれています。同日に開催されました戦略発表会でもオールフラッシュについて少しお話させていただきました。（当日の様子は[こちらの記事](http://ascii.jp/elem/000/001/076/1076160/)などをご覧ください。）
今回、そのオールフラッシュストレージの採用や基盤設計全般を担当した中の人から、西日本リージョンのストレージ性能の値や、リリース前に行っている性能試験の一部について解説いたします。


# ストレージの性能試験の種類
ストレージの性能試験にはいろいろなやり方があり、それぞれ測っている値やその意味が異なります。極言してしまえば、実際のアプリケーションとデータ（データベースなど）でアプリケーションに負荷をかけないと本当の性能はわかりません。
とはいえ、ある程度の指標は事前に欲しいので、いくつかのストレージ読み書きパターンを再現させて、試験を行うことになります。
ストレージ読み書きのパターンには以下のようなパラメータがあります。（これ以外にもいくつかあります。）

> * ストレージへの**Read**か**Write**か
> * **シーケンシャル**か**ランダム**か
> * 1回の読み書きあたりのデータサイズ
> * 読み書き対象ファイルのサイズ

これらを組み合わせて試験パターンを作ります。私が実際にストレージの性能を測定する際は5つくらいのパターンで試験を行い、ストレージの特徴を把握するようにしています。おかげで、最近では性能試験の結果を見ることで、どの事業者がどこのストレージ製品もしくはソフトウェアを使っているのか、何となくわかるようになってきました。例えば・・・

1. 対象ファイルサイズを変えてシーケンシャルRead試験を行うと、ストレージのReadキャッシュサイズがわかる。
2. 同様にシーケンシャルWrite試験を行うと、ストレージのWriteキャッシュサイズがわかる。
3. ランダムRead試験を、大きなサイズのファイルに対して行うことで、キャッシュにヒットしないときの性能や使っているドライブ（SATA, SAS, SSDなど）が分かる。
4. ランダムWrite試験を大きなサイズのファイルに対して行うことで、ストレージコントローラーのCPU性能をある程度知ることができる。

# 負荷試験環境の準備
ストレージ性能が求められるアプリケーションとしてはデータベースが一番思いつくかと思います。データベースを動かす仮想マシンでは大抵ランダムWrite処理がほとんどとなります。これはデータベースソフトがRead処理はデータをメモリ上にキャッシュすることが多いためです。そこで、今回はランダムWrite性能に絞って、実際に試験したデータを見てみたいと思います。

## 負荷試験ツール
私は普段、[FIO]("http://git.kernel.dk/?p=fio.git;a=summary")をツールとして使っています。頻繁に試験を行うので、普段は負荷試験を行うためのVMイメージをOVA形式で持っています。中身は、

* OSはCentOS 6.4 64bit
* fio 2.0.13  (ちょっと古い・・・)
* 負荷試験のためのfio設定ファイル
* 負荷試験項目を一通り実行するためのシェルスクリプト
* 仮想マシンのサイズは8CPU, 16GB Memory

fioのインストール手順についてはすでに解説された記事があちこちにありますので、ここでは割愛します。

## 負荷試験を実行するOSとファイルシステムチューニング
fioのインストールと設定ファイルの準備ができたら、次は負荷試験対象のファイルシステムの準備をします。まず、IDCFクラウドのポータル画面でボリュームの追加とアタッチを行います。今回は10GBのファイルを作りたいので、それより大きい15GBくらいで作成します。そして負荷試験用仮想マシンにアタッチします。
次に仮想マシン内でOSを再起動するか以下のコマンドを実行して追加したDiskを認識させます。

```
# echo "- - -" > /sys/class/scsi_host/host0/scan
```

その後<code>/dev/sdb</code>をext4でフォーマットします。

```
# fdisk /dev/sdb
n
p
1


w
# mkfs.ext4 /dev/sdb1
```

フォーマットまで完了したら、<code>/etc/fstab</code>に以下の行を追加し、マウントオプションの設定を行います。

```
/dev/sdb1   /mnt    ext4  noatime,nobarrier,nodiratime 1 2
```
<code>/etc/fstab</code>に追記した内容でマウントするため、<code>mount -a</code>コマンドを実行します。

負荷試験対象がフラッシュストレージなので、IOスケジューラをnoopに変更するため、カーネルパラメータの変更を行います。

```
# echo noop > /sys/block/sdb/queue/scheduler
# cat /sys/block/sdb/queue/scheduler
[noop] deadline cfq 
```

再起動後も有効にするために、<code>/boot/grub/grub.conf</code>の<code>kernel=・・・</code>の行の最後に<code>elevator=noop</code>と追記します。
上記のIOスケジューラーの設定は一般的にSSD向けのチューニングとして行われるものです。

## 負荷試験対象ファイルの作成
fioではWriteの試験の際は空のファイルを生成して試験を開始してしまうため、1回目と2回目以降で性能がかなり変わってしまいます。逆にReadの試験の際は、最初にランダムなデータで埋めたファイルを生成してから試験を開始します。そこで、まずはファイル生成のためだけにRead試験を一度行います。そのためのfio設定ファイルは以下の通りです。

```
[global]
rw=read
size=10g
runtime=1
ioengine=libaio
iodepth=1
direct=1
bs=1M
group_reporting
time_based

[cpu0]
cpus_allowed=0

```

上記のファイルを負荷試験用ボリュームをマウントした<code>/mnt</code>以下に作成し、
fioによる負荷試験を行います。

```
# cd /mnt
# fio seqread.fio
```

上記試験を行うと、10GBのファイルが生成されます。以上で負荷試験を行う準備が整いました。

# IDCFクラウド西日本リージョンの負荷試験結果

ランダムWrite試験をする際のコンフィグファイルは以下のような物を使います。

```
[global]
rw=randwrite
size=10g
runtime=300
ioengine=libaio
iodepth=32
direct=1
bs=4k
group_reporting
time_based

[cpu0]
cpus_allowed=0

```

負荷試験準備を行った<code>/mnt</code>以下に上記の設定ファイルを置き、fioコマンドで負荷試験を行います。
4KBランダムWriteのIOをQueue Depth 32で10GBのファイルに対して実施した際の試験結果は以下の通りです。

```
# fio write.fio
cpu0: (g=0): rw=randwrite, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=32
fio-2.1.10
Starting 1 process
Jobs: 1 (f=1): [w] [100.0% done] [0KB/89372KB/0KB /s] [0/22.4K/0 iops] [eta 00m:00s]
cpu0: (groupid=0, jobs=1): err= 0: pid=2913: Tue Dec 22 20:10:59 2015
  write: io=27153MB, bw=92682KB/s, iops=23170, runt=300002msec
    slat (usec): min=3, max=2209, avg= 9.67, stdev= 4.20
    clat (usec): min=395, max=104190, avg=1369.57, stdev=1031.23
     lat (usec): min=402, max=104198, avg=1379.42, stdev=1031.25
    clat percentiles (usec):
     |  1.00th=[  596],  5.00th=[  716], 10.00th=[  796], 20.00th=[  908],
     | 30.00th=[ 1012], 40.00th=[ 1112], 50.00th=[ 1208], 60.00th=[ 1320],
     | 70.00th=[ 1448], 80.00th=[ 1624], 90.00th=[ 1912], 95.00th=[ 2256],
     | 99.00th=[ 4128], 99.50th=[ 8896], 99.90th=[16064], 99.95th=[17792],
     | 99.99th=[24960]
    bw (KB  /s): min=15377, max=108432, per=100.00%, avg=92709.93, stdev=10126.26
    lat (usec) : 500=0.06%, 750=7.01%, 1000=21.65%
    lat (msec) : 2=62.97%, 4=7.29%, 10=0.70%, 20=0.30%, 50=0.03%
    lat (msec) : 100=0.01%, 250=0.01%
  cpu          : usr=7.54%, sys=26.23%, ctx=1661146, majf=0, minf=27
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=100.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
     issued    : total=r=0/w=6951205/d=0, short=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
  WRITE: io=27153MB, aggrb=92682KB/s, minb=92682KB/s, maxb=92682KB/s, mint=300002msec, maxt=300002msec

Disk stats (read/write):
  sdb: ios=0/6949400, merge=0/5, ticks=0/9313606, in_queue=9311214, util=100.00%
```


このように、数万IOPSのストレージ性能を持つ仮想マシンが手軽に利用できるようになりました。ぜひ、試しに触ってみていただければと思います。