LabHub

ブログ

eBPF完全ガイド2025:カーネルプログラミング、Observability、ネットワーキング、セキュリティの革命

한국어English日本語

TL;DR


1. eBPFとは何か?

1.1 一行(いちぎょう)定義(ていぎ)

eBPFはオペレーティングシステムカーネルを修正(しゅうせい)せずにカーネル内部(ないぶ)でサンドボックス化(か)されたプログラムを実行(じっこう)できる技術(ぎじゅつ)である。

伝統的(でんとうてき)にカーネル機能(きのう)を拡張(かくちょう)するには2つの方法(ほうほう)しかありませんでした:

  1. カーネル自体(じたい)にコード追加(ついか) → 貢献(こうけん)が難(むずか)しく、マージされてもユーザーは新(あたら)しいカーネルバージョンを待(ま)たなければならない
  2. カーネルモジュールのロード → 誤(あやま)って書(か)くとシステムクラッシュの危険(きけん)。カーネルABI変更(へんこう)に脆弱(ぜいじゃく)

eBPFは第三(だいさん)の道(みち)を提示(ていじ)します — カーネル内(ない)で安全(あんぜん)にカスタムコードを実行(じっこう)

1.2 どのように安全性(あんぜんせい)を保証(ほしょう)するか?

eBPFプログラムはカーネルにロードされる前(まえ)、BPF Verifier(検証器(けんしょうき))の静的(せいてき)解析(かいせき)を通過(つうか)しなければなりません:

検証器(けんしょうき)通過(つうか)後(ご)、JITコンパイラがネイティブマシンコードに変換(へんかん)してほぼネイティブ速度(そくど)で実行(じっこう)されます。

1.3 cBPFからeBPFへの進化(しんか)

特性(とくせい)cBPF (1992)eBPF (2014~)
用途(ようと)パケットフィルタリングのみ汎用(はんよう)カーネルプログラミング
レジスタ2個(こ)(32ビット)11個(こ)(64ビット)
命令(めいれい)22個(こ)100+
ヘルパー関数(かんすう)なし200+
マップなし30+ 種類(しゅるい)
JIT一部(いちぶ)アーキテクチャほとんどのアーキテクチャ

tcpdumpが使用(しよう)したcBPFは単純(たんじゅん)なパケットフィルタでしたが、eBPFは小型(こがた)仮想(かそう)マシンに進化(しんか)しました。


2. eBPFアーキテクチャ深層(しんそう)分析(ぶんせき)

2.1 コンポーネント概要(がいよう)

┌─────────────────────────────────────────────┐
ユーザー空間(くうかん) (User Space)│  ┌──────────┐  ┌──────────┐  ┌──────────┐  │
│  │ bpftool  │  │ bpftrace │  │ Cilium   │  │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  │
│       │             │             │         │
│       └─────────────┼─────────────┘         │
│                     │ bpf() syscall          │
└─────────────────────┼───────────────────────┘
┌─────────────────────────────────────────────┐
カーネル空間(くうかん) (Kernel Space)│  ┌─────────────────────────────────────┐   │
│  │  BPF Verifier                       │   │
│  └──────────────┬──────────────────────┘   │
│                 ▼                            │
│  ┌─────────────────────────────────────┐   │
│  │  JIT Compiler                       │   │
│  └──────────────┬──────────────────────┘   │
│                 ▼                            │
│  ┌─────────────────────────────────────┐   │
│  │  Hooks: kprobe, tracepoint, XDP,    │   │
│  │  perf_event, socket, cgroup, LSM    │   │
│  └─────────────────────────────────────┘   │
└─────────────────────────────────────────────┘

2.2 主要(しゅよう)フック種類(しゅるい)

eBPFプログラムは様々(さまざま)なカーネルイベントにアタッチできます:

フック種類(しゅるい)説明(せつめい)例(れい)
kprobe / kretprobeカーネル関数(かんすう)進入(しんにゅう)/終了(しゅうりょう)do_sys_open呼(よ)び出(だ)し追跡(ついせき)
uprobe / uretprobeユーザー空間(くうかん)関数(かんすう)OpenSSLのSSL_read追跡(ついせき)
tracepointカーネル静的(せいてき)追跡(ついせき)ポイントsched:sched_switch
perf_eventハードウェア/ソフトウェアカウンタCPUサイクル、キャッシュミス
XDPネットワークドライバDDoSフィルタリング
TC (Traffic Control)トラフィックシェーピングQoS、ロードバランシング
LSMセキュリティポリシーファイルアクセス制御(せいぎょ)

2.3 BPF Maps — 核心(かくしん)データ構造(こうぞう)

eBPFプログラムとユーザー空間(くうかん)間(かん)のデータ共有(きょうゆう)はBPF Mapsを通(つう)じて行(おこな)われます:

