« vSphere DRSとNutanixの親和性は悪いっていう都市伝説は本当なのかやってみた ~前編~ | メイン | Nutanix 5.0の機能概要(Beyond Marketing) パート4 »

2016/12/20

VMware ESXi - 仮想化環境内のI/Oブロックサイズ

本記事はvExperts Advent Calendar 2016への寄稿も兼ねております。是非アドベントカレンダーの他の記事もお楽しみください。当社からは私とSEの工藤が寄稿します。

本記事の原文はもともとPernixData社のTechnical Support Engineer (TSE)で、現在はPernixData社のNutanix社による買収でNutanix社のSr. Systems Reliability Engineerとして活動を継続しているGuido Hagemann氏によるものです。

VMworld EMEAに参加した際に初めてお会いしましたが、Guidoさんはサポート担当ですので、時間によってはサポートコールを取ってくれて話やメールをした間柄です。

原文を参照したい方はVMware ESXi - I/O Block Size in Virtual Environmentsをご確認ください。情報は原文の投稿時のままの情報ですので、現時点では投稿時の情報と製品とで差異が出ている場合があります。

当社のNutanix社製品についてはこちら。VMware社製品についてはこちら

この記事は仮想化環境内のI/Oサイズまたはブロックサイズに関するものです。これに会いたいする際にはデータベースや他のシステムへの対応のため、ということがほとんどでしょう。Microsoft SQLデータベースを利用する際には64KBでフォーマットされているヴォリュームを利用するか、NTFSにそのように割当を行うのがベストだということはよく知られていますが、これにストレージシステムまで考慮に入れているでしょうか?まだMicrosoft SQLサーバは64KBのブロックのみで操作を行っているとまだ信じているのであれば、これは間違いでです。実際にはSQLデータベースが何を行っているかによって様々なサイズのブロックが生成されています。I/OサイズとNTFSの割り当てサイズ、VMFSブロックサイズ、NFSブロックサイズの間には明確な誤解が有ります。ヴォリュームに関連付けられたそれを支えるストレージシステムはその更に下の物理ディスクやフラッシュを抽象化した構造になっています。このブロクの記事はこの部分に少しだけでも光を当てたいと思っています。以下の図は64KiBのWrite I/Oが仮想化環境の異なるレベルをどのように流れていくのかを示したものです。

Fig145

図1: I/Oのワークフロー

セクタとクラスタ

Windows NTFSファイルシステムに入る前に、セクタとクラスタを理解しておくことが重要です。セクタは物理ストレージのディスク上のもっとも小さな単位です。標準的なセクタのサイズは512バイトで、ハードディスクドライブの登場から利用されています。市場には4096バイトのセクタをもつドライブも有りますが、それでもほとんどのすべての回転ディスクはセクタのサイズとして512バイトを利用しています。

ディスクデータ構造のオーバーヘッドを取り除くため、ディスク上の継続したセクタのグループをクラスタと呼ぶという概念が導入されました。クラスタはファイルやディレクトリのためのディスク割り当ての単位で、アロケーションユニットとも呼ばれています。論理的には4 KiB(4096バイト)のクラスタには8つのセクタ(8 x 512バイト)が含まれています。

フラッシュデバイスはセクタに良く似たページ(サイズは8KiB)でグループ化されており、さらに物理ディスクの世界のプラッターやスピンドルの代わりにブロックやプレーンでグループ化されています。この後方互換性はフラッシュにFlash Translation Layer(FTL - フラッシュ翻訳レイヤ)という名前で組み込まれており、physical page number(PPN - 物理ページ番号)へとLogical Block Address(LBA - 論理ブロックアドレス)を変換されています。ブロックは通常2MiBのデータを格納しており、256 x 8 KiBのページからなっています。

Windows NTFS

WindowsファイルシステムのNTFSはその下のハードディスクのクラスタサイズ、つまり「アロケーションユニットサイズ」に関連付けられています。クラスタサイズの大きさはファイルが利用できるもっとも小さな領域となっています。標準のサイズは4KiBで、アロケーションユニットサイズはディスクフォーマット時に 512、1024、4096、8192、16384、32768、65536バイトで構成することが出来ます。この リンク をクリックしてマイクロソフトが標準のクラスタサイズについてどのように推奨しているかを確認することが出来ます。最後の3つの選択肢は 16K、32K、64Kとして表されていますが、これはKibibyteを簡略化して記載したものですから16Kは実際には16K(16,000)ではなく、16384バイトもしくは16KiB(2^14)であることに注意してください。アプリケーションが非常に小さな512バイトのファイルを継続的に書き込んでいるという例を見てみましょう。結果としてNTFSファイルシステムの容量は無駄になってしまいます。10,000のファイルがあり、ディスクが512バイトと4KiBのアロケーションユニットで作成されている場合を例に取ります。

  • 10,000 x 512 バイトのファイル =  5,120 KiB のスペース利用 / 4 KiBのアロケーションユニットサイズの場合、40,960KiBが利用される
  • 10,000 x 4 KiB のファイル = 40,960 KiB のスペース利用 / 4KiBのアロケーションユニットサイズの場合、40,960 KiB が利用される
