eBPFとは何か——カーネルを再起動せずに拡張する技術が、クラウドの監視・セキュリティ・ネットワーキングを支える仕組み
1. はじめに——なぜカーネル拡張はこれほど難しかったのか
eBPF(extended Berkeley Packet Filter)とは、Linuxカーネルを再起動・ソースコード変更なしで安全に拡張する技術です。カーネル空間でサンドボックス化されたプログラムを実行できるため、システムコールやネットワークパケットといったカーネル内のイベントを、高い粒度で計測・制御できるようになります(出典: ebpf.io)。
金曜日の16時、担当するKubernetesクラスタで特定サービスのレイテンシだけが急上昇した——そんな経験はありませんか。アプリケーションのログに異常はなく、既存のメトリクスは「遅い」ことしか教えてくれません。本当の原因、つまりどのプロセスがどのファイルを開いたのか、パケットがどのノードで遅れているのかを知るには、すべてのシステムコールとパケットが通過するカーネルの内側から観測するのが理想的です。ところがカーネルはOSの心臓部であり、安易に手を入れればホストごとクラスタを道連れにしかねません。
カーネルに機能を足す、従来のつらい2択
OSカーネルは観測と制御に最適な場所でありながら、安定性とセキュリティが最優先されるため、その進化は本質的に遅くなります。実際、カーネルに新しい機能を追加する手段は長らく次の2つしかありませんでした(出典: ebpf.io)。
- カーネルのソースコードを変更する —— メーリングリストでコミュニティの合意を取り付け、マージを待つ。手元で使えるようになるまで数年かかることも珍しくありません。
- カーネルモジュールとしてロードする —— 手軽な一方で、カーネルを更新するたびに壊れる可能性があり、クラッシュやセキュリティリスクをホストに直接持ち込みます。
どちらの道も、本番環境で気軽に選べるものではありません。「カーネルの中で観測したい。でもカーネルには手を出したくない」——このジレンマこそ、Linuxインフラエンジニアが長年抱えてきた課題でした。
eBPFが開く「第3の道」と、この記事で得られること
eBPFはこの構図を変えます。カーネルのソース変更も、カーネルモジュールのロードも、再起動も不要。安全性を検証されたプログラムを、稼働中のシステムのカーネル空間へ追加できる——それがeBPFの約束です(出典: ebpf.io)。
KubernetesのCNIとして人気のCilium、ランタイムセキュリティのFalco、手動計装なしでテレメトリを取得するPixie。これらのプロダクトが高い性能を発揮できる背景には、共通の土台としてeBPFがあります(各プロダクトの機能・性能は設定や環境に依存します)。本記事では、eBPFの基本概念と30年余りの歴史、検証器・JIT・マップによる動作原理、監視・セキュリティ・ネットワーキングの3分野でのユースケース比較、bpftraceではじめる実践入門、そしてMetaやGoogleといった大手での採用実態までを順に解説します。読み終える頃には「CiliumやFalcoがなぜ速いのか」の答えと、明日から自分の環境で試す最初の一歩が見えているはずです。
2. eBPFとは何か?基本概念と30年の歴史を5分で
まず定義をもう一段正確にしておきましょう。eBPFとは、Linuxカーネル内でサンドボックス化されたプログラムを安全に実行できる技術です。カーネルのソース変更もカーネルモジュールのロードも再起動も必要とせず、システムコールやネットワークイベントなどのタイミングで発火する、イベント駆動型のプログラムとして動作します(出典: ebpf.io)。
「JavaScriptがブラウザを変えた」と同じ構図
eBPFの公式ドキュメントは、その本質を伝える例えを示しています。かつて静的なHTMLを表示するだけだったブラウザは、JavaScriptの登場によってアプリケーションプラットフォームへ進化しました(GeoCitiesの時代から、いまのWebアプリへ)。これと同じように、eBPFは変更が難しかったLinuxカーネルを「プログラマブルな存在」に変えます。安全性(サンドボックス実行)・必要なときにいつでも追加できる柔軟性・高性能(JITコンパイル)の3要件を同時に満たす点が本質です(出典: ebpf.io)。
cBPFとの違い——パケットフィルタからカーネル拡張基盤へ
BPFは元々「Berkeley Packet Filter」の略称で、パケットフィルタリング用の仮想マシンでした。現在のeBPFはパケット処理をはるかに超える能力を持ち、旧来のものはcBPF(classic BPF)と呼ばれて区別されます。いまLinux界隈で「BPF」と言えばeBPFと同義です(出典: ebpf.io・Zenn)。
| 項目 | cBPF(classic BPF) | eBPF |
|---|---|---|
| 誕生 | 1992年 | 2014年(カーネル3.18で初登場) |
| 目的 | パケットフィルタリング | 監視・セキュリティ・ネットワーキング全般 |
| レジスタ幅 | 32ビット | 64ビット |
| カーネルとの連携 | なし | BPFマップ・ヘルパー関数 |
| アタッチ先 | パケットフィルタ用途のみ | kprobe / XDP / cgroup / LSM など多様 |
30年の歴史——1992年のBPF誕生からeBPF Foundationまで
- 1992年:McCanneとJacobsonがオリジナルのBPF(パケットフィルタ用仮想マシン)を発表(出典: Wikipedia)
- 2014年:Alexei StarovoitovとDaniel BorkmannがeBPF("e"はextendedの意)をLinuxカーネルにマージ。ネットワーク以外のカーネル部位へ利用が拡大(出典: Wikipedia)
- 2015年:NetflixのBrendan GreggがeBPFを「superpowers for Linux(Linuxの超能力)」と紹介(出典: Brendan Gregg Blog)
- 2020年:第1回eBPF Summit開催、ロゴの蜂マスコット「eBee」に命名
- 2021年8月:Linux Foundation傘下にeBPF Foundationを設立。Meta・Google・Isovalent・Microsoft・Netflixが設立メンバー(出典: eBPF Foundation)
- その後:Microsoftによる「eBPF for Windows」(MITライセンス)への移植など、Linuxを超えた展開へ
この技術の価値は、Linus Torvalds自身の言葉が最もよく表しています。「BPFは実に有用で、その真の力は専門特化したコードを書ける点にある」(出典: Wikipedia)。
図解:eBPFプログラムはどうやってカーネルで動くのか
歴史だけでなく動作イメージも掴んでおきましょう。eBPFプログラムがロードされ、イベントで動くまでの一連の流れを次の図にまとめました。
flowchart LR
A["擬似Cコード<br/>(ユーザ空間)"] -->|LLVMでコンパイル| B["eBPFバイトコード"]
B -->|"bpf() システムコールでロード"| V["検証器(verifier)<br/>安全性を静的検証"]
V -->|不適切なら| X["ロード拒否"]
V -->|検証通過| J["JITコンパイル<br/>ネイティブ命令へ変換"]
J --> P["アタッチポイント<br/>kprobe / XDP / tracepoint 等"]
P -->|イベントで発火| M["BPFマップ<br/>状態とデータの共有"]
M <-->|読み書き| U["ユーザ空間アプリ<br/>監視・セキュリティ・NWツール"]
テキストでも説明します。①擬似Cで書いたコードをLLVMでeBPFバイトコードにコンパイルし、②bpf()システムコールでカーネルにロード、③検証器(verifier)が安全性を静的検証し、④通過したプログラムだけがJITコンパイルでCPU固有のネイティブ命令に変換、⑤kprobeやXDPなどのアタッチポイントでイベント発生時に発火、⑥結果はBPFマップ経由でユーザ空間のアプリケーションから読み取ります。「検証→JIT」の2段構えにより、高い安全性と高速な実行を両立する設計になっています(実際の性能はプログラムの内容やイベント頻度に依存します)(出典: ebpf.io)。
3. 動作原理——検証器・JIT・マップ・アタッチポイントはどう連携する?
前節では概略図で全体像を見ました。ここからは各部品を詳しく見ていきます。eBPFが「カーネルを壊さず、しかも高速」であり続けられるのは、検証器(verifier)/JITコンパイル/BPFマップ/アタッチポイントという4つの構成要素が、ロード→検証→変換→設置→実行というパイプラインで連携しているからです。
flowchart TD
A["ユーザ空間:擬似Cコード"] -->|"LLVMでコンパイル"| B["eBPFバイトコード"]
B -->|"bpf()システムコールでロード"| C{"検証器(verifier)"}
C -->|"安全でない場合は拒否"| X["ロード失敗"]
C -->|"安全性を確認"| D["JITコンパイル:CPU固有の命令へ変換"]
D --> E["アタッチポイントに設置"]
E -->|"イベント発生で発火"| F["カーネル内を高速に実行(ネイティブ変換済み)"]
F --> G["結果をBPFマップへ書き込み"]
G --> H["ユーザ空間アプリが読み取り"]
図の流れを文章でも説明します。開発者は擬似Cで書いたコードをLLVMでeBPFバイトコードにコンパイルし、bpf()システムコールでカーネルにロードします(通常はlibbpfなどのライブラリが代行)。ここで検証器が安全性を審査し、通過したプログラムだけがJITコンパイルでCPU固有の命令に変換されます。その後、任意のアタッチポイントに設置され、イベントが発生するたびにカーネル内で実行。収集したデータはBPFマップを介して、ユーザ空間のアプリケーションから読み取ります。
検証器(verifier)——「カーネルを壊さない」を静的検証する門番
検証器は静的コード解析により、主に次の4点をチェックします(eBPF公式ドキュメント)。
- 権限:ロードするプロセスがrootまたはCAP_BPFを持つか。非特権eBPFはデフォルトで無効
- 必ず終了する:無限ループは拒否。ループは終了条件が必ず真になると保証できる場合のみ許可
- メモリ安全性:未初期化変数の使用と境界外アクセスの禁止
- サイズ・複雑さの上限:実行されうるすべての命令パスを解析し、上限内で完了できる必要がある
見落としがちな点として、検証器は「安全に実行できるか」を検証するものであり、「プログラムが何をするか」を審査するものではありません。また、検証器による静的検証は安全性を大きく高めますが、すべてのリスクを排除する万能の保証ではありません。
JITコンパイル——ネイティブコードと同等の速度
検証を通過したバイトコードは、JITによって実行環境のCPU固有の命令セットへ変換されます。これにより解釈実行ではなくネイティブコードに近い高速な実行が可能とされています(ebpf.ioではネイティブコード同等と説明されていますが、実際の性能はプログラムの内容やアタッチするイベントの頻度に依存します)。実行モデルはイベント駆動のラン・トゥ・コンプリション(run-to-completion)方式で、発火したら最後まで一気に実行し切ります。
BPFマップとヘルパー関数——カーネルとユーザ空間の架け橋
eBPFプログラムは、カーネルバージョン依存を防ぐためカーネル関数を直接呼べず、ヘルパー関数という安定したAPI経由でのみカーネル機能(乱数・日時取得、マップアクセス、パケット操作など)を利用します。末尾呼び出し(tail call)で別のeBPFプログラムに処理を委譲できるのも特徴です。
状態保存とデータ共有の中核がBPFマップです。ハッシュテーブル、配列、LRU、リングバッファ、LPM(最長プレフィックス一致)など多様なデータ構造をサポートし、システムコール経由でユーザ空間アプリケーションからも参照できます。カーネル内で集計・フィルタした結果をユーザ空間に渡す、標準のデータ連携経路となります。
アタッチポイント——カーネルのどこにフックするか
| アタッチポイント | 位置と主な用途 |
|---|---|
| kprobe/uprobe | カーネル関数/ユーザ空間関数のほぼ任意の場所に動的に設置 |
| tracepoint/システムコール | カーネルが公式に提供する安定した計測点 |
| XDP | NIC受信の最前面。ネットワークスタック処理前の高速パケット処理 |
| cgroup | コンテナ単位のリソース制御・セキュリティ |
| LSM | セキュリティポリシーのリアルタイム実行(BPF LSM) |
とくにXDPが高速なのは、カーネルのネットワークスタックに入る前の最前面でパケットを処理できるためです。Metaのレイヤー4ロードバランサーKatranはXDPを活用し、NICの受信キュー数に対して性能が線形にスケールします。
最後に、実行時の堅牢化も多層的に組み込まれています。プログラムメモリは読み取り専用として保護され、Spectre系サイドチャネルへの緩和(投機的実行パスの検証とメモリアクセスのマスキング)、JITスプレー攻撃対策の定数隠蔽(constant blinding)などが施されています。
4. ユースケース比較——監視・セキュリティ・ネットワーキングで何が変わる?
eBPFの大きな強みは、同じ「カーネルフック」という土台の上に、性質の異なる3つのユースケースが同時に成立している点です。まずは代表プロダクトを一つの表にまとめてみます。
3分野の比較表
※採用例・効果の記述はebpf.io ApplicationsおよびWikipedia「eBPF」のProduction users記載に基づきます。個別企業の詳細な規模・用途は各社の公式資料でもご確認ください。
| 分野 | 代表プロダクト | 主なアタッチポイント | 得られる効果 | 導入企業例 |
|---|---|---|---|---|
| オブザーバビリティ | Pixie、Parca/Pyroscope、eBPF Exporter | tracepoint、kprobe | 計装不要のテレメトリ自動取得、メソッド名・行番号単位のボトルネック特定、Prometheusへのカスタムメトリクス連携 | Netflix(フリート規模のネットワーク観測) |
| セキュリティ | Falco、Tracee、Tetragon | システムコール、kprobe、LSM | 振る舞いベースの異常検知とリアルタイム実行強制。カーネル内フィルタ・集約による低オーバーヘッド | Shopify(Falcoで侵入検知)、Apple(Podセキュリティ) |
| ネットワーキング | Cilium、Katran、Calico eBPF | XDP、cgroup | KubernetesのCNI、カーネルスタック通過前の高速パケット処理、L4ロードバランシング | Meta(Katranでfacebook.comの全トラフィック)、Cloudflare(DDoS防御) |
各分野の使いどころ
- オブザーバビリティ: PixieはKubernetesアプリに計装を入れず、サービスマップからPod状態・リクエストの詳細までドリルダウンできます。ParcaはCPU・メモリ・I/Oのボトルネックをメソッド名・クラス名・行番号単位で時系列に追跡します。
- セキュリティ: Falcoは「コンテナ内でシェルが実行された」といった振る舞いをLinuxカーネル層で継続的に検知します。Tetragonは検知にとどまらず、ポリシーに違反するシステムコールやカーネル関数へのアクセスに対するリアルタイムの実行強制(enforcement)を提供する設計です。
- ネットワーキング: XDPはパケットがカーネルのネットワークスタックに入る前に処理できるため高速で、KatranはNICの受信キュー数に対して性能が線形にスケールします。
従来方式との対比
| 観点 | 従来方式 | eBPF方式 |
|---|---|---|
| アプリ計測 | エージェント組み込み・再ビルド・再デプロイ | ゼロ計装でカーネルから自動取得 |
| パケット処理 | iptables等のカーネルスタック経由 | XDPでスタック侵入前に処理 |
| セキュリティ監視 | ユーザ空間エージェントによる事後検知中心 | カーネル層での振る舞い検知+リアルタイム実行強制 |
3分野の根っこは共通です。「カーネルという特権的な観測・制御地点に、安全にプログラムを置ける」という一点が、監視・セキュリティ・ネットワーキングの3分野を支えています。なお、XDPによるデータプレーン高速処理はRPKIが守るインターネットの経路——BGPハイジャックとは何かの記事とも、サンドボックス実行という観点ではWebAssembly(Wasm)とは何かの記事とも関わるテーマです。
5. 実践入門——bpftraceで今日から始める5ステップ
理論を理解したら、次は自分の手で動かしてみるのが一番の近道です。ここでは高レベルトレーシング言語「bpftrace」を使って、今日からeBPFを体験できる5ステップを紹介します。bpftraceはawk・C・DTraceにインスパイアされた言語仕様を持ち、LLVMをバックエンドにスクリプトをeBPFバイトコードへコンパイルします(出典: bpftrace GitHub)。
Step 1: 環境を確認する
まずカーネルバージョンとBTFの有無を確認します。
uname -r # カーネルバージョン
ls /sys/kernel/btf/vmlinux # 存在すればBTF(CO-RE)対応カーネル
必要なカーネルバージョンはプロダクトごとに異なります。例えばeCaptureはx86_64でカーネル4.18以上、aarch64で5.5以上が要件です(出典: ebpf.io Applications)。
Step 2: bpftraceをインストールする
多くのディストリビューションではパッケージから導入できます。公式の静的バイナリもGitHubリリースで配布されています(出典: bpftrace GitHub)。
sudo apt install bpftrace # Ubuntu / Debian
sudo dnf install bpftrace # Fedora / RHEL
Step 3: 最初のワンライナー——「誰がファイルを開いているか」
openatシステムコールをプロセス名ごとに集計し、ファイルオープン監視を1行で実現します。
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { @[comm] = count(); }'
Ctrl+Cで停止すると、プロセス別のオープン回数ランキングが表示されます。
Step 4: BCCツール群で定番計測
BCCには実用的なコマンドラインツールが同梱されています(出典: ebpf.io Applications)。ブロックI/Oのレイテンシ分布を測るbiolatencyや、新規プロセス実行をリアルタイム表示するexecsnoopが定番です。
sudo biolatency
sudo execsnoop
Step 5: 可視化ツールへ進む
Kubernetesを運用しているなら、計装不要でテレメトリを自動取得するPixieや、ボトルネックをメソッド・行番号単位で時系列追跡する継続的プロファイリングのParcaが次の候補です(出典: ebpf.io Applications)。
実行前の注意点
- 権限: eBPFプログラムのロードにはrootまたはCAP_BPF権限が必要です。非特権eBPFはサイドチャネル攻撃への懸念からデフォルトで無効化されています(出典: ebpf.io・Wikipedia)。
- 負荷: JITによりネイティブに近い高速な実行が可能とはいえ、高頻度イベントへのアタッチはオーバーヘッドを生みます。本番環境では影響の小さいフックから試しましょう。
- 検証器: 自作プログラムは検証器に拒否されることがあります。ループは終了条件が保証される場合のみ許可されます(出典: ebpf.io)。
Cで本格的なプログラムを書きたくなったら、BCCからlibbpf+CO-RE(Compile Once – Run Everywhere)へ進むのが定番の学習経路です。CO-REはBTFによるロード時再配置でカーネルバージョン差異を吸収します(出典: eBPF Docs・libbpf)。
6. 導入事例と現在地——大手はどう使い、どこに限界があるか
大手テック企業の採用実態
eBPFはすでに大規模な本番環境で採用実績のある技術です。代表的な採用事例として次のようなものが報告されています(主にWikipedia「eBPF」のProduction usersセクションおよびebpf.io Applicationsの記載に基づきます。記載内容の最新状況は各社・各プロジェクトの公式資料でご確認ください)。
| 企業 | 報告されている主な用途 |
|---|---|
| Meta | L4ロードバランサ「Katran」による大規模トラフィック処理 |
| GKEでの利用、BPF LSMによるauditの置き換え、ネットワーキング | |
| Cloudflare | ロードバランシング、DDoS防御、セキュリティ強制 |
| Netflix | フリート全体のネットワーク観測とパフォーマンス診断 |
| Microsoft | eBPFとXDPのWindowsへの移植(eBPF for Windows) |
| Shopify | Falcoによる侵入検知 |
| Apple | Kubernetes Podのセキュリティ |
| Android | NAT46とトラフィック監視 |
このほかDropbox(Katran)、DigitalOcean(XDPによるレート制限)、Walmart(L4ロードバランシング)などの報告もあり、業種を超えて採用が広がっています。日本語圏でも「AWSやGoogle Cloudも採用する監視技術」として紹介されるほど、クラウド基盤の観測技術として定着しつつあります。
体制面では、2021年8月にLinux Foundation傘下でeBPF Foundationが設立されました。設立メンバーはMeta、Google、Isovalent、Microsoft、Netflixで、以降Red Hat、Huawei、CrowdStrikeなども参加しています(出典: eBPF Foundation)。
正直な課題と限界
一方で、現実的なハードルも存在します。
- 検証器の厳しさ: 検証器はすべての実行パスを解析し、複雑さの上限を設けます。ループは終了条件が保証される場合のみ許可されるため、書きたいプログラムが通らないことがあります。
- 学習曲線: 擬似Cでの記述、アタッチポイントなどのカーネル知識、検証器エラーの読み解きが必要です。ただしbpftraceやFalco・Ciliumといった完成品の利用で、この壁を回避することは可能です。
- カーネルバージョン互換性: プロダクトごとに必要なカーネルバージョンが異なります。CO-REとBTFによるロード時再配置で大幅に緩和されましたが、BTFを持たないカーネルでは別の手段が必要になるなど、完全な解消ではありません。
- セキュリティ面の議論: Spectre系サイドチャネル攻撃への悪用可能性を受け、カーネルコミュニティは非特権eBPFをデフォルトで無効化しました。特権(root/CAP_BPF)での運用が前提です。検証器自体の健全性を問う学術研究(Rutgers大学、SAS 2024)もあるとおり、検証器も改良が続くソフトウェアです。
導入事例の多さは技術の成熟を示しますが、これらの条件と制約を理解したうえで採用を判断するのが現実的な姿と言えるでしょう。
7. よくある質問(FAQ)とまとめ——次に取るべきアクション
eBPFとカーネルモジュールは何が違う?
カーネルモジュールはカーネル内の任意の関数やメモリにアクセスできる一方で、カーネル更新のたびに破損やセキュリティリスクが伴います。対してeBPFは、ロード時に検証器がクラッシュ・無限ループ・境界外アクセスなどを静的に検査してから実行します。さらにヘルパー関数とCO-REによってカーネルバージョンへの依存が小さく、再起動やソース変更なしで機能追加できる点が決定的な違いです。
eBPFを使うのに必要なカーネルバージョンは?
プロダクトごとに要件は異なります。たとえばeCaptureではx86_64でカーネル4.18以上、aarch64で5.5以上が必要です。近年のカーネルでBTFが有効になっていれば、CO-REによりコンパイル済みプログラムをバージョン差異を気にせずロードでき、互換性の問題は大きく緩和されます。
C言語を書けないSREでもeBPFは使える?
使えます。bpftraceのワンライナーならawkに近い記述で即座に計測できますし、Pixie・Falco・Ciliumのような「eBPF内蔵」プロダクトはeBPFを直接書く必要がありません。実際、多くのユーザーはeBPFを直接記述せず、こうしたプロジェクトを通じて間接的に利用しています。
eBPFのオーバーヘッドは?
JITコンパイルにより、検証済みプログラムはネイティブコードに近い速度で動作するとされています。ただし実際のオーバーヘッドはアタッチするイベントの頻度やマップ操作の設計次第で変動します。Tetragonのようにカーネル内でフィルタと集約を行いデータ量を減らす設計が、有力なアプローチとされています。
WindowsでもeBPFは動く?
動きます。Microsoftが「eBPF for Windows」としてMITライセンスで移植を進めており、XDPなどが利用できます。eBPFという概念はLinux固有を超えて、OSを横断する技術へと広がりつつあります。
まとめ
本記事では、eBPFとは「カーネルのソース変更・モジュール・再起動なしに、安全にカーネルへ機能追加する技術」であり、検証器・JIT・マップ・アタッチポイントの連携で高い安全性と高速な実行を両立する設計となっている仕組みを見てきました。この「カーネルのプログラマビリティ」の獲得こそが、オブザーバビリティ・セキュリティ・ネットワーキングの3分野を支え、Meta・Google・Netflixらのプロダクション環境での採用が報告されています。学習曲線という課題はありますが、bpftraceや完成品プロダクトから始めれば今日から実践できます。次の3つのアクションから始めてみてください。
- 検証環境でbpftraceのワンライナーを1つ試す(10分)
- 運用中のKubernetesクラスタでPixieまたはCiliumのPoCを計画する
- 所属組織の監視・セキュリティ・ネットワーク要件を、第4節の比較表に当てはめて評価する
参考文献
※本文中の技術仕様・歴史・バージョン要件に関する記述は、以下の情報源(ebpf.io公式ドキュメント、Wikipedia、各プロジェクト公式リポジトリ)の記載に基づきます。カーネルバージョン固有の要件や最新の対応状況は、導入時に各プロジェクトの公式ドキュメントでご確認ください。