ストレージ使用状況の分析
ストレージ使用状況の分析にあたっては、OS上でどのような仕組みでI/Oが処理されるかを知っておくことが大事です。Linuxカーネル内部ではブロック単位でI/Oが行われるため、OS上で認識されるストレージはブロックデバイスと呼ばれています。
ここでは、次のポイントを押さえておきます。
- I/O処理のおおまかな流れ
- ファイルシステムとブロックデバイスの対応関係
- ブロックデバイスのI/O状況の計測
I/O処理のおおまかな流れ
アプリケーション(ユーザプロセス)がファイルやディレクトリに対してリード処理やライト処理を行うと、ファイルシステムを経由してストレージへI/Oが発行されます。このI/O処理のおおまかな流れは、次のようになります。
上図の各番号で行われる処理
① ユーザプロセスがファイルシステムに対してリード処理やライト処理を行うと、内部的にread
やwrite
のシステムコールが発行される
② ファイルシステム層では、次表のような動作が行われる
処理 | 動作の説明 |
---|---|
リード | 必要データがファイルシステム層のディスクキャッシュに存在する場合、ディスクキャッシュから読み込む。そのため、I/Oは発生せず、ユーザプロセスに応答が戻る。必要データがディスクキャッシュに存在しない場合(またはダイレクトI/Oモードの場合)、ストレージから読み込む。そのため、I/Oが発生する |
ライト | ファイルシステム層のディスクキャッシュに書き込み、ユーザプロセスに応答が戻る。書き込まれた分はDirtyと呼ばれ[2]、しばらくしてからバックグラウンドでflushカーネルスレッドにより書き出される。したがって、I/Oが発生するタイミングはユーザプロセスがライト処理を行ったタイミングではなく、Dirtyが書き出されたタイミングとなる。なお、ダイレクトI/Oモードの場合、キャッシュを経由せずに書き出しが行われるため、即座にI/Oが発生する |
③ ファイルシステム層から汎用ブロック層へ、bio(ブロックI/O)単位によるI/O要求が行われる
④ I/Oスケジューラ内部のキューにbioが格納される。ここではなるべく物理I/Oが効率的となるよう並べ替えやマージが行われ、ある程度bioがたまるまでI/O発行を待つ
⑤ I/Oスケジューラ内部のキューからbioが取り出され、デバイスドライバへI/O要求が行われる
⑥ デバイスドライバを経由して、データ転送およびストレージ上で物理I/Oが処理される(またはストレージのキャッシュにアクセスする)
⑦ I/O処理が完了すると、完了通知とともに応答が戻る
ここで、応答時間として見落としがちなのは、④のI/Oスケジューラ内部のキューでI/O発行が待たされる部分です。例えば、Red Hat Enterprise Linux(以下、RHEL)5およびRHEL6におけるデフォルトのI/Oスケジューラである「cfq(Completely Fair Queueing)」は低速ハードディスク向けといえます。ハードディスクの磁器ヘッド移動を極力抑えることを目的としてI/O最適化処理やI/O発行タイミングが調整されますが、この挙動によって待たされやすくなり、RAID構成やSSDおよびフラッシュアレイなど高速なストレージを採用している環境では、逆にI/O待ちを生じさせる要因になってしまいます。RHEL7からは、デフォルトのI/Oスケジューラは遅延回避を目的とした「deadline」へと変更となり、性能が改善されました[3]。特にライト処理が多いデータベースなどのサーバでは、I/Oスケジューラの選定は重要といえるでしょう。
注
[2]: Dirty量は/proc/meminfoから確認できます。その方法については前回の記事をご覧ください。
[3]: 参考資料:米Red Hat「Using the Deadline IO Scheduler」
ファイルシステムとブロックデバイスの対応関係の確認
ファイルシステムを経由してストレージへ発行されるI/Oの状況は、iostat
コマンドで計測できます。しかし、iostat
コマンドはファイルシステム層ではなく、下位レイヤーとなる汎用ブロック層を計測対象とします。そのため、iostat
コマンドを使ってI/Oの状況を分析するには、まずファイルシステムとブロックデバイスの対応関係を把握しておく必要があります。
ファイルシステムとブロックデバイスの対応関係は、「df -k
」コマンドおよびlsblk
コマンドで確認できます[4]。次に示すのは、両コマンドの出力結果の例です。
$ df -k Filesystem 1K-blocks Used Available Use% Mounted on /dev/mapper/VolGroup-lv_root 37797400 10717820 25159580 30% / tmpfs 2988704 80 2988624 1% /dev/shm /dev/sda1 495844 56263 413981 12% /boot $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 41G 0 disk ├sda1 8:1 0 500M 0 part /boot └sda2 8:2 0 40.5G 0 part ├VolGroup-lv_root (dm-0) 253:0 0 36.6G 0 lvm / └VolGroup-lv_swap (dm-1) 253:1 0 3.9G 0 lvm [SWAP] sr0 11:0 1 1024M 0 rom
NAME列とMOUNTPOINT列から、ブロックデバイスに対応するファイルシステム(マウント先ディレクトリ)を確認します。上記の出力結果からは「/boot」「/」「SWAP」は、同一ブロックデバイス「sda」に収容されていることが分かります。なお、「dm-0」や「dm-1」はデバイスマッパーと呼ばれる論理ボリュームです。
このように、1つのブロックデバイスには複数のファイルシステムを収容できますが、いずれかのファイルシステムで大量I/Oが発生すると、同じブロックデバイスに収容されているファイルシステム全てが大量I/Oに伴う負荷影響を受けることになります。このような観点からも、ブロックデバイスにどのファイルシステムが収容されているかを把握しておく意味があります。
注
[4]: RHEL5では「df -k
」「cat /proc/swaps
」「cat /proc/partitions
」「ls -l /dev/mapper
」「lvs
」「pvs
」といった複数のコマンドを組み合わせて確認します。