Google Compute Engineの鬼速Local SSDを試す

[Google Cloud Platform Advent Calendar 2014](http://qiita.com/advent-calendar/2014/gcp)の12日目の記事です。

1か月ほど前にBeta版がリリースされたGoogle Compute Engine (GCE)の[Local SSD](http://googlecloudplatform.blogspot.jp/2014/10/announcing-beta-for-local-ssd.html)を試してみたので、さっそくレポートしたい。

## Local SSDって何？

GCEではこれまで、[Persistent Disk](https://cloud.google.com/compute/docs/disks)というネットワーク ディスクのみが提供されており、ブートもデータもPDだけでまかなわれてきた。PD上のデータはすべて冗長化されているので、一般的な単体ディスクよりも高い可用性を提供する。

一方で「可用性は普通でよいのでともかく高い帯域とIOPS値を」というニーズに応えるべく新たに提供されたのがLocal SSDだ。特長をまとめると、

* 375GB SSDを1 VMあたり最大4台まで装着可能
* 4台使用時は**680K IOPS** (4K random read)と360K IOPS (4K random write)の性能を提供。PDのおおよそ15倍のリード性能
* PCIe接続のSSD用インタフェース[NVMe](http://marosama.blogspot.jp/2013/07/ssdpcie-ssd.html)に対応
* $0.218/GB/month（2014年12月現在）で、コスパが恐ろしくよい
* どんなタイプのGCEインスタンスでも使える
* [GCEのライブマイグレーション](http://qiita.com/kazunori279/items/c35cbc24c5b93df3ee6b#3-7)にも対応予定。つまり計画メンテナンスでデータが消えたりしない
* データは暗号化される

![Screen Shot 2014-12-11 at 13.43.22.png](https://qiita-image-store.s3.amazonaws.com/0/38290/5467f314-8815-c862-5e0f-6c35425d5fe6.png)

一方で、Local SSDの制約は以下のとおり。

* 一部のゾーン（us-central1-bとeurope-west1-a）では利用不可
* PDのような冗長性やスナップショット機能、rootディスク機能はなく、また単独では作成できないのでGCEインスタンス作成時にLocal SSD作成をオプション指定する必要がある
* NVMe版を使うには専用のDebian 7イメージ（例えば`nvme-backports-debian-7-wheezy-v20141108`など）を用いる。それ以外のOSでは現在のところSCSI版のみのサポート

## 使ってみよう

[ドキュメント](https://cloud.google.com/compute/docs/local-ssd)に書いてある手順ですんなり使えた。GCPプロジェクトの作成やGoogle Cloud SDKのインストール等が済んでいる状態で、以下のコマンドでGCEインスタンスを作成する。

```
$ gcloud compute instances create YOUR_INSTANCE_NAME \
         --machine-type n1-standard-16 \
         --zone us-central1-f \
         --local-ssd interface=nvme \
         --local-ssd interface=nvme \
         --local-ssd interface=nvme \
         --local-ssd interface=nvme \
         --image nvme-backports-debian-7-wheezy-v20141108 \
         --image-project gce-nvme
```

このように、`--local-ssd interface=nvme`というオプションを台数分だけ指定する。上記例は、

* us-central1-fゾーンにタイプn1-standard-16（16コア、60GBメモリ）のインスタンスを作成
* NVMe版のLocal SSDを4台装着
* NVMe版に対応するDebian 7イメージを指定

という意味となる。ここでポイントとなるのは「Local SSDの性能をフルに引き出すには1台あたり4もしくは8コアを割り当てる」という点だ。このSSDは**速い**ので、CPUのコア数が少ないとCPU側がネックとなってしまう。上記のように4台用いる場合は、16コアのGCEインスタンスを割り当てないと、簡単なベンチマークを取るのでさえCPU使用率が高くなりフルな性能は引き出せない。実際にGCE + Local SSD上でApache SparkとTezの性能評価を行ったozaさんによると、SSDの2台構成でも16コアのCPUがサチってしまったそうだ。もはや"ディスク"のスピードではないね。。

もうひとつ、ドキュメントの[Recommended local SSD settings](https://cloud.google.com/compute/docs/local-ssd#recommended_local_ssd_settings)に記載のスクリプト`set-interrupts.sh`を実行しておく。このスクリプトによって、SSDが発生するIRQ（割り込みリクエスト）を各CPUコアに均等に分散させることができる。

## fioで性能測定、752K IOPS・3GB/s

ドキュメントの[Replicating SSD Performance](https://cloud.google.com/compute/docs/local-ssd#replicating_local_ssd_performance)の手順を実行すると、`fio`コマンドを用いたSSD単体の性能測定が可能だ。

しかし単体ではつまらないので、`mdadm`を使って4台のSSDをストライピングしたRAID0を組む。

```
$ sudo /sbin/mdadm --create /dev/md0 --chunk=256 --level=0 --raid-devices=/dev/disk/by-id/google-local-ssd-0 /dev/disk/by-id/google-local-ssd-1 /dev/disk/by-id/google-local-ssd-2 /dev/disk/by-id/google-local-ssd-3 
```

これで`/dev/md0`にソフトウェアRAID0が作成される。さっそく`fio`で性能を測ってみよう。

```
$ sudo fio --time_based --name=benchmark --size=100G --runtime=30 \
--filename=/dev/md0 --ioengine=libaio --randrepeat=0 \
--iodepth=128 --direct=1 --invalidate=1 --verify=0 --verify_fatal=0 \
--numjobs=16 --rw=randread --blocksize=4k --group_reporting
```

結果は以下のとおり。

```
read : io=88170MB, bw=2938.5MB/s, iops=752231 , runt= 30006msec  
write: io=54744MB, bw=1824.2MB/s, iops=466947 , runt= 30013msec 
```

ブロックサイズ4K時のrandom readは**752K IOPS**、random writeは467K IOPSとなった。readの帯域は**3GB/s**。なんかカタログスペックより速い...!

## MySQLでsysbench、4,171 tps

ついでに、MySQLのパフォーマンスも測ってみよう。まずは`/dev/md0`を`/mnt/md0`にマウントしてフォーマットする。

```
$ sudo /usr/share/google/safe_format_and_mount -m "mkfs.ext4 -F" /dev/md0 /mnt/md0
```

つづいて、MySQL 5.6をインストールして、`/mnt/md0`上にdatadirを作成。さらにLocal SSDのサイズやIOPS性能、メモリサイズに合わせてMySQLのパラメータをチューニング...しかし俺はこのあたりの経験が全然ないので、とりあえずこんな感じにしてみた：

```
innodb_buffer_pool_size=50G
innodb_log_file_size=2G
innodb_flush_neighbors=0
innodb_io_capacity=10000
innodb_io_capacity_max=10000
innodb_lru_scan_depth=1024
```

[このブログ](http://ijin.github.io/blog/2014/01/01/mysql-benchmarks-on-aws-i2-instance-ssds/)を参考に、同じ条件でsysbenchを実行してみたところ、以下の結果が得られた。

* read only: 4,171 tps
* read + write: 1,893 tps

今回の構成でのGCE+Local SSDのトータルコストは$1.26/hなので、同じ4K tps程度の性能を得るために他のクラウドサービスを使う場合に比べて、およそ**1/3程度のコスト**となった。コスパいいね！

## まとめ

Local SSDの使い勝手をまとめると：

* 冗長性がなかったり等の制約や、コア数やIRQ設定の最適化は考慮が必要（といっても設定は簡単）。
* 4台でRAID0を組むと752K IOPS・3GB/s出る。速い。
* 素人ベンチの結果、MySQL運用時のtpsあたりのコストは一般的なクラウドサービスに比べて1/3くらいっぽい。

というわけで、Local SSDお試しあれ。

----
Disclaimer この記事は個人的なものです｡ここで述べられていることは私の個人的な意見に基づくものであり､私の雇用者には関係はありません｡