eBPF 整理 — カーネルを再コンパイルせずに拡張する技術

読了 6分

Cilium、Falco、Pixie、Katran。ここ数年、インフラツールの紹介ページのあちこちに eBPF という単語が登場します。結論を先に書くと、eBPF はカーネルを再コンパイルしたりモジュールをインストールしたりせずに、検証済みの小さなプログラムを実行中のカーネルの中で安全に動かす技術です。「カーネルのプログラマブル化」と呼ぶことができ、可観測性・ネットワーキング・セキュリティのツール群がこの 10 年でこの上に移り住みました。この記事ではその原理と地形を整理します。

問題 — カーネルの中で起きていることを見たい #

システムの真実はカーネルの中にあります。どのプロセスがどのファイルを開き、パケットがどこで捨てられ、ディスク I/O がどこで遅延しているのか。ところが、カーネルの中をのぞいたり動作を変えたりする伝統的な方法は、どちらも問題を抱えていました。

  • カーネルモジュール: 何でもできますが、バグひとつがカーネルパニックになります。モジュールひとつのためにサーバー全体が死ぬリスクを、本番で引き受けるのは困難です。
  • ユーザースペースのツール: 安全ですが遅く、限定的です。たとえばパケットをユーザースペースにコピーしてきて検査する方式は、コピーのコスト自体がボトルネックになります。

eBPF は第三の道です。小さなプログラムをカーネル内の仮想マシンで実行しつつ、ロード前に検証器(verifier)が安全性を静的に証明します。カーネルの速度と視野を得ながら、モジュールのリスクは負わない構造です。

動作原理 — 検証器という門番 #

eBPF プログラムのライフサイクルはこうです。

  1. プログラム(普通は C で書いてバイトコードにコンパイル)をカーネルにロードします。
  2. 検証器がすべての実行経路を検査します。 終了が保証されないループ、許可範囲外のメモリアクセス、未初期化の値の使用があれば、ロード自体が拒否されます。「カーネルの中で動くのにカーネルを殺せない」理由がこの門番です。
  3. 通過したプログラムは JIT コンパイルされ、ネイティブ速度で実行されます。
  4. フック(hook)に接続されます。特定のカーネルイベントが起きるたびにプログラムが呼ばれる構造です。
  5. 収集したデータはマップ(map)というカーネル内のデータ構造にたまり、ユーザースペースのツールがそれを読み出します。

フック地点がそのまま活用先の地図になります。

フックいつ呼ばれるか代表的な用途
kprobe / kretprobeほぼすべてのカーネル関数の進入・復帰任意地点のトレーシング
tracepointカーネルが公式に提供する安定した計測点システムコール、スケジューラー、I/O の追跡
uprobeユーザースペースの関数アプリケーション関数の追跡
XDPNIC ドライバー、ネットワークスタック進入前超高速パケットフィルター・ロードバランシング
tc / socketネットワークスタックの各段階トラフィック制御、ポリシー
LSMセキュリティ決定地点ランタイムセキュリティポリシー

何に使われるか — 3 つの枝 #

可観測性(observability)が最も触れやすい枝です。従来の方式はアプリケーションに計測コードを入れるかサンプリングプロファイラーを付ける必要がありましたが、eBPF はカーネルイベントから直接データを取るので、対象プロセスを修正も再起動もせずにシステム全体を見られます。「どのプロセスがどのファイルを開いているか」「TCP 再送はどこから出ているか」「ディスク遅延の分布はどうか」といった問いがワンライナーで解けます。サーバーが遅い系の診断で標準ツールが答えをくれないとき、次の層として取り出す道具です。

ネットワーキングは eBPF が業界を変えた枝です。XDP はパケットがカーネルのネットワークスタックに入る前、NIC ドライバーのレベルで eBPF プログラムを回します。毎秒数百万パケットのフィルタリング・転送が可能になり、DDoS 防御や L4 ロードバランサーがこの上に建てられました。Kubernetes の世界では Cilium が iptables のチェーンの代わりに eBPF でポッドのネットワーキング・ポリシー・ロードバランシングを実装し、CNI の事実上の標準軸になりました。

セキュリティは、システムコールとカーネルイベントをリアルタイムに観察してポリシー違反を検知・遮断する枝です。Falco、Tetragon のようなランタイムセキュリティツールが「コンテナが突然シェルを実行した」「想定外のパスに書き込みをした」を捕まえる基盤が eBPF です。

触ってみる — 道具のはしご #

eBPF を使うために C とカーネルに詳しくなる必要はありません。はしごがあります。

  1. bpftrace: awk に似たワンライナー言語です。学習コスト対効用が最も大きい入り口です。
  2. bcc ツール集: execsnoop(プロセス実行の追跡)、opensnoop(ファイルオープン)、biolatency(ディスク遅延のヒストグラム)、tcpretrans(TCP 再送)など、できあいのツール数十個がパッケージでインストールされます。運用の疑問の大半はこの既成ツールで片付きます。
  3. libbpf + CO-RE: 自前のツール・製品を作る段階です。CO-RE(Compile Once, Run Everywhere)が、カーネルバージョンごとに再コンパイルしていた苦痛を大きく減らしました。
bpftrace ワンライナー
# 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 権限とカーネルバージョン依存が現実的な制約なので、導入検討は「うちのカーネルでこのツールは動くか」から始めます。
X