← 一覧へ戻る

Claude が書いた記事

Cilium ってなんやねん? ── eBPF が『壁を越えない』速さと、身元 ID を載せて運ぶ仕掛け

「cilium って何?」から始めた学習ログ。eBPF とはカーネル内で安全にプログラムを動かすことができる土台のことで、Cilium はその土台の上に建てた k8s 向けのプログラム。ユーザー空間ではなくカーネル空間で動作させることができるため、高速な通信処理ができる。

俺の最初の疑問

ふと「cilium って何?」と気になった。ニュースやら k8s の文脈やらでよく見るが、腹落ちしていない。

俺はネットワークの技術サポートをやっている。Azure の Application Gateway / Load Balancer / VNet / Front Door あたりが守備範囲で、最近は k8s の overlay やら east-west をかじり始めたところ。だから Cilium も「k8s のネットワーク系の何か」くらいの解像度しかなかった。

素朴な疑問を順に潰していったら、「カーネルの中でパケットを捌く」という、俺が慣れ親しんでいるネットワーク技術とは別レイヤーの話だった。しかも掘っていくと、最後は Azure の SDN とまったく同じ骨格に着地した。その記録。

まず一言でいうと

eBPF = Linux カーネルの中で、自作の小さなプログラムを安全に動かせる仕組み。Cilium = その eBPF を使って建てた、Kubernetes 向けのネットワーク / セキュリティの完成品。

そして eBPF の速さの正体は一行で言える。

パケット (データ) をユーザー空間まで運ばず、カーネルの中で通す / 落とす / 転送まで判断し終えること。

このカーネル空間の中で動作させることこそ、今日いちばん腹落ちしたところだった。

何と比べるとわかるか

二段階で比較すると一気に見通しが良くなった。

① 従来のパケット処理 vs eBPF (壁を越えるか)

Linux はメモリと実行環境が カーネル空間 (OS の中核。ハードウェアに直結できる特権の世界) と ユーザー空間 (普通のアプリが動く世界) に分かれていて、両者は壁で隔離されている。

従来eBPF
処理する場所ユーザー空間のアプリまで運ぶカーネル空間の中でその場で判断
壁の往復行き帰りで 2 回 (コピー + コンテキストスイッチ)越えない (往復ゼロ)
速さパケットが大量だと往復が積もって遅い速い

② eBPF vs Cilium (土台か完成品か)

ここは「どっちがいい」と比べるものではなかった。レイヤーが違う

  • eBPF = 小麦粉。汎用の素材。それ単体では仕事をしない。自分でプログラムを書いて仕込む必要がある。
  • Cilium = パン屋の食パン。その小麦粉で焼いた完成品。買ってすぐ使える。

同じ小麦粉を使う店は他にもある (Falco=セキュリティ、Pixie=可観測性、Katran=Meta のロードバランサ)。Cilium はその中の有力な一つ、という位置づけ。

何が問題なのか

「ユーザー空間にコピーする」が地味に効く。普通の TCP 処理だと、パケットはまずカーネルに届くが、処理したいアプリ (ファイアウォールやパケット解析) はユーザー空間にいる。壁で隔離されているので、データを複製して壁の向こうへ渡す (コピー) + カーネルとユーザー空間を行き来する (コンテキストスイッチ) が要る。

パケットが毎秒何百万個も飛んでくると、この「コピー + 行き来」の積み重ねが大きなオーバーヘッドになる。k8s でサービスが数百個に増えると、従来の iptables ベースのルーティングはルールが膨らんで遅延し始める。eBPF はカーネル内で完結するから、ここを高速に捌ける。

「書類を別の部署に運んで判子をもらって戻す」のではなく、「その場で判断して即処理する」。これが eBPF。

図で見る

1. ベースとなる概念:ユーザー空間とカーネル空間の壁

左 (従来):NIC からカーネルに届いたパケットを、壁の向こうのユーザー空間アプリまで運ぶ。下る①と戻る②で壁を 2 回またぎ、毎回コピー + コンテキストスイッチが起きる=遅い。右 (eBPF):カーネル空間の中の eBPF プログラムがその場で通す / 落とす / 転送を判断。壁を越えないので往復ゼロ=速い。eBPF の速さの正体は『壁を越えないこと』。

2. eBPF と Cilium の関係:土台と完成品 (小麦粉とパン)

下から:Linux カーネル (eBPF が実際に動く場所=1 枚目のカーネル空間) → eBPF (土台技術=小麦粉) → その上の製品たち (Cilium、Falco、Pixie、Katran)。eBPF を使うのは Cilium だけじゃないし、Cilium の中身も eBPF だけじゃない (k8s 連携や Hubble の可視化 UI など周辺も足して『製品』にしている)。だから『どっちがいい』は問いとして成立しない。

3. Cilium の構成:職人 (agent) と機械 (eBPF) の役割分担

cilium-agent (職人) はユーザー空間の普通のプロセスで、カーネルの中には住んでいない。k8s API (共通の頭脳) を見て eBPF (機械) をカーネルに仕込む / 更新する。アプリ Pod もユーザー空間にいて、カーネルにいるのは eBPF だけ。Pod の通信が下りてきて eBPF を通る。台数:agent は DaemonSet で 1 ノード 1 個、operator はクラスタ全体で数個 (冗長)、cilium は人が叩く CLI。

4. ノードまたぎ:身元 ID (identity) を載せて運ぶ

eBPF の魔法は 1 ノード内で完結する。ノード (VM) が別ならカーネルも別物なので、ノードをまたぐ瞬間は現実のネットワークを渡る=魔法が一度切れる。Cilium の橋渡しは 2 つ:①各ノードの agent が k8s API で同期し ID とポリシーを全ノードで揃える ②パケットに送信元の身元 ID (ラベルを数値化したもの) を VXLAN / Geneve で載せて運ぶ。受信側は IP から推測し直さず即判断できる。カプセル化を実行するのはカーネル側 (eBPF + VXLAN 機能) で、agent は設定を仕込むだけ。

混乱しやすいポイント

俺が実際に引っかかって直された点。

① cilium-agent はカーネルに常駐していない

「カーネルで動く」と聞くと agent 自体がカーネルにいる気がするが、違う。agent はユーザー空間の普通のプロセス (デーモン)。カーネルで動くのは、agent が仕込んだ eBPF の方。職人 (agent) は設計図を読んで機械 (eBPF) を据え付けるが、現場 (カーネル) に住み着くわけではない。だから agent が落ちても、すでに仕込まれた eBPF はカーネルで動き続ける

ネットワーク屋の感覚で言うと、cilium-agentbirdfrr(ルーティングデーモン) と同じポジションだ。OS の上に常駐して、設定 (k8s API=設計図) を見て、実際の転送ルール (bird なら FIB、Cilium なら eBPF) を書き換え続けるデーモン。

② アプリ Pod もユーザー空間にいる

これも俺が間違えたところ。アプリ Pod の中身 (コンテナ=普通のプロセス) はユーザー空間で動く。カーネル空間にいるのは eBPF だけ。Pod の「通信」がカーネルに下りてきて eBPF に捌かれるだけで、Pod 自身がカーネルに住んでいるわけではない。

③ eBPF は「プロセス」ではない

プロセスはユーザー空間で動く実行単位。eBPF は カーネル内のフックに取り付けられて、イベント発火時だけ動く実行コード。だから ps で並ぶようなものではない。

④ カプセル化を「誰が」やるのか

ノードまたぎで VXLAN / Geneve に包むのは誰か。答えは カーネル側 (eBPF + カーネルの VXLAN 機能) が実行する。cilium-agent は設定を仕込むだけで、パケット 1 枚ごとには登場しない。もし毎パケット職人が出てきたら、それこそ壁を往復して遅くなる (1 枚目の話に戻る)。

⑤ 「Cilium をやる」に C 言語は要らない

eBPF の中身は制限付き C (xxx.bpf.c) で書かれているが、それを書いて仕込むのは Cilium の仕事。使う側 (大多数) がやるのは k8s の知識・YAML でポリシーを書く・CLI を叩くだけ。C が要るのは Cilium 本体に貢献する / 独自の eBPF を自作する側 (+ Go も要る)。サクッと自分で eBPF を書きたいだけなら bpftrace(.bt、awk 風) という軽い道だ。

⑥ eBPF は k8s 専用じゃない (Linux の機能)

ここを分けておかないと「eBPF=k8s の何か」と誤解する。eBPF は Linux カーネルの汎用機能で、k8s も Docker も要らない (新しめのカーネルがあれば動く。今は Windows 版 ebpf-for-windows まである)。k8s / Cilium は、その eBPF を使う数ある消費者の一つにすぎない。

中央が eBPF (Linux カーネルの汎用機能=土台)。そこから放射状に用途が広がる:tcpdump (BPF の親・30 年前から)、bpftrace / BCC (1 台のサーバーの syscall・性能を覗く)、XDP で DDoS 防御 (NIC 手前で叩き落とす=Cloudflare)、Katran (Meta の L4 ロードバランサ・ベアメタル)、Falco (ホストのセキュリティ監視)。k8s / Cilium (緑) は今回の主役だが、数ある用途の『1 本』にすぎない。だから『壁を越えない速さ』の図は、k8s が一切出てこなくても成立する。

ネットワーク屋として効くのは XDP の例だ。NIC ドライバの一番手前で eBPF を動かし、攻撃パケットをカーネルに入る前に叩き落とす (Cloudflare の DDoS 防御や L4 ロードバランサ Unimog がこれ)。前にやった CDN / Cloudflare の話 の、さらに下のレイヤーで eBPF が効いている。

たとえ話

3 つのたとえが効いた。

  • 小麦粉とパン (eBPF と Cilium)。素材と完成品。レイヤーが違うので「どっちがいい」と比べない。
  • 職人と機械 (agent と eBPF)。職人 (agent・ユーザー空間) が設計図を読んで機械 (eBPF・カーネル) を据え付ける。据え付けた後は機械が自動で動き続け、職人が離れても動く。
  • VFP (Azure) と Cilium (ノードまたぎ)。ここがネットワーク屋として一番でかかった。Cilium が「身元 ID を VXLAN に載せて運ぶ」のは、Azure の SDN が VFP でテナントを分離して運ぶのと同じ骨格だった。
Azure SDN (俺の土俵)Cilium
カプセル化を実行する VFP (ホストのデータパス=カーネル / vSwitch 側)eBPF + カーネルの VXLAN 機能
VXLAN / NVGREVXLAN / Geneve
テナント / VNet を識別する VNI身元 ID (security identity=ラベルの数値化)
ポリシーを配るコントロールプレーンcilium-agent + k8s API

cilium-agent = コントロールプレーン側、eBPF+カーネル = VFP のデータパス側。両方ともコントロールプレーンはパケット 1 枚ごとには出てこない。ここがピタッと重なった瞬間に、Cilium が知らない技術じゃなくなった。(east-west の overlay 自体は前回のPod 間通信と overlay で掴んだ続きでもある。)

ニュースを読むための変換表

言葉つまり何の話?
eBPFLinux カーネル内で自作プログラムを安全に動かす仕組み。検証器が事前チェック。汎用の土台
CiliumeBPF を使った k8s 向けネットワーク / セキュリティの完成品。CNCF Graduated
カーネル空間 / ユーザー空間OS の中核 (特権・ハード直結) / 普通のアプリの世界。壁で隔離されている
cilium-agent各ノード常駐のプロセス (職人)。eBPF を仕込む。DaemonSet で 1 ノード 1 個
cilium-operatorクラスタ全体で数個動く管理役。ノード数と無関係
HubbleCilium の可視化機能。サービス間通信をマップで見る
security identityラベルを数値化した「身元」。IP でなくこれで通信制御。ノードまたぎで載せて運ぶ
DaemonSet全ノードに 1 個ずつ必ず配る k8s の仕組み
VXLAN / Geneveノード間で身元 ID と元パケットを包んで運ぶカプセル (オーバーレイ)
WireGuard (Cilium 透過暗号化)ノードをまたぐ区間だけ、アプリ無改修で通信を暗号化
bpftrace / .bteBPF を awk 風スクリプトでサクッと書く道具
次に答える、設計者の問い で、それがなんやねん?

壁を越えない速さと、Azure の VFP と同じ骨格まで掴んだ。次は設計者として「で、自分なら kube-proxy のまま粘るか、Cilium に替えるか?」。

  • Service が数百〜数千に増えたとき、kube-proxy (iptables) のまま粘るか eBPF (Cilium) に替えるか、即答できるか。 判断軸は「Service 数 × iptables のルール線形探索コスト × 運用の入れ替えコスト」。小規模なら移行コストの方が高い。
  • 責任境界:パケットの行き先を決めてるのは誰か ── カーネル (eBPF・データパス) か、cilium-agent + k8s API (コントロールプレーン・設定) か。 障害時に「agent が落ちた」と「eBPF が壊れた」を切り分けられるか (agent が落ちても eBPF は流れ続ける)。

これに答えられると強い。「Cilium を知ってる」の一歩先 ── 規模から CNI を選び、コントロールプレーンとデータパスのどっちの障害かを切り分けられる側に立てる。Azure の VFP で掴んだ「決めるソフト / 流すハード」がそのまま効く。

深掘りメニュー 次におすすめのトピック
  • kube-proxy / iptables の置き換え ── 規模で遅くなる iptables を、eBPF が east-west の Service ルーティングでどう肩代わりするか。次の一歩。
  • north-south の Cilium (Ingress / Gateway API) ── 入口側を Cilium で見る。AGC の north-south の続き。
  • security identity の正体 ── ラベルがどう数値 ID に変わり、ノード間で同期されるか。Azure の VNI と並べる。
  • Hubble で通信を見る ── kind / minikube に Cilium を入れ、ポリシー違反を可視化する手を動かす入口。
  • bpftrace で eBPF を 1 本書く ── opensnoop 的な数行から、土台をこねて壁を越えない速さを体感する。