マップ種類(しゅるい)用途(ようと)
BPF_MAP_TYPE_HASH一般(いっぱん)的(てき)なキー値(ち)保存(ほぞん)
BPF_MAP_TYPE_ARRAY配列(はいれつ)(インデックスベース)
BPF_MAP_TYPE_PERF_EVENT_ARRAYユーザー空間(くうかん)へのイベントストリーミング
BPF_MAP_TYPE_RINGBUFより効率的(こうりつてき)なイベントストリーミング
BPF_MAP_TYPE_LRU_HASHLRUキャッシュ
BPF_MAP_TYPE_LPM_TRIE最長(さいちょう)プレフィックス一致(いっち)

3. 開発(かいはつ)ツール比較(ひかく)

3.1 BCC (BPF Compiler Collection)

3.2 bpftrace — DTraceの後継者(こうけいしゃ)

# プロセス別(べつ)システムコール呼(よ)び出(だ)し回数(かいすう)
bpftrace -e 'tracepoint:syscalls:sys_enter_* { @[comm] = count(); }'

# 1秒(びょう)以上(いじょう)かかるread()システムコール追跡(ついせき)
bpftrace -e '
kprobe:vfs_read { @start[tid] = nsecs; }
kretprobe:vfs_read /@start[tid]/ {
    $duration = nsecs - @start[tid];
    if ($duration > 1000000000) {
        printf("%s pid %d took %d ms\n", comm, pid, $duration / 1000000);
    }
    delete(@start[tid]);
}'

3.3 libbpf + CO-RE — 本番(ほんばん)標準(ひょうじゅん)

3.4 ツール比較(ひかく)表(ひょう)

ツール学習(がくしゅう)曲線(きょくせん)性能(せいのう)デプロイ容易性(よういせい)適切(てきせつ)な用途(ようと)
BCC中(ちゅう)中(ちゅう)難(むずか)しい学習(がくしゅう)、一回性(いっかいせい)分析(ぶんせき)
bpftrace易(やさ)しい高(たか)い中(ちゅう)即席(そくせき)トレーシング
libbpf + CO-RE難(むずか)しい非常(ひじょう)に高(たか)い易(やさ)しい本番(ほんばん)ツール開発(かいはつ)
Aya (Rust)難(むずか)しい非常(ひじょう)に高(たか)い易(やさ)しいRustエコシステム統合(とうごう)

4. eBPFの3大(だい)活用(かつよう)分野(ぶんや)

4.1 Observability — 観測性(かんそくせい)

eBPFはアプリケーションコード変更(へんこう)なしにシステム動作(どうさ)を深(ふか)く観察(かんさつ)します。

Pixie — Kubernetes Native Observability

Parca — Continuous Profiling

4.2 Networking — ネットワーキング

Cilium — eBPFベースK8sネットワーキングの標準(ひょうじゅん)

XDP — 超高速(ちょうこうそく)パケット処理(しょり)

XDPはネットワークドライバレベルでパケットを処理(しょり)します — カーネルネットワークスタックを通過(つうか)しません。

4.3 Security — セキュリティ

Falco — ランタイムセキュリティ監視(かんし)

Tetragon — Ciliumチームの次世代(じせだい)セキュリティ


5. 実践(じっせん):bpftraceでデバッグする

5.1 シナリオ:ディスクI/Oが急(きゅう)に遅(おそ)くなった

# 1. どのプロセスがディスクI/Oを引(ひ)き起(お)こしているか?
sudo bpftrace -e '
tracepoint:block:block_rq_issue {
    @[comm] = count();
}
interval:s:5 {
    print(@);
    clear(@);
}'

5.2 シナリオ:未知(みち)のファイルが開(ひら)かれている

sudo bpftrace -e '
tracepoint:syscalls:sys_enter_openat {
    printf("%s opened: %s\n", comm, str(args->filename));
}'

6. CO-RE:一度(いちど)コンパイル、どこでも実行(じっこう)

6.1 問題(もんだい):カーネルバージョンごとに構造体(こうぞうたい)が異(こと)なる

伝統的(でんとうてき)なBCCは実行(じっこう)時点(じてん)でカーネルヘッダを使用(しよう)してコンパイルしました。しかしコンテナではホストカーネルヘッダにアクセスしにくく、コンパイル時間(じかん)も長(なが)かったです。

6.2 解決策(かいけつさく):BTF + CO-RE

BTF:カーネルが自分(じぶん)の構造体(こうぞうたい)情報(じょうほう)を/sys/kernel/btf/vmlinuxに公開(こうかい)します。

CO-RE:コンパイラが構造体(こうぞうたい)フィールドアクセスを「シンボリック」に表現(ひょうげん)し、ローダーがランタイムにBTF情報(じょうほう)で再配置(さいはいち)します。

効果(こうか):一度(いちど)ビルドした.oファイルが5.4から6.5まですべてのカーネルで動作(どうさ)。


7. 本番(ほんばん)事例(じれい)

7.1 Netflix — bpftraceで性能(せいのう)デバッグ

NetflixのBrendan Greggは最(もっと)も影響力(えいきょうりょく)のあるeBPF擁護者(ようごしゃ)です。Netflixは数万(すうまん)個(こ)のEC2インスタンスでBCCとbpftraceを活用(かつよう)して:

7.2 Cloudflare — XDPでDDoS防御(ぼうぎょ)