最初の例では、たったの5,120 KiBのデータに40,960KiBが利用されます。これは単に4KiBのアロケーションユニットサイズであるからという理由で、2つ目の例ではファイルサイズが4KiBなので完全に一致します。
パフォーマンスの観点からは、回転するディスクは例えばデータベースなどが殆どの場合において64KiBのI/Oを行っており、アロケーションユニットサイズを64KiBに設定している場合には1つのブロックが1つのクラスタに合致するため、単一の64KiBのI/Oを多くの小さなクラスタに分散して処理する必要が無いために、メリットを得ることが可能です。また、メタデータについても効率がよくなり、オーバーヘッドが小さくなります。フラッシュデバイスの場合、パフォーマンスのペナルティを受けることはありません。アロケーションユニットサイズは4KiBですが、大きなファイルを利用するシステムではメタデータの総量はもっと大きくなります。一般的に、フラッシュではパフォーマンスの違いはさほど大きくなりません。私がお話をしてきたほとんどのお客様は標準のアロケーションユニットサイズを利用していました。私自身も出来る限り標準のままにしておくほうが良いと思っています。個人的な意見ですが、特別な理由がない限りアロケーションユニットサイズは4 KiBのままのほうが良いです。ご自身のヴォリュームのシリアル番号、セクター数、アロケーションユニットサイズなどを知りたい場合にはWindows Server上でfsutilを利用すれば以下のように表示されます:
C:\Windows\system32>fsutil fsinfo ntfsinfo c:
NTFS Volume Serial Number :       0x7498f02e98efed14
NTFS Version   :                  3.1
LFS Version    :                  2.0
Number Sectors :                  0x000000000634f7ff
Total Clusters :                  0x0000000000c69eff
Free Clusters  :                  0x000000000001dae3
Total Reserved :                  0x0000000000000fe0
Bytes Per Sector  :               512
Bytes Per Physical Sector :       512
Bytes Per Cluster :               4096
Bytes Per FileRecord Segment    : 1024
Clusters Per FileRecord Segment : 0
Mft Valid Data Length :           0x0000000015fc0000
Mft Start Lcn  :                  0x00000000000c0000
Mft2 Start Lcn :                  0x0000000000000002
Mft Zone Start :                  0x00000000004f2340
Mft Zone End   :                  0x00000000004f2b40
Resource Manager Identifier :     BC106797-18B8-11E4-A61C-E413A45A8CC7

VMFS

Virtual Machine File System(VMFS - 仮想マシンファイルシステム)は仮想マシンをブロックストレージ上に格納できる高度な拡張が可能なシンメトリックなクラスタファイルシステムです。VMFSはSCSIコントローラを利用したDAS(Direct Attached Storage)と、サーバ内のディスク、またはiSCSI(Internet Small Compuer System Interface)、FC(Fibre Channel)そして、FCoE(Fibre Channel over Ethernet)のいずれもを利用する共有ブロックストレージでサポートされています。VMFSを更に深く知りたいと思った場合にはこのリンクの先のSatyam Vaghani氏(VMwareの元CTOであり、PernixDataの元CTO)の論文をご参照ください(VMFS-3をベースにしていますが、基本的には現在も同様です)。ESXi 5.0で導入されたVMFS-5とVMFS-3がどう違うのかという詳細には触れません。すべての人がVMFS-3からVMFS-5へアップグレードしていないとはわかっていますが、もしもアップグレードしていないのであれば、是非アップグレードしてください。これはVMFS-3には多くの制限があるからです。VMFS-3からのアップグレードですべての機能が利用できるわけではありませんが、殆どの重要なものは利用可能です。VMFS-3とVMFS-5の比較についてはVMwareのKB2003813をご参照ください。以下にVMFS-5の新しい機能の主なものをまとめておきます(ESXi 6.0での構成上の最大値はこちらにあります):

  • ブロックサイズの1 MiBへの統一。 以前のVMFS-3では1、2、4、または6MiBのブロックサイズを指定してヴォリュームの作成が可能でしたが、このブロックサイズによってVMDKの最大のサイズが決まっていました。
  • 大きな単一ヴォリューム。 VMFS-5は単一のVMFSファイルシステムとして64TiBをサポートしています(VMDKの最大サイズは 62TiB)。これは以前は2TiB(マイナス512バイト)でした。
  • より小さなサブブロック。 サブブロックは8KiBとなり、VMFS-3の64KiBと比べると、4,000から32,000までその数が増えています。
  • ファイルカウントの増加。 現行のVMFS-5では130,000ファイルがサポートされており、以前のVMFS-3の30,000と比べて大きく増加しています。
  • ATS の改善。 ATS (Atomic Test & Set)がVMFS-5に含まれており、これによってアトミックアルゴリズムによってロック機構が改善されています。ATS は VAAI (vSphere Storage APIs for Array Integration)の一部として含まれており、以前のVMFS-3のSCSI-2予約と比べて大きく改善されています。
