eBPF 整理 — カーネルを再コンパイルせずに拡張する技術
Cilium、Falco、Pixie、Katran。ここ数年、インフラツールの紹介ページのあちこちに eBPF という単語が登場します。結論を先に書くと、eBPF はカーネルを再コンパイルしたりモジュールをインストールしたりせずに、検証済みの小さなプログラムを実行中のカーネルの中で安全に動かす技術です。「カーネルのプログラマブル化」と呼ぶことができ、可観測性・ネットワーキング・セキュリティのツール群がこの 10 年でこの上に移り住みました。この記事ではその原理と地形を整理します。
問題 — カーネルの中で起きていることを見たい #
システムの真実はカーネルの中にあります。どのプロセスがどのファイルを開き、パケットがどこで捨てられ、ディスク I/O がどこで遅延しているのか。ところが、カーネルの中をのぞいたり動作を変えたりする伝統的な方法は、どちらも問題を抱えていました。
- カーネルモジュール: 何でもできますが、バグひとつがカーネルパニックになります。モジュールひとつのためにサーバー全体が死ぬリスクを、本番で引き受けるのは困難です。
- ユーザースペースのツール: 安全ですが遅く、限定的です。たとえばパケットをユーザースペースにコピーしてきて検査する方式は、コピーのコスト自体がボトルネックになります。
eBPF は第三の道です。小さなプログラムをカーネル内の仮想マシンで実行しつつ、ロード前に検証器(verifier)が安全性を静的に証明します。カーネルの速度と視野を得ながら、モジュールのリスクは負わない構造です。
動作原理 — 検証器という門番 #
eBPF プログラムのライフサイクルはこうです。
- プログラム(普通は C で書いてバイトコードにコンパイル)をカーネルにロードします。
- 検証器がすべての実行経路を検査します。 終了が保証されないループ、許可範囲外のメモリアクセス、未初期化の値の使用があれば、ロード自体が拒否されます。「カーネルの中で動くのにカーネルを殺せない」理由がこの門番です。
- 通過したプログラムは JIT コンパイルされ、ネイティブ速度で実行されます。
- フック(hook)に接続されます。特定のカーネルイベントが起きるたびにプログラムが呼ばれる構造です。
- 収集したデータはマップ(map)というカーネル内のデータ構造にたまり、ユーザースペースのツールがそれを読み出します。
フック地点がそのまま活用先の地図になります。
| フック | いつ呼ばれるか | 代表的な用途 |
|---|---|---|
| kprobe / kretprobe | ほぼすべてのカーネル関数の進入・復帰 | 任意地点のトレーシング |
| tracepoint | カーネルが公式に提供する安定した計測点 | システムコール、スケジューラー、I/O の追跡 |
| uprobe | ユーザースペースの関数 | アプリケーション関数の追跡 |
| XDP | NIC ドライバー、ネットワークスタック進入前 | 超高速パケットフィルター・ロードバランシング |
| tc / socket | ネットワークスタックの各段階 | トラフィック制御、ポリシー |
| LSM | セキュリティ決定地点 | ランタイムセキュリティポリシー |
何に使われるか — 3 つの枝 #
可観測性(observability)が最も触れやすい枝です。従来の方式はアプリケーションに計測コードを入れるかサンプリングプロファイラーを付ける必要がありましたが、eBPF はカーネルイベントから直接データを取るので、対象プロセスを修正も再起動もせずにシステム全体を見られます。「どのプロセスがどのファイルを開いているか」「TCP 再送はどこから出ているか」「ディスク遅延の分布はどうか」といった問いがワンライナーで解けます。サーバーが遅い系の診断で標準ツールが答えをくれないとき、次の層として取り出す道具です。
ネットワーキングは eBPF が業界を変えた枝です。XDP はパケットがカーネルのネットワークスタックに入る前、NIC ドライバーのレベルで eBPF プログラムを回します。毎秒数百万パケットのフィルタリング・転送が可能になり、DDoS 防御や L4 ロードバランサーがこの上に建てられました。Kubernetes の世界では Cilium が iptables のチェーンの代わりに eBPF でポッドのネットワーキング・ポリシー・ロードバランシングを実装し、CNI の事実上の標準軸になりました。
セキュリティは、システムコールとカーネルイベントをリアルタイムに観察してポリシー違反を検知・遮断する枝です。Falco、Tetragon のようなランタイムセキュリティツールが「コンテナが突然シェルを実行した」「想定外のパスに書き込みをした」を捕まえる基盤が eBPF です。
触ってみる — 道具のはしご #
eBPF を使うために C とカーネルに詳しくなる必要はありません。はしごがあります。
- bpftrace: awk に似たワンライナー言語です。学習コスト対効用が最も大きい入り口です。
- bcc ツール集: execsnoop(プロセス実行の追跡)、opensnoop(ファイルオープン)、biolatency(ディスク遅延のヒストグラム)、tcpretrans(TCP 再送)など、できあいのツール数十個がパッケージでインストールされます。運用の疑問の大半はこの既成ツールで片付きます。
- libbpf + CO-RE: 自前のツール・製品を作る段階です。CO-RE(Compile Once, Run Everywhere)が、カーネルバージョンごとに再コンパイルしていた苦痛を大きく減らしました。
# bpftrace ワンライナー: いまシステムで開かれるファイルをリアルタイムに
bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }'現実的な制約 #
- 権限: eBPF のロードは基本的に root(または CAP_BPF などの細分化されたケーパビリティ)が必要です。任意のプロセスがカーネルを計測できるなら、それ自体がセキュリティホールだからです。
- カーネルバージョン: 機能がカーネルバージョンに強く結び付いています。新しい機能ほど新しいカーネルが必要なので、古いディストリビューションでは、ツールが要求するカーネルバージョンの確認が最初の一歩です。
- マネージド環境: コンテナの中からの eBPF はホストカーネルの権限問題と絡み、一部のマネージドサービスでは制限されます。ノードデーモン(DaemonSet)の形でデプロイするのが標準パターンである理由です。
- 万能ではありません: 検証器の制約(プログラムのサイズ、複雑さ)の中で動くので、複雑なロジックは今もユーザースペースとの協業として設計します。
まとめ #
- eBPF は検証済みの小さなプログラムをカーネルの中で安全に動かす技術です。モジュールのリスクなしに、カーネルの視野と速度を得ます。
- 安全の核心は検証器です。終了が証明できない、あるいはメモリアクセスが危険なプログラムは、ロード自体が拒否されます。
- 活用は可観測性(無修正・無再起動の計測)、ネットワーキング(XDP、Cilium)、セキュリティ(Falco などのランタイム検知)の 3 つの枝です。
- 入門は bpftrace のワンライナーと bcc の既成ツールで十分で、製品を作るときに libbpf + CO-RE に降りていきます。
- root 権限とカーネルバージョン依存が現実的な制約なので、導入検討は「うちのカーネルでこのツールは動くか」から始めます。