7.3 Meta (Facebook) — すべての場所(ばしょ)でeBPF

7.4 Google — Ciliumを利用(りよう)したGKE Dataplane V2


8. eBPFの限界(げんかい)と挑戦(ちょうせん)

8.1 検証器(けんしょうき)の制約(せいやく)

8.2 カーネルバージョン依存性(いぞんせい)

8.3 デバッグの難(むずか)しさ


9. eBPFの未来(みらい)

9.1 BPF in Windows

MicrosoftがeBPF for Windowsを開発(かいはつ)中(ちゅう)。Windowsでも同(おな)じeBPFプログラム実行(じっこう)可能(かのう) → 真(しん)のクロスプラットフォームカーネルプログラミング。

9.2 sched_ext — スケジューラをeBPFで

カーネル6.12+で導入(どうにゅう)。CPUスケジューラ自体(じたい)をeBPFで作成(さくせい)可能(かのう) → ワークロード別(べつ)カスタムスケジューリング。


10. eBPF始(はじ)める — 学習(がくしゅう)ロードマップ

Week 1:基礎(きそ)

Week 2-3:BCC

Week 4-6:libbpf + CO-RE

Week 7+:実践(じっせん)プロジェクト


クイズ

1. eBPFプログラムが安全(あんぜん)と保証(ほしょう)される理由(りゆう)は何(なん)ですか?

答(こた)え:カーネルにロードされる前(まえ)、BPF Verifierが静的(せいてき)解析(かいせき)を実行(じっこう)します。無限(むげん)ループ禁止(きんし)、メモリアクセス検証(けんしょう)、許可(きょか)されたヘルパー関数(かんすう)のみ呼(よ)び出(だ)し、命令(めいれい)数(すう)制限(せいげん)などを確認(かくにん)します。検証(けんしょう)を通過(つうか)するとJITコンパイラがネイティブマシンコードに変換(へんかん)してほぼネイティブ速度(そくど)で実行(じっこう)されます。

2. CO-RE(Compile Once, Run Everywhere)が解決(かいけつ)する問題(もんだい)は?

答(こた)え:伝統的(でんとうてき)なBCCは実行(じっこう)時点(じてん)でカーネルヘッダでコンパイルする必要(ひつよう)がありました。これはLLVM依存性(いぞんせい)、長(なが)い起動(きどう)時間(じかん)、コンテナ環境(かんきょう)での困難(こんなん)を引(ひ)き起(お)こしました。CO-REはBTF(BPF Type Format)を活用(かつよう)してコンパイラが構造体(こうぞうたい)フィールドアクセスを「シンボリック」に表現(ひょうげん)し、ローダーがランタイムにBTF情報(じょうほう)で再配置(さいはいち)します。一度(いちど)ビルドした.oファイルが様々(さまざま)なカーネルバージョンで動作(どうさ)します。

3. XDPがiptablesより速(はや)い理由(りゆう)は?

答(こた)え:XDPはネットワークドライバ水準(すいじゅん)でパケットを処理(しょり)します。パケットがカーネルネットワークスタック(skb割(わ)り当(あ)て、conntrackなど)を通過(つうか)する前(まえ)に処理(しょり)するためオーバーヘッドが非常(ひじょう)に少(すく)ないです。Cloudflareは単一(たんいつ)サーバーで毎秒(まいびょう)1千万(せんまん)+ パケットを処理(しょり)し、iptables対比(たいひ)10倍(ばい)以上(いじょう)効率的(こうりつてき)です。

4. Ciliumがkube-proxyをどのように置換(ちかん)しますか?

答(こた)え:kube-proxyはiptablesまたはIPVSルールでService ClusterIPをバックエンドPodにルーティングします。クラスタが大(おお)きくなるとiptablesルールが数千個(すうせんこ)に増(ふ)え性能(せいのう)が低下(ていか)します。CiliumはeBPFプログラムがソケット作業(さぎょう)とパケット処理(しょり)で直接(ちょくせつ)バックエンドを選択(せんたく)するためiptablesルールが必要(ひつよう)ありません。結果的(けっかてき)に一定(いってい)の性能(せいのう)を維持(いじ)しCPU使用量(しようりょう)が低(ひく)いです。

5. bpftraceとlibbpfの違(ちが)いはいつ何(なに)を使用(しよう)すべきですか?

答(こた)えbpftraceは即席(そくせき)トレーシングとデバッグに適(てき)しています。DTraceのような高水準(こうすいじゅん)DSLで1行(ぎょう)で強力(きょうりょく)な分析(ぶんせき)が可能(かのう)です。libbpf + CO-REは本番(ほんばん)ツール開発(かいはつ)に適(てき)しています。小(ちい)さなバイナリ、コンパイラ依存性(いぞんせい)なし、高速(こうそく)起動(きどう)、様々(さまざま)なカーネル互換性(ごかんせい)を提供(ていきょう)します。個人(こじん)デバッグはbpftrace、デプロイするツールはlibbpfで作成(さくせい)するのが一般的(いっぱんてき)です。


参考(さんこう)資料(しりょう)

コメント

まだコメントはありません。

ログインするとコメントできます