Cilium が eBPF をどう使うか:アイデンティティ、ポリシー、ソケット
Pod の起動、Pod 間の通信、パケットのポリシー判定のときにカーネル内で実際に何が起きているか、そしてなぜ高速なのか。
Cilium を特徴づけるのは、個々の機能ではなく、ネットワーキング、セキュリティ、可観測性のすべてが、iptables ルールやサイドカープロキシを後付けするのではなく、eBPF を通じて Linux カーネル内で直接動作するプログラムとして実装されていることです。このガイドでは、それが実際に何を意味するのかを説明します。Pod が起動したときに何が起こるのか、ポリシーの判定がどのように行われるのか、そして Cilium のネットワークパスが、置き換える代替手段より高速な理由です。
eBPF を一段落で
eBPF を使うと、カーネルモジュールを書いたりカーネル自体にパッチを当てたりすることなく、小さな目的特化のプログラムを実行時に Linux カーネルへロードできます。そのようなプログラムがロードを許可される前に、カーネル内のベリファイアが静的に解析します。プログラムが終了すること(無制限のループがないこと)、安全なメモリ範囲内にとどまること、カーネルをクラッシュさせたりハングさせたりしないことを確認します。このチェックに失敗したプログラムは完全に拒否されるため、ユーザー空間のツールが任意のロジックをカーネル空間にロードしても安全なのです。すべての eBPF プログラムは、事前にコンパイルされたカーネルバイナリとして配布されるのではなく、その都度コンパイルされてロードされます。
Pod が起動するときに起きること
Kubernetes の kubelet は、設定された CNI プラグインに、新しい Pod のネットワーキングを設定するよう依頼します。Cilium がその CNI の場合は次のようになります。
- Cilium は Pod にネットワーク namespace と通常の IP 設定を割り当てます。これは、あらゆる CNI が行う基本的な仕事と同じです。
- Cilium は Pod に、IP アドレスではなく Kubernetes のラベルから導出されるセキュリティアイデンティティを割り当てます。関連するラベル(通常は Deployment のセレクターラベルなど)を共有するすべての Pod は、同じアイデンティティを共有します。Pod の IP は短命で絶えず再割り当てされるため、これは重要です。ラベルに結びついたアイデンティティは、IP アドレスでは不可能な形で、再起動や再スケジュールを経ても安定しています。
- Cilium は、Pod のネットワーク namespace に eBPF プログラムをアタッチします。この時点以降、そのプログラムは、この Pod に関わるすべてのネットワークイベントを監視し、対処できます。接続のオープン、パケットの到着、他のサービスや外部へのリクエストの送信などです。
ポリシーの判定は、セッション単位ではなくパケット単位
従来のファイアウォールは、一般に「allow established」を実装しています。いったん接続が許可されると、その後のパケットはすべて再評価なしで通過し、新しい接続だけがポリシーに照らしてチェックされます。Cilium の eBPF ベースの適用は、接続の最初のセットアップだけでなく、個々のパケットすべてを現在のポリシーに照らして評価します。
実際的な結果として、ネットワークポリシーを変更すると、すでに開いている接続を含むすべてのトラフィックに、変更が即座に効力を持ちます。確立済みのセッションが、閉じて再び開くまで古いルールの下で流れ続けるという期間は存在しません。
可観測性は同じイベントストリームから、無料で得られる
ポリシー判定を行う同じ eBPF のインストルメンテーションが、観測したすべてのネットワークのやり取りに対してイベントも生成します。接続の試行、許可および拒否されたトラフィック、外部の宛先へのリクエストなどです。これにより、Cilium はトラフィックを、実際に生成したプロセスに帰属させることもできます。「この Pod がその Pod と通信した」だけでなく、Pod 内のどの特定のプロセスが接続を開いたかまで分かります。これは、サイドカーのエッジでのディープパケットインスペクションのようなアプローチでは、通常、後から再構築できない詳細レベルです。このイベントストリームは、Cilium 自身の可観測性ツールである Hubble の基盤で、この技術のトップページの主要な概念で説明されています。
ソケットレベルのロードバランシング:パケット書き換えを省略する
Kubernetes Service への到達は、従来、Service の仮想 IP 宛てのパケットが実際のバックエンド Pod の IP に書き換え(NAT)られることを意味しました。この手順は歴史的に、すべてのパケットが通過しなければならない iptables や IPVS のルールで実装されてきました。Cilium はこの変換を、接続時にソケット層で行います。プロセスが connect() を呼び出す場所やデータを送信する場所にアタッチされた eBPF フックを使います。アプリケーションの接続は、最初から選ばれたバックエンドを直接指すように設定され、後続のパケットを 1 つずつ転送中に書き換える必要がありません。これによりパケットごとのオーバーヘッドがかなり削減され、特にスループットが高い、またはレイテンシーに敏感なサービス間トラフィックで顕著です。
kube-proxy を完全に置き換える
標準の Kubernetes バイナリに含まれる kube-proxy は、デフォルトで iptables または IPVS ルールを使って Service のルーティング(ClusterIP、NodePort など)を実装しています。Cilium は kube-proxy を完全に置き換え、同じ Service ルーティングのロジックを eBPF で実装できます。純粋なパフォーマンスだけでなく、運用上の特性も変わります。大規模な iptables のルールセットは相互に依存する 1 つの構造であり、1 つのルールの変更でセット全体の再ロードが必要になることがあります。Cilium の eBPF ベースのルールは独立したアトミックなエントリに近く、1 つを変更しても他に触れる必要がありません。
「速い」だけではない、この仕組みが重要な理由
パフォーマンスは目立つ利点ですが、より深い点はアーキテクチャにあります。Cilium は iptables ルールの積み重ねや Pod ごとのサイドカーではなくカーネルレベルで動作するため、ネットワーキング、セキュリティポリシー、ロードバランシング、可観測性のすべてが、同じ基盤のイベントストリームと同じカーネルレベルの適用ポイントを利用します。互いに整合していることを個別に設定し、同期を保ち、信頼しなければならない 4 つの別々のシステムになるのとは違います。このシリーズの残りは、その基盤の上に構築されています。クラスターのセットアップ、Gateway API、ネットワークポリシーの作成、BGP ルートアドバタイズです。
人気のガイド
-
Cilium 用にクラスターを準備する:まずデフォルトの CNI を無効にする Cilium はクラスターのネットワーキングを完全に置き換えるため、ほとんどのアドオンよりも作業の順序が重要になります。 -
Cilium の Gateway API サポートで Service を公開する GatewayClass、Gateway、HTTPRoute:ホストベースのルーティング、パスマッチング、URL リライト、TLS。専用のゲートウェイ Pod は不要です。 -
ネットワークポリシーを書く:L3/L4 から L7 ルールまで Kubernetes はすべての Pod が他のすべての Pod に到達できる状態から始まります。CiliumNetworkPolicy はそれを絞り込む手段で、必要なら HTTP メソッドまで制限できます。