MENU

eBPFトレースでLinux本番サーバーのI/Oレイテンシを診断する|bpftraceスクリプト作成と原因特定の流れ

ディスクI/Oの遅延が間欠的に発生しているのに、iostatやsarを見てもどのプロセスが原因か特定できない——本番環境の運用担当者が直面しやすい状況です。eBPFとbpftraceはこの「見えない遅延」を低オーバーヘッドで可視化する手段として、2026年現在、実運用に十分耐えうる成熟度に達しています。本記事では、bpftraceスクリプトの作成から出力の解釈、原因特定までの一連の流れを具体的に解説します。

目次

なぜ従来のI/O診断ツールでは限界があるのか

iostatやiotopはシステム全体のスループットやキュー深度を把握するには有用ですが、「特定プロセスの特定I/O要求が何マイクロ秒かかっているか」を細粒度で捉える能力は持っていません。sar -d はデバイス単位の集計値を見せてくれますが、時間軸での平均にすぎず、スパイク的なレイテンシ上昇の原因追跡には不向きです。

straceはシステムコールをトレースできますが、プロセスごとにアタッチする必要があり、オーバーヘッドも大きいため本番での継続利用は現実的ではありません。blktrace/blkparseはブロック層の詳細を取れますが出力が膨大で解析コストが高く、運用ツールとして常用されるケースは限られています。

eBPFはこれらの課題を解決します。カーネルの内部トレースポイントにアタッチした小さなプログラムが、カーネルベリファイアによる安全検証を経てJITコンパイルされ実行されます。計測対象以外のコードパスに影響を与えないまま、μs単位の精度でI/Oレイテンシを計測できます。

eBPFとbpftraceの現在地(2026年)

2026年時点でeBPFエコシステムは成熟期に入っています。Linux 6.x系カーネルではBTF(BPF Type Format)がデフォルト有効となり、/sys/kernel/btf/vmlinux が標準で存在します。これにより、カーネルデバッグシンボルパッケージを別途インストールしなくても、bpftraceがカーネル内部の型情報を直接参照できるようになりました。

bpftrace 0.21以降はCO-RE(Compile Once – Run Everywhere)への対応が強化され、ディストリビューションをまたいでも同一スクリプトが動作するケースが増えています。主要ディストリビューションの対応状況は以下のとおりです。

  • Ubuntu 24.04 LTS:apt install bpftrace でインストール可能、BTFはデフォルト有効
  • RHEL / AlmaLinux 9.x:dnf install bpftrace、カーネル5.14ベースでBTF有効
  • Debian 12 (Bookworm):apt install bpftrace、カーネル6.1ベースでBTF有効

注意が必要なのはクラウドプロバイダーのカスタムカーネルです。一部のAWS・GCPの最適化AMIではBTFが無効になっているケースがあります。診断を始める前に ls /sys/kernel/btf/vmlinux でファイルの存在を確認するのが確実です。

診断環境の準備と動作確認

bpftraceのインストール自体はシンプルです。

# Ubuntu / Debian
sudo apt install bpftrace

# RHEL系
sudo dnf install bpftrace

インストール後、まず動作を確認します。

sudo bpftrace -e 'BEGIN { printf("bpftrace OK\n"); exit(); }'

BTFが有効かどうかも確認しておきます。

ls /sys/kernel/btf/vmlinux

ファイルが存在しない場合は、Ubuntu なら linux-image-$(uname -r)-dbgsym、RHEL系なら kernel-debuginfo を追加インストールします。本番サーバーに直接インストールするのが難しい場合は、同一カーネルバージョンのステージング環境で検証してから展開するアプローチが安全です。

I/Oレイテンシを計測するbpftraceスクリプト

以下のスクリプトはブロック層のI/O要求をトレースし、挿入から完了までのレイテンシをヒストグラムとして出力します。Linux 5.14以降の環境を対象としています。

#!/usr/bin/env bpftrace

tracepoint:block:block_rq_insert
{
    @start[args->dev, args->sector] = nsecs;
}

tracepoint:block:block_rq_complete
/@start[args->dev, args->sector]/
{
    $lat = (nsecs - @start[args->dev, args->sector]) / 1000;
    @latency_us = hist($lat);
    delete(@start[args->dev, args->sector]);
}

interval:s:10
{
    printf("\n--- 10秒間のI/Oレイテンシ分布 (μs) ---\n");
    print(@latency_us);
    clear(@latency_us);
}

END
{
    clear(@start);
}

このスクリプトを io_latency.bt として保存し、以下で実行します。

sudo bpftrace io_latency.bt

特定プロセス(例:mysqld)のI/Oだけに絞りたい場合は、トレースポイントにフィルタ条件を追加します。

tracepoint:block:block_rq_insert
/comm == "mysqld"/
{
    @start[args->dev, args->sector] = nsecs;
}

