「iostatで%utilが高いのは分かったが、これはもう限界なのか、まだ余裕があるのか判断できない……」
そのディスクの「本来の最大性能」を知らないまま障害対応しても、判断の根拠が曖昧になります。ベンチマーク値がなければ「%util 80%が普通なのか危険水域なのか」を判定できないのです。
この記事では、Linuxサーバーのディスクパフォーマンスを定量評価するためのベンチマークツール「fio」の使い方を解説します。シーケンシャル・ランダム・混在負荷の計測手順から、bw・IOPS・clatの出力の読み方、iostatと組み合わせた高負荷時の診断まで、RHEL 9 / Rocky Linux 9 / Ubuntu 24.04 LTSで動作確認した実機例でカバーします。
この記事のポイント
・fioで「ディスクの実力値」を事前計測しておくと障害時の判断基準になる
・シーケンシャルはbs=1M iodepth=1、ランダムはbs=4k iodepth=32が定番パラメータ
・--direct=1を忘れるとRAMを測定してしまい、実際のディスク性能が分からない
・bw(帯域)・IOPS・clat(完了レイテンシ)の3指標を読めれば実用上十分
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
ディスクI/Oが疑われる場面とfioが必要な理由
ディスクパフォーマンスの問題はいくつかの典型的な場面で浮かび上がります。・ピーク時間帯にWebアプリのレスポンスが急に悪化する
・MySQLのスロークエリが多発しているがクエリ内容よりI/O待ちが原因に見える
・
iostat -xz 1 で特定ディスクの%utilが90%を超える時間帯がある・仮想マシンのディスクをSSDに変更したが期待ほど速くならない
こういった場面で「本当にディスクが詰まっているのか、アプリ側の問題なのか」を切り分けるには、ディスク単体の最大性能(ベンチマーク値)が必要です。ベンチマーク値がなければ、iostatの
%util 80%が「通常範囲」なのか「限界間際」なのかを判断できません。fio(Flexible I/O Tester)はLinux標準の汎用I/Oベンチマークツールです。ブロックサイズ・キュー深度・並列数・アクセスパターンを自由に組み合わせられるため、本番ワークロードに近い条件での性能計測が可能です。ディスクが本番に搬入された直後の計測、OSリプレース後の性能確認、クラウドストレージの実効帯域確認など、幅広い場面で活用されています。
fioのインストール方法
1. RHEL 9 / Rocky Linux 9 / AlmaLinux 9 の場合
# baseリポジトリに含まれているためEPEL不要 [root@server01 ~]# dnf install -y fio # インストール確認 [root@server01 ~]# fio --version fio-3.35
2. Ubuntu 24.04 LTS / Debian 12 の場合
[root@server01 ~]# apt update && apt install -y fio [root@server01 ~]# fio --version fio-3.33
計測の前に確認しておくこと
1. テスト対象のディスクを特定する
ベンチマーク前に、評価したいディスクとファイルシステムを確認します。dmidecode でハードウェア情報を取得することでディスクの種類(HDD/SSD/NVMe)やインタフェースを把握しておくと、測定値が妥当かどうかの判断基準になります。テストファイルを置くパスは、評価したいディスク上に作成します。mount コマンドの使い方で現在のマウントポイントとファイルシステムの種類(ext4 / XFS)を確認しておきましょう。
# マウント状況を確認してテスト先を決める [root@server01 ~]# df -Th Filesystem Type Size Used Avail Use% Mounted on devtmpfs devtmpfs 3.8G 0 3.8G 0% /dev /dev/sda1 xfs 50G 12G 38G 24% / /dev/sdb1 xfs 200G 15G 185G 8% /data
/data(/dev/sdb1にマウント)を対象にするなら、テストファイルは/data/fio-testfileに作成します。2. テストファイルとブロックデバイス直接指定の違い
fioのテスト対象にはテストファイル(推奨)とブロックデバイス直接の2種類があります。・テストファイル(--filename=/data/fio-testfile):既存のデータを破壊しないため安全。本番稼働中のディスクでも使える
・ブロックデバイス直接(--filename=/dev/sdb):ファイルシステムのオーバーヘッドを排除した純粋な計測が可能。ただしそのデバイス上のデータをすべて上書き・消去するため、アンマウント済みの専用テストディスクにのみ使用すること
通常のサーバー運用ではテストファイルを使う方法で十分です。誤ってブロックデバイス直接指定で本番ディスクを上書きしてしまう事故が実際に起きているため、本番サーバーでは必ずテストファイル方式を選んでください。
シーケンシャル読み書きのベンチマーク
シーケンシャルアクセスは動画配信・ログ集約・バックアップのような「大きなファイルを順番に読み書きする」ワークロードの計測です。ブロックサイズ1M、iodepth=1が定番設定です。1. シーケンシャル書き込みテスト
[root@server01 ~]# fio \ --name=seq_write \ --rw=write \ --bs=1M \ --size=2G \ --numjobs=1 \ --direct=1 \ --iodepth=1 \ --ioengine=libaio \ --filename=/data/fio-testfile \ --group_reporting seq_write: (groupid=0, jobs=1): err= 0: pid=12438: Mon Sep 14 10:00:05 2026 write: IOPS=487, BW=487MiB/s (511MB/s)(2048MiB/4205msec); 0 zone resets slat (usec): min=3, max=180, avg=14.22, stdev= 8.11 clat (usec): min=924, max=3524, avg=2035.80, stdev=202.14 lat (usec): min=930, max=3540, avg=2050.02, stdev=203.94 clat percentiles (usec): | 1.00th=[ 1582], 5.00th=[ 1729], 50.00th=[ 2024], 99.00th=[ 2507] iops : min= 408, max= 504, avg=487.40, stdev=19.32, samples=8 Run status group 0 (all jobs): WRITE: bw=487MiB/s (511MB/s), io=2048MiB (2148MB), run=4205-4205msec
2. シーケンシャル読み込みテスト
[root@server01 ~]# fio \ --name=seq_read \ --rw=read \ --bs=1M \ --size=2G \ --numjobs=1 \ --direct=1 \ --iodepth=1 \ --ioengine=libaio \ --filename=/data/fio-testfile \ --group_reporting seq_read: (groupid=0, jobs=1): err= 0: pid=12512: read: IOPS=489, BW=489MiB/s (513MB/s)(2048MiB/4188msec) clat (usec): min=908, max=4102, avg=2040.12, stdev=215.34 iops : min= 412, max= 510, avg=490.20, stdev=19.51, samples=8 Run status group 0 (all jobs): READ: bw=489MiB/s (513MB/s), io=2048MiB (2148MB), run=4188-4188msec
ランダム読み書きのベンチマーク(4K)
ランダムアクセスはMySQL・PostgreSQL・メールサーバーのような「小さなブロックを非連続に読み書きする」ワークロードの計測です。ブロックサイズ4k、numjobs=4、iodepth=32が定番設定です。1. ランダム4K書き込みテスト
[root@server01 ~]# fio \ --name=rand_write \ --rw=randwrite \ --bs=4k \ --size=2G \ --numjobs=4 \ --direct=1 \ --iodepth=32 \ --ioengine=libaio \ --filename=/data/fio-testfile \ --group_reporting rand_write: (groupid=0, jobs=4): err= 0: pid=12605: write: IOPS=41.5k, BW=162MiB/s (170MB/s)(2048MiB/12625msec) slat (nsec): min=1460, max=98010, avg=5224.37, stdev=3105.92 clat (usec): min=278, max=48219, avg=3072.88, stdev=2145.33 clat percentiles (usec): | 1.00th=[ 604], 5.00th=[ 668], 50.00th=[ 2900], 99.00th=[ 9503] | 99.99th=[35390] iops : min=32768, max=44128, avg=40579.42, stdev=1956.57, samples=100 Run status group 0 (all jobs): WRITE: bw=162MiB/s (170MB/s), io=2048MiB (2148MB), run=12625-12625msec
2. ランダム4K読み込みテスト
[root@server01 ~]# fio \ --name=rand_read \ --rw=randread \ --bs=4k \ --size=2G \ --numjobs=4 \ --direct=1 \ --iodepth=32 \ --ioengine=libaio \ --filename=/data/fio-testfile \ --group_reporting rand_read: (groupid=0, jobs=4): err= 0: pid=12714: read: IOPS=87.2k, BW=341MiB/s (357MB/s)(2048MiB/6014msec) clat (usec): min=212, max=16584, avg=1459.84, stdev=876.42 clat percentiles (usec): | 1.00th=[ 318], 5.00th=[ 437], 50.00th=[ 1270], 99.00th=[ 4293] | 99.99th=[12648] iops : min=67424, max=100032, avg=87206.36, stdev=5834.10, samples=24 Run status group 0 (all jobs): READ: bw=341MiB/s (357MB/s), io=2048MiB (2148MB), run=6014-6014msec
fio出力の読み方(bw・IOPS・clatの3指標)
1. bw(帯域幅)
bw=487MiB/sのように表示されるのが帯域幅(スループット)です。「1秒間に何バイト転送できたか」を示します。・シーケンシャルアクセスでは帯域幅がボトルネックになりやすい(大容量ファイルの書き出しなど)
・ランダムアクセスでは後述のIOPSの方が重要な指標になる場合が多い
・単位は「KiB/s」または「MiB/s」。MB/s(メガバイト毎秒)とMiB/sは1.048576倍の差があるため、カタログスペックと比較するときは注意する
2. IOPS(秒間I/O処理数)
IOPS=41.5kのように表示されるのがI/O operations per secondです。「1秒間に何回のI/Oリクエストを処理できたか」を示します。・データベースのパフォーマンスはIOPSに支配されることが多い(MySQLの4Kランダム読み書き等)
・HDDは100~200 IOPS、SATA SSDは40,000~100,000 IOPS、NVMe SSDは200,000~1,000,000 IOPSが目安
・iodepthやnumjobsを増やすとIOPSが上がる場合があるが、ある値を超えるとCPU・カーネルがボトルネックになって頭打ちになる
3. clat(completion latency・完了レイテンシ)
clat (usec): avg=3072.88のように表示されるのが完了レイテンシです。「I/Oリクエストを出してから完了するまでの時間」をマイクロ秒(usec)で示します。・アプリケーションが体感する応答速度に直結する指標
・99パーセンタイル(
99.00th)の値を見ることで外れ値の影響を把握できる・
slat(submission latency)はカーネルへのI/O投入にかかる時間で、通常はマイクロ秒以下・
lat(total latency)= slat + clat の合計値SSDでランダム読み込みの
clat avgが1,000~2,000usec(1~2ms)であれば正常範囲です。HDDでは回転待ちがあるため5,000usec以上になることもあります。重要オプションの早見表
| オプション | 意味 | 推奨値・注意点 |
|---|---|---|
fio --name=... --direct=1 |
OSページキャッシュをバイパスして直接I/O | 常に指定する。省略するとRAMのキャッシュを測ることになり、実ディスク性能が分からない |
fio --name=... --ioengine=libaio |
Linuxカーネルの非同期I/Oエンジンを使用 | Linuxサーバーの推奨値。デフォルトのposixaioより高スループット |
fio --name=... --bs=N |
ブロックサイズ | シーケンシャルテストは1M、ランダムテストは4k |
fio --name=... --iodepth=N |
キュー深度(未完了I/Oの最大同時発行数) | シーケンシャルは1、ランダムは32が定番。NVMe SSDは128以上でさらに伸びることがある |
fio --name=... --numjobs=N |
並列ワーカー数 | 1~CPUコア数。多すぎるとCPUがボトルネックになる |
fio --name=... --runtime=N --time_based |
測定時間を秒で指定(サイズでなく時間で制御) | 60~300秒で安定した平均値が得やすい |
fio --name=... --size=N |
各ワーカーのI/O量(またはテストファイルサイズ) | 実メモリより大きいサイズを指定するとキャッシュ汚染を防げる |
ジョブファイルで再現性のあるテストを管理する
コマンドラインが長くなる場合はジョブファイル(.fio)にまとめると管理しやすく、バージョン管理にも置きやすくなります。1. ジョブファイルの作成
[root@server01 ~]# cat /etc/fio/diskbench.fio [global] ioengine=libaio direct=1 runtime=60 time_based=1 group_reporting=1 filename=/data/fio-testfile [seq-write-1M] rw=write bs=1M numjobs=1 iodepth=1 [seq-read-1M] rw=read bs=1M numjobs=1 iodepth=1 [rand-write-4k] rw=randwrite bs=4k numjobs=4 iodepth=32 [rand-read-4k] rw=randread bs=4k numjobs=4 iodepth=32
2. ジョブファイルを実行する
# ジョブを順番に実行([global]の設定が各セクションに引き継がれる) [root@server01 ~]# fio /etc/fio/diskbench.fio # 特定のセクションだけ実行したい場合 [root@server01 ~]# fio /etc/fio/diskbench.fio --section=rand-read-4k # 結果をJSONで保存(ディスク交換前後の比較に便利) [root@server01 ~]# fio /etc/fio/diskbench.fio --output=result_20260914.json --output-format=json
トラブルシュート:iostatとの組み合わせで高負荷を診断する
fioのベンチマーク値を基準にして、本番稼働中のiostat実測値と比較するのが高負荷診断の定石です。1. 別ターミナルでiostatをリアルタイム監視する
# 1秒間隔でsdb(データディスク)の詳細統計を表示 [root@server01 ~]# iostat -xz 1 sdb Linux 5.14.0-427.13.1.el9_4.x86_64 09/14/2026 _x86_64_ Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s r_await w_await aqu-sz %util sdb 82400.0 0.0 329600.0 0.0 0.0 0.0 0.94 0.00 0.08 93.00
2. iostat出力で確認すべき3指標
・%util:ディスクがビジー状態だった時間の割合。80%を超えると要注意。100%に張り付いていれば飽和(I/O待ちが発生してアプリに影響が出ている状態)・r_await / w_await:読み書きI/Oリクエストの平均待ち時間(ミリ秒)。SSDで平均10ms超はストレージ問題の可能性。HDDでは10~20msが正常範囲
・aqu-sz:平均キューサイズ。大きいほどI/Oが滞留している。SSDで1を大きく超えている場合はIOPS上限に近い
fioベンチマーク値との組み合わせ診断例:
fioで計測したランダム読み込みIOPSが87,000 IOPS(最大)だとします。iostatで本番稼働中の
r/sが82,400まで上がっているなら、ディスクの限界に近いと判断できます。一方でr/sが30,000程度で%utilが90%になっている場合は、ディスクの飽和ではなくホストのI/Oスケジューラ・VMのストレージ割り当て側の問題を疑うべきです。ベンチマーク値なしでiostatの数値だけ見ていると「%util 90%だからディスク交換しよう」という誤判断をしがちです。fioで実力値を把握しておくことで、交換・増強が本当に必要かどうかの根拠を持った判断が可能になります。
本記事のまとめ
| 測定目的 | コマンドの例 |
|---|---|
| シーケンシャル書き込み帯域 | fio --name=seq_write --rw=write --bs=1M --size=2G --numjobs=1 --direct=1 --iodepth=1 --ioengine=libaio --filename=/data/fio-testfile |
| シーケンシャル読み込み帯域 | fio --name=seq_read --rw=read --bs=1M --size=2G --numjobs=1 --direct=1 --iodepth=1 --ioengine=libaio --filename=/data/fio-testfile |
| ランダム4K書き込みIOPS | fio --name=rand_write --rw=randwrite --bs=4k --size=2G --numjobs=4 --direct=1 --iodepth=32 --ioengine=libaio --filename=/data/fio-testfile |
| ランダム4K読み込みIOPS | fio --name=rand_read --rw=randread --bs=4k --size=2G --numjobs=4 --direct=1 --iodepth=32 --ioengine=libaio --filename=/data/fio-testfile |
| ジョブファイルで複数テストを一括実行 | fio /etc/fio/diskbench.fio --output=result.json --output-format=json |
| 特定セクションだけ実行 | fio /etc/fio/diskbench.fio --section=rand-read-4k |
ディスクI/Oのボトルネック診断スキルを固めたら、次はLinuxサーバー全体の構築・運用スキルを体系的に身につけませんか?
fioで実力値を計測し、iostatで現場を診断できるのは、Linuxのストレージ構造を理解しているエンジニアだけです。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:conntrackコマンドでLinuxのNAT接続追跡を診断する方法|nf_conntrack_maxが上限に達した時の調査と恒久対処
- この記事の属するカテゴリ:Linuxトラブルシューティングへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます