- Authors

- Name
- Youngju Kim
- @fjvbn20031
Cilium eBPFデータパス深層分析:パケット処理パイプライン
概要
CiliumのeBPFデータパスはLinuxカーネル内でパケットを処理する高性能ネットワークパイプラインです。この記事ではパケットがPodで送受信される際に通る全プロセスを詳細に分析します。
1. パケット処理フロー概要
1.1 イングレスパケットフロー(外部 -> Pod)
外部ネットワーク
|
v
[物理NIC] eth0
|
v
[XDPプログラム](オプション)
- NodePortアクセラレーション
- DDoS防御
- プリフィルタリング
|
v
[tc ingress: from-netdev]
- ソースIdentityルックアップ(ipcache)
- トンネルデカプセル化(VXLAN/Geneve)
- NodePort DNAT
|
v
[ルーティング決定]
- ローカルPod? -> cilium_host
- リモートノード? -> トンネルまたはダイレクトルーティング
|
v
[cilium_host: to-host]
- ホストファイアウォールポリシー確認
|
v
[tc egress: to-container](lxc*)
- 宛先Identity確認
- イングレスポリシー確認
- L3/L4フィルタリング
- conntrackエントリ作成/更新
- L7リダイレクション(必要に応じてEnvoyへ)
|
v
[Podネットワーク名前空間]
1.2 イグレスパケットフロー(Pod -> 外部)
[Podネットワーク名前空間]
|
v
[tc ingress: from-container](lxc*)
- ソースエンドポイント識別
- イグレスポリシー確認
- サービスDNAT(kube-proxy代替)
- conntrackルックアップ/作成
- L7リダイレクション(必要に応じて)
|
v
[ルーティング決定]
- 同一ノードPod? -> 直接配送
- リモートPod? -> トンネルまたはダイレクトルーティング
- 外部? -> SNAT(マスカレード)
|
v
[tc egress: to-netdev](eth0)
- SNAT適用
- トンネルカプセル化(VXLAN/Geneve)
|
v
[物理NIC] eth0
|
v
外部ネットワーク
2. BPFプログラム詳細
2.1 from-container(Podイグレス)
Podから出ていくパケットを処理する最初のBPFプログラムです。
// 概念的なfrom-container処理フロー(簡略化)
// 実際のコード:bpf/bpf_lxc.c - handle_xgress()
int from_container(struct __sk_buff *skb) {
// 1. パケットパース(L2/L3/L4ヘッダー)
// 2. ソースエンドポイント識別
// 3. イグレスポリシー確認
// - IdentityベースL3/L4ポリシー
// - CIDRポリシー
// - L7ポリシー -> Envoyリダイレクション
// 4. サービスロードバランシング
// - ClusterIP DNAT
// - NodePort DNAT
// 5. conntrack処理
// 6. ルーティング決定
// - 同一ノード:tail call to-container
// - リモートノード:トンネルカプセル化またはダイレクトルーティング
// - 外部:SNAT
return TC_ACT_OK; // or TC_ACT_SHOT(drop)
}
主要な処理ステージ:
| ステージ | 説明 | 使用BPFマップ |
|---|---|---|
| パケットパース | L2/L3/L4ヘッダー抽出 | - |
| エンドポイント識別 | ソースPod確認 | cilium_lxc |
| ポリシー確認 | イグレスポリシーマッチング | cilium_policy |
| サービスLB | ClusterIP/NodePort DNAT | cilium_lb4_services |
| conntrack | 接続状態追跡 | cilium_ct4_global |
| ルーティング | 宛先ノード決定 | cilium_ipcache、cilium_tunnel_map |
2.2 to-container(Podイングレス)
Podに入ってくるパケットを処理するBPFプログラムです。
// 概念的なto-container処理フロー
// 実際のコード:bpf/bpf_lxc.c - handle_ingress()
int to_container(struct __sk_buff *skb) {
// 1. パケットパース
// 2. ソースIdentityルックアップ
// - ipcacheでソースIP -> Identityマッピング
// 3. イングレスポリシー確認
// - IdentityベースL3/L4ポリシー
// - L7ポリシー -> Envoyリダイレクション
// 4. conntrack更新
// 5. reverse NAT(応答パケットの場合)
// 6. Podへ配送
return TC_ACT_OK;
}
2.3 from-overlay / to-overlay
オーバーレイネットワーク(VXLAN/Geneve)を通じたパケット処理です。
VXLAN受信フロー:
[物理NIC] -> [VXLANデカプセル化] -> [from-overlay BPF]
- 内部Identity抽出(Geneve TLVまたはソースIPベース)
- 宛先エンドポイントルックアップ
- ポリシー確認
- 対象Podへ配送
VXLAN送信フロー:
[from-container BPF] -> [ルーティング:リモートノード] -> [to-overlay BPF]
- Identity情報をトンネルヘッダーに含める
- VXLAN/Geneveカプセル化
- 物理NICへ転送
3. コネクショントラッキング実装
3.1 conntrack構造
Ciliumは独自のeBPFベースコネクショントラッキングを実装しています。
// conntrackキー構造(概念的)
struct ct_key {
__u32 src_ip;
__u32 dst_ip;
__u16 src_port;
__u16 dst_port;
__u8 protocol; // TCP、UDP、ICMP
__u8 direction; // ingress、egress
};
// conntrack値構造
struct ct_entry {
__u64 rx_packets;
__u64 rx_bytes;
__u64 tx_packets;
__u64 tx_bytes;
__u32 lifetime;
__u16 rev_nat_index; // reverse NATインデックス
__u16 src_sec_id; // ソースIdentity
__u32 flags;
};
3.2 conntrackステートマシン
TCP接続状態追跡:
SYN -> [NEW] -> SYN-ACK -> [ESTABLISHED] -> FIN -> [CLOSING] -> [CLOSED]
状態別タイムアウト:
- NEW:60秒
- ESTABLISHED:6時間(TCP)、60秒(UDP)
- CLOSING:10秒
3.3 conntrackの活用
# conntrackテーブル照会
cilium bpf ct list global
# TCP接続の出力例:
# TCP IN 10.244.1.5:34567 -> 10.96.0.1:443
# Expires: 21590s Identity: 48291
# RxPackets: 142 RxBytes: 15234
# TxPackets: 138 TxBytes: 12890
# Flags: rx+tx established
# conntrackエントリ数の確認
cilium bpf ct list global | wc -l
# 特定IPのconntrackフィルタリング
cilium bpf ct list global | grep "10.244.1.5"
3.4 conntrack GC(ガベージコレクション)
期限切れのconntrackエントリは定期的にクリーンアップされます。
Agent内部GCループ:
1. BPFマップの全エントリを走査
2. タイムアウト期限切れエントリを識別
3. 期限切れエントリを削除
4. 関連NATエントリも合わせて削除
5. メトリクスの更新
GC周期:設定可能(デフォルト約12秒)
4. NATエンジン
4.1 SNAT(Source NAT / マスカレード)
Podからクラスタ外部へ出るトラフィックのソースIPをノードIPに変換します。
SNAT処理フロー:
Pod(10.244.1.5:34567)-> 外部(8.8.8.8:443)
|
v
[from-container BPF]
- 宛先がクラスタ外部か確認
- SNATの必要性を判断
|
v
[SNATエンジン]
- ソースIPをノードIPに変換(10.244.1.5 -> 192.168.1.100)
- ソースポートをエフェメラルポートに変換
- NATマッピングをBPFマップに保存
|
v
ノードIP(192.168.1.100:50123)-> 外部(8.8.8.8:443)
応答パケット(Reverse SNAT):
外部(8.8.8.8:443)-> ノードIP(192.168.1.100:50123)
|
v
[to-netdev BPF]
- NATマッピングから元のソースを照会
- 宛先を元のPod IP/ポートに復元
|
v
外部(8.8.8.8:443)-> Pod(10.244.1.5:34567)
4.2 DNAT(サービスロードバランシング)
KubernetesサービスIPを実際のバックエンドPod IPに変換します。
サービスDNATフロー:
クライアント(10.244.1.5)-> Service(10.96.0.10:80)
|
v
[from-container BPF:サービスLB]
- cilium_lb4_servicesでサービスをルックアップ
- バックエンド選択(ラウンドロビン、Maglevなど)
- 宛先IP/ポートをバックエンドに変換
|
v
クライアント(10.244.1.5)-> Backend Pod(10.244.2.10:8080)
4.3 Maglev一貫性ハッシュ
MaglevはGoogleが開発した一貫性ハッシュアルゴリズムで、Ciliumのサービスロードバランシングに使用されます。
Maglevハッシュ処理過程:
1. ルックアップテーブル作成(65537エントリ)
- 各バックエンドがテーブルの複数の位置にマッピング
- バックエンド数に関係なく均一な分布
2. パケットハッシュ計算
- 5-tupleハッシュ:src_ip + dst_ip + src_port + dst_port + protocol
- ハッシュ値でテーブルインデックスを決定
3. バックエンド選択
- table[hash % table_size] = backend
バックエンド変更時の影響:
- 1つのバックエンド追加/削除 -> 約1/Nの接続のみ再マッピング
- 既存接続の大部分を維持
4.4 サービスタイプ別処理
ClusterIP:
- from-containerでDNAT
- ソケットレベルLB(bpf_sock)またはtcレベル
NodePort:
- XDPまたはtc ingress(from-netdev)でDNAT
- DSRモード:応答パケットを直接配送
- SNATモード:元のノードを通じて応答
LoadBalancer:
- NodePortと同一の処理 + ExternalIPマッピング
- LB-IPAMによるIP割り当て
ExternalTrafficPolicy: Local
- ローカルバックエンドがある場合のみ処理
- クライアントソースIPを保持
5. DSR(Direct Server Return)モード
5.1 DSRの動作原理
DSRモードでは応答パケットが元のリクエストを受信したノードを経由せず直接クライアントに配送されます。
DSRフロー:
1. クライアント -> ノードA(NodePort)
[ノードA:DNAT + DSRオプション設定]
- 宛先をバックエンドPod(ノードB)に変換
- IPオプションに元のサービスIP/ポートをエンコード
2. ノードA -> ノードB(バックエンドPod)
[ノードB:DSRオプション処理]
- IPオプションから元のサービスIP/ポートを復元
- conntrackにreverse NAT情報を保存
3. ノードB(バックエンドPod)-> クライアント
[ノードB:reverse NAT]
- ソースIPをサービスIPに変換
- ノードAを経由せず直接応答
通常モード(SNAT):
クライアント -> ノードA -> ノードB -> ノードA -> クライアント
(2ホップ追加)
DSRモード:
クライアント -> ノードA -> ノードB -> クライアント
(応答は直接)
6. eBPFテールコール:プログラムチェイニング
6.1 テールコールメカニズム
eBPFプログラムには命令数制限があるため、複雑な処理を複数のプログラムに分離します。
テールコールチェーン例:
[from-container]
|
tail_call -> [IPv4ポリシー確認]
|
tail_call -> [サービスLB]
|
tail_call -> [NAT処理]
|
tail_call -> [転送]
6.2 Ciliumの主要テールコールポイント
CILIUM_CALL_IPV4_FROM_LXC = 0 // IPv4 from-containerエントリ
CILIUM_CALL_IPV4_CT_INGRESS = 4 // IPv4 conntrackイングレス
CILIUM_CALL_IPV4_CT_EGRESS = 5 // IPv4 conntrackイグレス
CILIUM_CALL_IPV4_NODEPORT_NAT = 13 // NodePort NAT
CILIUM_CALL_IPV4_NODEPORT_DSR = 14 // NodePort DSR
CILIUM_CALL_IPV4_ENCAP = 15 // トンネルカプセル化
CILIUM_CALL_SEND_ICMP_UNREACH = 18 // ICMP Unreachable送信
CILIUM_CALL_SRV6_ENCAP = 23 // SRv6カプセル化
7. ソケットレベルロードバランシング
7.1 ソケットLBの概要
ソケットレベルロードバランシングはiptablesやtcレベルのNATをバイパスし、connect()システムコール時点でサービスIPをバックエンドIPに直接変換します。
従来の方式(iptables/tc):
connect(サービスIP) -> [カーネルネットワークスタック] -> [NAT] -> [conntrack] -> バックエンド
ソケットLB方式:
connect(サービスIP) -> [BPF sock_ops] -> connect(バックエンドIP)
- NAT不要
- conntrackエントリ不要
- ネットワークスタックオーバーヘッド除去
7.2 ソケットLBの利点
パフォーマンス比較:
tcレベルLB:
- パケットごとにNAT実行
- conntrackエントリが必要
- 追加CPUサイクル
ソケットレベルLB:
- 接続ごとに1回のみ変換
- conntrack不要
- 最小CPUオーバーヘッド
- 元のサービスIPを保持(getpeername)
8. パケットドロップとモニタリング
8.1 ドロップ理由コード
Ciliumはパケットドロップ時に詳細な理由コードを提供します。
# ドロップされたパケットのモニタリング
cilium monitor --type drop
# 出力例:
# xx drop (Policy denied) flow ...
# xx drop (Invalid source ip) flow ...
# xx drop (CT: Map insertion failed) flow ...
主要なドロップ理由:
| コード | 説明 |
|---|---|
| Policy denied | ポリシーにより拒否 |
| Invalid source ip | ソースIPが無効 |
| CT: Map insertion failed | conntrackマップ挿入失敗 |
| No mapping for NAT | NATマッピングなし |
| Unknown L3 target | L3宛先が不明 |
| Authentication required | mTLS認証が必要 |
| Service backend not found | サービスバックエンドなし |
8.2 パケットトレーシング
# リアルタイムパケットトレース
cilium monitor --type trace
# 特定エンドポイントのトラフィックのみモニタリング
cilium monitor --type trace --from-endpoint 1234
# ポリシーverdictモニタリング
cilium monitor --type policy-verdict
# デバッグレベルモニタリング
cilium monitor --type debug
9. パフォーマンス最適化技法
9.1 XDPアクセラレーション
XDPモード別パフォーマンス:
- XDP native(ドライバ内蔵):最高パフォーマンス
- XDP generic(ソフトウェア):互換性優先
- XDP offload(NICハードウェア):特定NICのみサポート
9.2 BIG TCP
BIG TCPの動作:
- GRO(Generic Receive Offload)で受信パケットを64KB+サイズに統合
- 内部的に大容量パケットとして処理しパケットあたりのオーバーヘッドを削減
- GSO(Generic Segmentation Offload)で送信時に分割
9.3 eBPFプログラム最適化
コンパイル時最適化:
- 未使用機能をコンパイルから除外
- ポリシーのないエンドポイント:最小限のBPFコード
- IPv4専用環境:IPv6コードを除去
ランタイム最適化:
- BPFマッププリフェッチ
- インライン関数の活用
- 不要な条件分岐の除去
- JITコンパイルによるネイティブコード実行
まとめ
CiliumのeBPFデータパスは以下の核心設計で高性能を達成しています。
- カーネル内処理:すべてのパケット処理がカーネル空間で行われユーザー空間遷移オーバーヘッドを除去
- テールコールチェイニング:複雑なロジックを複数のBPFプログラムに分離しモジュール性を確保
- 独自conntrack:Linux netfilter conntrackの代わりにBPFマップベースの高性能コネクショントラッキング
- ソケットレベルLB:NATなしでサービスロードバランシングし最小オーバーヘッド
- DSRモード:不要なネットワークホップを除去し応答レイテンシーを削減
- XDPアクセラレーション:ネットワークドライバレベルで超高速パケット処理