VFSレイヤーでのファイル読み書きレイテンシを見たい場合(バッファキャッシュ後の実ディスクI/Oではなく、アプリから見えるレイテンシを計測したい場合)は以下のスクリプトが有効です。

kprobe:vfs_read
{
    @start[tid] = nsecs;
}

kretprobe:vfs_read
/@start[tid]/
{
    @vfs_read_us = hist((nsecs - @start[tid]) / 1000);
    delete(@start[tid]);
}

interval:s:10
{
    print(@vfs_read_us);
    clear(@vfs_read_us);
}

END
{
    clear(@start);
}

出力の読み方と原因特定のチェックポイント

bpftraceのhistはlog2スケール(対数2スケール)のヒストグラムを出力します。各行の [下限, 上限) はレイテンシのバケットを表し、右の数値がそのバケットに入ったI/O件数です。正常なNVMe SSDであれば大半のI/Oは50〜500μsの範囲に収まります。SATA SSDでは100〜2000μsが一般的な分布です。

以下のパターンが見られた場合は原因を絞り込む必要があります。

  • [4096, 8192) 以上(4〜8ms)に件数が集中:ディスクI/Oキューの飽和、またはI/Oスケジューラの問題を疑います
  • [65536, …)(65ms超)が散見される:ハードウェア障害、クラウドストレージのスロットリング、ファームウェアレベルの問題の可能性があります
  • 特定の10秒間だけ分布が悪化する:バッチジョブや定期タスクとの競合を疑います

高レイテンシが検出された場合の追加確認コマンドを以下に示します。

# デバイス使用率の確認
iostat -x 1

# I/Oスケジューラの確認
cat /sys/block/sda/queue/scheduler

# カーネルのディスクエラーログ確認
dmesg | grep -E 'ata|error|reset|timeout'

# I/Oスケジューラをmq-deadlineに一時変更(再起動で元に戻る)
echo mq-deadline | sudo tee /sys/block/sda/queue/scheduler

I/Oスケジューラの変更はNVMe SSDでは効果が限定的ですが(NVMeはデフォルトでnoneが推奨)、SATA SSDや回転ディスクではmq-deadlineへの変更でレイテンシが改善するケースがあります。恒久的な変更はudevルールかsystemd-udevdのHWDB経由で管理し、再起動後も設定が維持されるようにします。

本番運用における安全策と環境差異への対応

eBPFプログラムはカーネルのベリファイアによる静的検証を必須とするため、無限ループや不正なメモリアクセスはロード段階で拒否されます。通常の使用でカーネルをクラッシュさせるリスクは極めて低く、この点はdtraceやktapと比べた大きな安全上の優位点です。

ただし本番環境での運用にあたり、以下の点には注意が必要です。

CPU使用率:高頻度I/Oが発生している環境ではトレースポイントのヒット数が増え、bpftrace自身のCPU使用率が上昇します。診断実施前にtopやmpstatでCPUヘッドルームを確認し、余裕のあるタイミングで実行することが望まれます。

マップメモリ@start マップはI/O要求ごとにエントリを作成します。大量の未完了I/Oが重複する状況では一時的なメモリ増加が起きます。スクリプトのENDブロックで clear(@start) を呼ぶことでCtrl+C時の正常解放を担保できます。

カーネルバージョン差異block:block_rq_insert トレースポイントの引数構造はLinux 5.11で変更されています。5.11未満のカーネル(一部のCentOS 7延長サポート環境など)では kprobe:blk_account_io_start と対応する kretprobe を使う必要があります。現在の主要ディストリビューションはほぼ5.15以降のため実害は少ないですが、長期サポートで止まっているサーバーでは事前確認が必要です。

コンテナ環境:Kubernetes Pod内からbpftraceを実行する場合、ホストの /sys/kernel/btf/vmlinux へのアクセスと CAP_BPF または CAP_SYS_ADMIN 権限が必要です。特権コンテナを使わずにeBPFを活用したい場合は、Cilium Tetragonのような専用オブザーバビリティスタックの採用を検討するのが現実的な選択肢です。

bpftraceはCtrl+Cで安全に停止でき、終了時にマップの内容を自動出力してから終了します。診断中に状況が変化した場合でも途中経過を失わずに確認できる点は、実運用での使いやすさにつながっています。eBPFトレースは「重くて使えない」というかつてのイメージから大きく変わり、本番サーバーでのリアルタイム診断ツールとして現場に定着しつつあります。

「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。

ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。

>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)

※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。

PR・広告

新しいLinuxの教科書 第2版(Amazon)

コマンド操作から基本運用までを手を動かして学べる定番書。記事で触れた技術の土台固めに。

Amazonで見る

※ Amazonのアソシエイトとして、当サイトは適格販売により収入を得ています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次