上を見て明らかな通り、VMFS-5は1MiBのブロックを利用してファイルシステムを構成しており、そのサイズを変更することはできません。そして、VMDKの最大サイズは62TBです。1KiBよりもちいさい、メタデータなどを格納する非常に小さなファイルについてはファイルディスクリプタの場所(inodeとも呼ばれます)へ格納されます。サブブロックが1KiBの制限に達すると、最大で8KiBサイズのサブブロックが利用されます。8KiBのサイズが使われると1MiBの標準ブロックサイズへと移行が行われます。サブブロックの数は32,000(VMFS-3では4,000)までに制限されているということにはご注意ください。小さなファイルの例としては .VMSD.VMXF.VMX.NVRAM.LOGなどです。標準で1MiBであるから、ということによってVMDKについての多くの誤解であふれています。覚えておいていただきたいのはファイルシステム自身はファイルネームやファイルのタイプは問題にならず、単にサイズを見てファイルを適切に取り扱っているだけということです。当たり前ですが、ほとんどのVMDKにとってこれはファイルの作成時には行われますが、VMDK自身はflatファイルへのディスクリプタであるということを思い出してください。このファイルは1024バイトよりも大きなものになることはほとんどなく、このファイルの名前はVMDKのディスクリプタファイルですから、inodeに格納されるということは理にかなったことなのです。
ですから、順を追って説明すると:
  • 1024 バイト未満 = ファイルディスクリプタの場所(inode)
  • 1024 バイトより大きく、8192 バイト未満 = サブブロック
  • 8192 バイト以上 = 1 MiB のブロック

vmkfstoolsを利用して、ファイルとサブブロックがどのように利用されているかの他、様々な情報を得ることが出来ます :

~ # vmkfstools -Pv 10 /vmfs/volumes/<your_vmfs_volume_name>/
VMFS-5.60 file system spanning 1 partitions.
File system label (if any): <your_vmfs_volume_name>
Mode: public ATS-only
Capacity 805037932544 (767744 file blocks * 1048576), 468339130368 (446643 blocks) avail, max supported file size 69201586814976
Volume Creation Time: Mon Jun 22 16:38:25 2015
Files (max/free): 130000/129472
Ptr Blocks (max/free): 64512/64009
Sub Blocks (max/free): 32000/31668
Secondary Ptr Blocks (max/free): 256/256
File Blocks (overcommit/used/overcommit %): 0/321101/0
Ptr Blocks  (overcommit/used/overcommit %): 0/503/0
Sub Blocks  (overcommit/used/overcommit %): 0/332/0
Volume Metadata size: 807567360
UUID: 55883a01-dd413d6a-ccee-001b21857010
Logical device: 55883a00-77a0316d-8c4d-001b21857010
Partitions spanned (on "lvm"):
naa.6001405ee3d0593d61f4d3873da453d5:1
Is Native Snapshot Capable: YES
OBJLIB-LIB: ObjLib cleanup done.
WORKER: asyncOps=0 maxActiveOps=0 maxPending=0 maxCompleted=0
findコマンドを利用することで、ファイルとディレクトリの数を知ることも出来ます:
  • 1024バイトより大きく、ファイルで8KiBより小さなファイル: ~ # find -size +1024c -size -8192c | wc -l
  • 1 Kibよりも小さなファイル: ~ # find -size -1024c | wc -l
  • ディレクトリ: ~ # find -type d | wc -l
