Bah humbug![1]
世間では天皇誕生日の次の日などが執り行われたようですが、皆様いかがお過ごしでしょうか? 今年も一年よい子でいた筆者には、ご褒美に夢のようなプレゼント[2] がやってきました。
筆者の元にやってきた夢のストレージ
「わあい、ioDrive2 Duoだ! ありがとうサンタさん。これ、ずっと欲しかったんだ!」
というわけで2012年最後のレシピは、Ubuntu 12.04日本語Remix上でioDrive2 Duoを動かす方法を紹介します。
[1] 小説「クリスマスキャロル」の主人公であるスクルージ老人が、「 メリークリスマス」に対して言った言葉。「 ふん、クリスマスなんてくだらないね」くらいの意味でしょうか。Wychwood Breweryから同名のクリスマスビールが販売されていることでも有名です。
ストレージ王に、俺はなる!
ioDrive2とは簡単に言ってしまえば、PCIeに接続するSSDの親戚みたいなものです[3] 。速い!大容量!高信頼性!お値段もそれなり!ということで有名ですね。ioDrive2にはMLC/SLCの違いや容量ごとに、いくつかのモデルが存在します。そんな中で今回用意したのは、MLCで2.4TBの容量を持つioDrive2 Duoです。ご家庭のパソコンでも、2TB、3TBはあたりまえのこの時代。SSD最大の弱点といえば、HDDにはまだまだ及ばない容量ですよね。しかしながらioDrive2 Duoのように2.4TBもの容量があれば、十分HDDの代替として、ご家庭のデスクトップ用途でも使えるのではないでしょうか。
なおこのモデルはPCIe x8のバスと、6pinの外部電源[4] が必要なので注意してください。今回筆者はNECのExpress5800/R120d-2M に搭載してみました。
デバイスドライバをインストールする
ioDrive2はSATAのHDDなどとは異なり、物理接続しただけでストレージとして認識されるわけではありません。まずは専用のドライバをインストールする必要があります。ドライバ一式は購入したベンダ、あるいはFusionIOのサイトなどから各自入手してください。ちなみにドライバの対応OSの都合上、Ubuntu 12.10ではなく、Ubuntu 12.04.1を利用しています。
ドライバとユーティリティは、ソースコードとdebパッケージにて提供されています。今回はユーティリティをdebパッケージからインストールし、ドライバモジュールであるiomemory-vslはソースコードから日本語Remix上でビルドしました。
まず、ビルドに必要なパッケージをインストールします。この他にカーネルのヘッダファイルが必要ですが、Ubuntu 12.04には標準でインストールされているので、別途インストールの必要はありません。もしも何らかの理由でインストールされていない場合は、linux-headers-genericパッケージをインストールしておいてください。
ドライバのソースコードは「iomemory-vsl_(バージョン).tar.gz」というファイルです。このアーカイブを展開し、展開されたディレクトリの中でdpkg-buildpackageを実行します。ビルドに成功すると、親ディレクトリに次のようなパッケージが作成されます。
iomemory-vsl-3.2.0-34-generic_3.2.2.869-1.0_amd64.deb
iomemory-vsl-config-3.2.0-34-generic_3.2.2.869-1.0_amd64.deb
iomemory-vsl-source_3.2.2.869-1.0_amd64.deb
パッケージの作成ができたら、iomemory-vslパッケージと、ライブラリであるlibvsl、ユーティリティ群であるfio-ではじまる名前のパッケージをインストールします。詳細は、インストールドキュメント「ioMemory VSL 3.2 User Guide for Linux」の「Building a Debian Installation Package」の節を参考にしてください。
ビルドに必要なパッケージのインストールと、ドライバのビルド
$ sudo apt-get install fakeroot build-essential debhelper
$ tar zxvfiomemory-vsl_3.2.2.869-1.0.tar.gz
$ cd iomemory-vsl-3.2.2.869
$ dpkg-buildpackage -rfakeroot -b
ドライバとユーティリティパッケージのインストール
$ sudo dpkg -i iomemory-vsl-3.2.0-34-generic_3.2.2.869-1.0_amd64.deb fio-util_3.2.2.869-1.0_amd64.deb fio-common_3.2.2.869-1.0_amd64.deb libvsl_3.2.2.869-1.0_amd64.deb
デバイスのチェックとモジュールのロード
インストールが完了したら、まずはfio-pci-checkコマンドを叩いてみましょう。これはPCIバスツリーのエラーや、デバイスのチェックを行うコマンドです。ioDrive2 Duoはその名が示す通り、2つのioDriveが1つのアダプタ上に載っている作りになっています[5] 。そのため次の実行例のように、2つのioDriveが見つかります。
fio-pci-checkでデバイスの状態を確認する
$ sudo fio-pci-check
Root Bridge PCIe 18250 MB/sec needed max
Bridge 00:02.02 (03-07) (8086:3c06)
* Needed 4000 MB/sec Avail 4000 MB/sec
Bridge 03:00.00 (04-07) (1aed:2100)
* Needed 4000 MB/sec Avail 4000 MB/sec
Slot Power limit: 25.0W (25000mw)
clearing corr_err_status_reg (0x2000)
Bridge 04:05.00 (06-06) (1aed:2100)
Needed 2000 MB/sec Avail 2000 MB/sec
clearing corr_err_status_reg (0x2000)
ioDrive 06:00.0 (2001) Firmware 109322
Slot Power limit: 25.0W (25000mw)
Bridge 04:06.00 (07-07) (1aed:2100)
Needed 2000 MB/sec Avail 2000 MB/sec
clearing corr_err_status_reg (0x2000)
ioDrive 07:00.0 (2001) Firmware 109322
Slot Power limit: 25.0W (25000mw)
次に、iomemory-vslモジュールをロードしましょう[6] 。正常にモジュールがロードされると、/dev/fct0と/dev/fct1という2つのデバイスを確認できます。fio-statusコマンドを叩いて、デバイスの状況を見ておきましょう。
モジュールのロード
$ sudo modprobe iomemory-vsl
fio-statusでデバイスのステータスを確認する
$ sudo fio-status
Found 2 ioMemory devices in this system with 1 ioDrive Duo
Driver version: 3.2.2 build 869
Adapter: Dual Controller Adapter
Fusion-io ioDrive2 Duo 2.41TB, Product Number:***-***-****-**-****, SN:*********, FIO SN:*********
PCIe Power limit threshold: 24.75W
Connected ioMemory modules:
fct0: SN:*********-****
fct1: SN:*********-****
fct0 Status unknown: Driver is in MINIMAL MODE:
The firmware on this device is not compatible with the currently installed version of the driver
SN:*********-****
!! ---> There are active errors or warnings on this device! Read below for details.
Located in slot 1 Lower of ioDrive2 Adapter Controller SN:*********
PCI:06:00.0, Slot Number:43
Firmware v7.0.2, rev 108609 Public
Geometry and capacity information not available.
Internal temperature: 46.26 degC, max 46.26 degC
ACTIVE WARNINGS:
The ioMemory is currently running in a minimal state.
fct1 Status unknown: Driver is in MINIMAL MODE:
The firmware on this device is not compatible with the currently installed version of the driver
SN:*********-****
!! ---> There are active errors or warnings on this device! Read below for details.
Located in slot 0 Upper of ioDrive2 Adapter Controller SN:*********
PCI:07:00.0, Slot Number:43
Firmware v7.0.2, rev 108609 Public
Geometry and capacity information not available.
Internal temperature: 48.23 degC, max 48.72 degC
ACTIVE WARNINGS:
The ioMemory is currently running in a minimal state.
ファームウェアのアップデート
前節のように、状況によってはioDrive2がMINIMALモードで動作していることがあります。これはioDrive2のファームウェアと、ドライバのバージョンが対応しない場合に発生する現象です。このような場合は、ファームウェアのアップデートを行いましょう。
モジュールをロードした段階で、ioDrive2は自動的にアタッチされているかもしれません。そのような時はアップデートの前準備として、ioDriveをデタッチしておく必要があります。デバイスのデタッチにはfio-detachコマンドを使います。
ファームウェアは拡張子が「fff」のファイルとして提供されています。このファイルをfio-update-iodriveコマンドの引数に渡すことで、ファームウェアをアップデートすることができます。今回は3.2.2-20121025にアップデートを行いました。
またファームウェアのアップデートには、最低限経由しなければならないアップデートパスが決められています。たとえば今回はバージョン3.2.2にアップデートしましたが、3.2.2へアップデートするためには、あらかじめ2.3.1以上のファームウェアにアップデート済みである必要があります。これらのアップデートパスはリリースノートに記載されていますので、アップデートの実行前にはかならずリリースノートを確認しておきましょう。
ioDriveのデタッチとファームウェアのアップデート
$ sudo fio-detach /dev/fct0
$ sudo fio-detach /dev/fct1
$ sudo fio-update-iodrive fusion_3.2.2-20121025.fff
ioDrive2のフォーマット
使用を開始する前に、ioDrive2をローレベルフォーマットしておきましょう。フォーマットにはfio-formatコマンドを使用します。
ioDrive2のフォーマット
$ sudo fio-format /dev/fct0
/dev/fct0: Creating block device.
Block device of size 1205.00GBytes (1122.24GiBytes).
Using default block (sector) size of 512 bytes.
WARNING: Formatting will destroy any existing data on the device!
Do you wish to continue [y/n]? y
Formatting: [====================] (100%) -
/dev/fct0 - format successful.
$ sudo fio-format /dev/fct1
(...略...)
フォーマットの際には、ioDrive2のブロックサイズを指定することができます。指定しなかった場合、デフォルト値の512バイトが使用されます。
ここで問題になるのが、iomemory-vslの使用するメモリ量です。iomemory-vslはioDrive2への書き込みブロック数に応じてシステムのメモリを使用していきますが、そのメモリ使用量はioDrive2のブロックサイズによって異なります(表参照 ) 。標準の512バイト/ブロックでioDrive2をフォーマットした状態で、2.4TBのストレージ全域を使用しようとすると、22×2400=52800。つまり最悪のケースでは50GB以上のメモリを消費してしまう可能性があることになります。
工場出荷時のioDrive2は、512バイト/ブロックでフォーマットされています。これは512バイト以外のサイズと互換性のないOSが存在するための措置です[7] ので、Ubuntuで使用する上ではブロックサイズを変更しても問題ありません。そこで、もっとも効率のよい4096を指定してフォーマットしなおすとよいでしょう。これで、2.85×2400 = 6840。最大でも7GB弱のメモリ消費で、2.4TBのストレージを使用できることになります。
表 ブロックサイズと1GBあたりの消費メモリ
ブロックサイズ 1GBあたりの消費メモリ
8192 1.59MB
4096 2.85MB
2048 5.38MB
1024 11MB
512 22MB
ブロックサイズ4Kでフォーマットする
$ sudo fio-format -b 4K /dev/fct0
筆者はioDriveの消費メモリと累積読み書きバイト数を計測するmuninプラグインを自作して、実際のリソースの変化を計測してみました。ブロックサイズによる消費メモリ量の違いがよくわかると思います。
図1 ブロックサイズと消費メモリの関係(1)
①は、デフォルトの512バイト/ブロックでフォーマットしたioDrive2(1.2TB)をアタッチした状態です。この場合の消費メモリは約750MBです。
②は、512バイト/ブロックのioDrive2の全域に、データを書き込んでいった際の消費メモリの変化です。書き込みが進むにつれメモリ使用量が増大し、ピークでは1.2GBほどのメモリを消費しています。
③は、ioDrive2を4096バイト/ブロックで再フォーマットして、アタッチしなおした状態です。消費メモリは約140MBまで低下しました。
④は、4096バイト/ブロックのidDrive2の全域に、データを書き込んでいった際の消費メモリの変化です。こちらはピークでも、消費メモリは190MB程度に抑えられています。
アタッチとRAIDの構成
フォーマットが完了したら、デバイスをアタッチしましょう。アタッチはfio-attachコマンドで行います。アタッチが完了すると、fio-statusの出力がDetachedからAttachedに変わり、/dev/fioaと/dev/fiobという、それぞれ1.2TBのブロックデバイスが使えるようになります。あとはこれを/dev/sdaなどと同様に、fdiskでパーティションを切り、/dev/fioa1などにファイルシステムを作成してマウントすれば、ストレージとして使用することができます。
デバイスをアタッチする
$ sudo fio-attach /dev/fct0
$ sudo fio-attach /dev/fct1
$ sudo fio-status
(...略...)
fct0 Attached
(...略...)
fioa State: Online, Type: block device
(...略...)
fct1 Attached
(...略...)
fiob State: Online, Type: block device
標準ではシステムの起動時に、自動的にアタッチされる設定となっています。もしも自動でのアタッチを抑制したいのならば、/etc/modprobe.d/iomemory-vsl.confに、次のオプションを記述してください。
ioDrive2の自動アタッチを抑制する
options iomemory-vsl auto_attach=0
ioDrive2のセッティングはこれで完了ですが、せっかくのDuoモデルです。1.2TBのストレージが2つというのは、なんとも中途半端な感じがしますよね。そこで、mdadmを利用してソフトウェアRAIDを組むことにしました。ioDrive2も、通常のHDDと同じ手順でRAIDを組むことができます。それではRAID0で2.4TBのアレイを作成しましょう。
mdadmのインストールと、アレイの作成
$ sudo apt-get install mdadm
$ sudo mdadm --create /dev/md0 --chunk=256 --level=0 --raid-devices=2 /dev/fioa /dev/fiob
mdadm: /dev/fioa1 appears to be part of a raid array:
level=raid0 devices=2 ctime=Fri Dec 14 16:07:01 2012
mdadm: /dev/fiob1 appears to be part of a raid array:
level=raid0 devices=2 ctime=Fri Dec 14 16:07:01 2012
Continue creating array? y
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.
図2 作成されたRAIDアレイ
作成したアレイのベンチマークを取ってみました。書き込みベンチマークはドライブがまっさらな状態でないと取れないため、こういったタイミングでないとなかなか実行できません。
読み書きともに2500MB/sと、HDDはもとより一般的なSSDと比較しても、かなり高い数値を叩き出しているのがわかると思います。
図3 RAID0を組んだioDrive2 Duoのベンチマーク
このアレイは2TBを越えているので、GPTでパーティションを切ります。ここではGpartedを使い、「 デバイス」 →「 パーティションテーブルの作成」 →「 詳細」からGPTのパーティションを切りました。ファイルシステムはxfsを選択。これもGparted上から作成しました。
図4 Gpartedを使い、GPTパーティションを作成した
図5 xfsでパーティションをフォーマットする
ioDrive2をSwapにする
「ioDriveを積むくらいなら、メモリ増やしたほうがよくない?」
そう思う人もいるかもしれません。たしかに一度メモリ上にデータが乗ってしまえば、ストレージのI/O waitは関係ありません。ですがメモリの搭載量は増えたとはいえ、その容量はせいぜい数十GBから数百GBのオーダーです。メモリに乗りきらないほど大量のデータを扱うケースではどうでしょうか? メモリが不足してスワップが発生すると、パフォーマンスが極端に落ちてしまいますよね。そこで、ioDriveをストレージではなくスワップ領域として使うという方法があります。実はioDrive2は通常のHDDと同じように、スワップパーティションを作ることも可能なんです。
前述の通り、iomemory-vslは書き込みブロックに応じてメモリを消費していきます。ioDrive2をスワップ領域として使用する場合は、使用する可能性のあるメモリをあらかじめ割り当てておく必要があります。このメモリの事前割り当てを有効にするのが、モジュールパラメータのpreallocate_memoryです。
まずスワップとして使用するioDriveデバイスのシリアルナンバーを調べます。その値を、/etc/modprobe.d/iomemory-vsl.confのpreallocate_memoryに記述してから、サーバーを再起動してください。
複数のデバイスをスワップとして使いたい場合は、複数のシリアルナンバーをカンマで区切って指定します。なおアダプタのシリアルナンバーではなく、ioDriveのシリアルナンバーであることに注意してください。具体的には、次のコマンドで求められます。
デバイスのシリアルナンバーを調べる
$ sudo fio-status -Fiom.serial_number /dev/fct1
*********-1111
preallocate_memoryの設定
options iomemory-vsl preallocate_memory=*********-1111
サーバーを再起動したあとは、通常のHDDと同様にパーティションとスワップを作成してください。
スワップの作成と有効化
$ sudo fdisk /dev/fiob
$ sudo mkswap /dev/fiob1
$ sudo swapon /dev/fiob1
$ free
total used free shared buffers cached
Mem: 41155412 34542800 6612612 0 40040 190532
-/+ buffers/cache: 34312228 6843184
Swap: 1176756784 0 1176756784
preallocate_memoryの設定をしていると、デバイスがアタッチされた瞬間に、要求されているメモリが確保されます。搭載メモリ量が少ないサーバーで大容量のスワップを確保してしまうと、メモリが不足しシステムが強制終了したり、プロセスが不安定になるような場合があるので気をつけてください。
たとえば512バイト/ブロックでフォーマットされた1.2TBのioDriveをスワップとして確保してしまうと、システム起動時に22×1200=26400、つまり26GB以上のメモリがiomemory-vslによって使用されてしまいます。もしシステムに実装されているメモリがこれより少なかった場合、システムは起動すらしないことになります。筆者は試しにメモリ搭載量の少ないシステムで2.4TBのスワップを作成してみましたが、アタッチした瞬間にシステムが再起動し、さらに自動アタッチを有効にしたままだったので、再起動後もシステムが正常に上がらないということをやらかしました。くれぐれも注意するようにしましょう。
図6 ブロックサイズと消費メモリの関係(2)
①は、4096バイト/ブロックでフォーマットしたioDrive2(1.2TB)をスワップに指定した場合の消費メモリです。およそ4.1GBのメモリを消費しています。
②は、デフォルトの512バイト/ブロックでフォーマットしたioDrive2(1.2TB)をスワップに指定した場合の消費メモリです。これだけで32GBのメモリを消費しており、実用には耐えません。
スワップを作る際のioDriveのブロックサイズに制限はないため、任意のブロックサイズでフォーマットして利用することが可能です。ですがこのような理由から、もっともメモリ使用効率のよい4096バイト/ブロックでフォーマットすることが推奨されています。
さて、来年のレシピは?
このように、ioDrive2は非常に簡単に使いはじめることができます。ご家庭のDBサーバーの台数を減らしたい人、普通のSSDで満足できない人、ベンチマークに命を賭けてしまっている人などは、ぜひ導入を検討してみてはいかがでしょうか。
さて、これにて2012年のUbuntu Weekly Recipeは最後となります。今年も一年、ご愛読ありがとうございました。
お気づきかと思いますが、今回でレシピは連載255回を迎えました。つまり2013年最初のレシピは、0xでついに3桁目に突入することになります。1月2日のレシピはお正月休みをいただきますが、その翌週には新春&256回特別企画として、ひさしぶりにあの人が執筆を担当する予定となっています。
それではみなさま、よいお年を!