vmkfstools -D(仮想マシンのディレクトリへ移動して)を利用して実際の個々のファイルのブロックサイズを調べることも出来ます(オーナーが0の並びとして表示されていることが有りますが、それはこのホストがそのファイルをロックしているという場合です)。以下では3つのファイル、vm-flat.vmdk(flat ディスク)、vm.ctk.vmdk(チェンジブロックトラッキング)、そしてvm.vmdk(ディスクリプタファイル)が表示されています。flatファイルは40GiBのサイズで、ctkファイルはおよそ2.6MiB、vmdkのディスクリプタファイルは608バイトです。様々な値を見ることが出来ますが、もっとも重要なものは"nb"であり、これは"New Block(新規ブロック)"という意味です。同様に"bs"はblock size(ブロックサイズ)という意味です。flatファイルは17425の新規ブロックと1MiBのブロックサイズ(おおよそ17425 x 1MiBが割り当て)、ctkファイルは3つの新規ブロックです(2621952 = 3 x 1MiB ブロックが割り当て)、そしてVMDKディスクリプタファイルは新規ブロックはありません。なぜ新しいブロックがないのか? それは1KiB未満の小さなファイルはinode自身を利用するからです。
~ # ls -lat *.vmdk*
-rw-------    1 root     root   42949672960 Nov  7 17:20 am1ifdc001-flat.vmdk
-rw-------    1 root     root       2621952 Nov  1 13:32 am1ifdc001-ctk.vmdk
-rw-------    1 root     root           608 Nov  1 13:32 am1ifdc001.vmdk
~ # vmkfstools -D am1ifdc001-flat.vmdk
Lock [type 10c00001 offset 189634560 v 45926, hb offset 3723264
gen 3447, mode 1, owner 5811dc4e-4f97b2d6-8112-001b21857010 mtime 282067
num 0 gblnum 0 gblgen 0 gblbrk 0]
Addr <4, 438, 131>, gen 45883, links 1, type reg, flags 0, uid 0, gid 0, mode 600 len 42949672960, nb 17425 tbz 0, cow 0, newSinceEpoch 17425, zla 3, bs 1048576
~ # vmkfstools -D am1ifdc001-ctk.vmdk
Lock [type 10c00001 offset 189646848 v 46049, hb offset 3723264
gen 3447, mode 1, owner 5811dc4e-4f97b2d6-8112-001b21857010 mtime 282071
num 0 gblnum 0 gblgen 0 gblbrk 0]
Addr <4, 438, 137>, gen 45888, links 1, type reg, flags 0, uid 0, gid 0, mode 600 len 2621952, nb 3 tbz 0, cow 0, newSinceEpoch 3, zla 1, bs 1048576
~ # vmkfstools -D am1ifdc001.vmdk
Lock [type 10c00001 offset 189636608 v 45998, hb offset 3723264
gen 3447, mode 0, owner 00000000-00000000-0000-000000000000 mtime 406842
num 0 gblnum 0 gblgen 0 gblbrk 0]
Addr <4, 438, 132>, gen 45884, links 1, type reg, flags 0, uid 0, gid 0, mode 600 len 608, nb 0 tbz 0, cow 0, newSinceEpoch 0, zla 4305, bs 8192
仮想マシンが行っているI/Oを理解しておくことは重要です。例えば、4KiBはVMFSファイルシステムのブロックサイズを反映しているものではありません。ファイルディスクリプタは固定長のデータアドレスを用いてデータブロックへアクセスします。ファイルサイズが増えるに従って、ファイルディスクリプタに含まれているものが変わっていき、ファイルディスクリプタはポインタブロックを利用して、間接アドレスを使ってアクセスを行います。それぞれのポインタブロックは4KiBのサイズで1024のアドレスを保持できますので、1 MiBのブロックサイズでは 1 GiBへ全体としてアクセス可能となります。VMFSファイルシステムを通り過ぎるとヴォリュームベースの構造と物理メディアへのアクセスが、本記事の最初の図1に記載されているとおりに行われます。この部分はすべてのストレージベンダーで異なっているため、ここでは詳細には取り上げません。

NFS

バックエンドのストレージへと仮想マシンのデータを格納するには様々な方法があります。NFSは定番の成熟した、高可用性を備えた高性能のストレージ実装です。コスト、パフォーマンス、そして管理の簡単さから非常に早くお客様に受け入れられるようになりました。VMFSと比較した際の機能についてもほとんど同等となり、機能がないためにNFSを利用しないということは殆どなくなっています。当たり前ですが、単一ESXiホストや単一ESXiクラスタ内でVMFSとNFSを一緒に使うということにも問題はありません。NFSは分散ファイルシステムプロトコルでもともとは1984年にSun Microsystemsによって開発されました。システムがネットワークを通じてストレージと接続することを非常に簡単に実現し、新たにFCベースのシステムのようにインフラストラクチャへ機材を追加すル必要もありません。vSphere 6.0では2つのヴァージョンのNFSがサポートされています。古いNFS 3とNFS 4.1です。しかし、殆どのお客様はNFS 3の機能がより完全てあるという理由からまだNFS 3を利用しています。NFS 4.1を使う理由はセキュリティ上の理由でしょう。ESXi内部のNFS ネットワークはレイヤ2のVLANを構成して利用されることが多く、外部から直接アクセスされる可能性はありません。これもNFS 3を使い続けるもう一つの理由です。この違いについては詳しくはこちらのVMware vSphere 6.0 ドキュメントセンターか、vmguru.comのNFSのベスト・プラクティスについての素晴らしい記事 をご参照ください。

ですが、この記事はブロックサイズとI/Oについての記事ですから、NFSベースのシステムのブロックサイズの話に切り替えましょう。VMFSとの違いはVMware自身がファイルシステムをフォーマットするのではないという点です。これはファイルシステムの実装自身がストレージベンダーによるもので、ブロックサイズはNFSサーバやNFS装置のもともとの実装によって異なってしまうからです。ブロックサイズ自身はVMFSと同じで、ゲスト仮想マシンへの依存もありません。これはVMDKが単にNFSサーバ/装置上の単独のファイルだからです。NFS上にはサブブロックもありません。VMFSと同様に、ブロックサイズについてはvmkfstoolsで知ることが出来ます。以下に見るようにNFSサーバは4KiBのブロックサイズを利用しています :

~ # vmkfstools -Pv 10 /vmfs/volumes/<your_nfs_volume_name>/
NFS-1.00 file system spanning 1 partitions.
File system label (if any): <your_nfs_volume_name>
Mode: public
Capacity 536870912000 (131072000 file blocks * 4096), 194154864640 (47401090 blocks) avail, max supported file size 18446744073709551615
UUID: fcf60a16-17ceaadb-0000-000000000000
Logical device: 10.14.5.21 /mnt/<your_nfs_mount>/<your_nfs_volume_name>
Partitions spanned (on "notDCS"):
nfs:<your_nfs_volume_name>
NAS VAAI Supported: NO
Is Native Snapshot Capable: NO
OBJLIB-LIB: ObjLib cleanup done.
WORKER: asyncOps=0 maxActiveOps=0 maxPending=0 maxCompleted=0

結論

この記事が皆様のお役に立ち、ブロックサイズが様々異なるレベルで議論されていることや、アロケーションユニットサイズは実際にはアプリケーションのI/Oには何も介在しておらず、仮想マシン自身はVMFSのブロックサイズについてはまったく関知していないことなどをご理解いただけたとしたら幸いです。個人的な意見ですが、環境は可能な限り標準の設定のままにしておくということが良いと思います。アプリケーションごとにちょっとした容量を削減するためにアロケーションユニットサイズを変更したりするのはよした方が良いです。最終的には標準が理にかなっており、異なる構成を入れたとしても1%くらいしか変わらないのでは無いかと思います。いつもどおり、質問、推奨、懸念などがあればご連絡ください。

記事担当者: マーケティング本部 三好哲生 (@miyo4i)

今回も前回に続きvExpertのAdvent Calenderということで、普段は絶対に訳さないようなテッキーな内容をお届け致しました。仮想化におけるブロックサイズはGuidoさんの言うとおり多くの階層でそれぞれ別々の議論になってしまい、そもそもそこを変えても・・・という話は多く出てきます。物理で役に立っていたベスト・プラクティスは仮想マシンの中でやるべきなのか、それともVMFSやNFSのレイヤでやるべきなのか、そもそもストレージシステムでやるべきなのか、、、そうした議論は尽きません。

Guidoさんの言う通り、ESXiという観点からすると、VMFSやNFSのレイヤを見回してもほとんどパフォーマンスに影響のあるようなパラメーターやチューニング操作はありません。アプリケーションの挙動をある程度変えながら、あとはストレージシステム側でのチューニングということに落ち着く事がほとんどです。

せっかくのアドベントカレンダーなので、よく考えずに今までの慣習でやってしまいがちなI/Oチューニングの間違いについての記事を翻訳致しました。いつもながら、Guidoさん、さすがです!