Kubernetes オンライン学習: Cilium と eBPF

Kubernetes オンライン学習: Cilium と eBPF

始める前に、少し話がそれますが。 Flannel CNI の最後のリリースから約 1 か月が経ちました。勢いに乗って昨年末に完成させるつもりでしたが、1ヶ月以内に予定していた内容をすべて完成させることができました。しかし、最後の投稿が公開されてから間もなく、私は感染してしまい、回復するまでに1週間以上かかりました。しかし、回復後の状態は私を少し混乱させました。私はいつも集中するのが難しく、気が散りやすいと感じていました。ネット上で広まっている「脳の霧」に近いかもしれないが、Cilium も霧のようなものだ。ネットワークに関する知識が不足し、eBPF の経験も不足していたため、私の学習プロセスは断続的なものでした。かつて私はこの記事が中止されるのではないかと疑っていました。

その記事には必ず問題があるはずだ。何か問題や提案がございましたら、お気軽にお知らせください。

背景

昨年、私は「CiliumによるKubernetesネットワークセキュリティの強化」[1]という記事を書きました。その中で、私はCiliumに触れ、Ciliumのネットワークポリシーを使用して、ネットワークレベルでポッド間の通信を制限する方法を学びました。しかし、当時の私はその実装原理を深く理解しておらず、Kubernetes ネットワークや CNI についても十分に理解していませんでした。今回は、実際の環境を通じて Cilium のネットワークを探索します。

この記事では、Cilium バージョン v1.12.3、オペレーティング システムが Ubuntu 20.04、カーネル バージョンが 5.4.0-91-generic を使用しています。

Ciliumについて

Cilium[2]は、革新的なカーネルテクノロジーeBPF[3]を搭載した、コンテナワークロード(クラウドネイティブ)間のネットワーク接続のプロビジョニング、セキュリティ保護、監視を行うオープンソースソフトウェアです。

Kubernetes 上の cilium

eBPF とは何ですか?

Linux カーネルは、監視/観測性、ネットワーク、セキュリティ機能を実装するのに常に理想的な場所でした。ただし、多くの場合、これは簡単な作業ではありません。これらのタスクではカーネル ソース コードの変更やカーネル モジュールのロードが必要であり、最終的な実装では既存の抽象化レイヤーに新しい抽象化を重ね合わせることになるためです。 eBPF は、カーネル ソース コードを変更したりカーネル モジュールをロードしたりすることなく、カーネル内でサンドボックス プログラムを実行できる革新的なテクノロジです。

Linux カーネルをプログラム可能にすることで、システムの複雑さを増したり、実行効率やセキュリティを犠牲にしたりすることなく、既存の抽象化レイヤーに基づいて (新しいレイヤーを追加するのではなく)、よりスマートで機能豊富なインフラストラクチャ ソフトウェアを構築できるようになります。

Linux カーネルは、ネットワーク スタック上に一連の BPF フックを提供しており、これを通じて BPF プログラムの実行をトリガーできます。 Cilium datapah はこれらのフックを使用して BPF プログラムをロードし、より高度なネットワーク構造を作成します。

CiliumのリファレンスドキュメントeBPF Datapath[4]を読むと、Ciliumが以下のフックを使用していることがわかります。

  • XDP: これは、ネットワーク パケットを受信するときに BPF プログラムをトリガーできるネットワーク ドライバー内のフックであり、最も早いポイントでもあります。この時点では、ネットワーク パケットをメモリに書き込むなどの他の操作は実行されないため、悪意のあるトラフィックや予期しないトラフィックを除去するフィルターや、その他の一般的な DDOS 保護メカニズムを実行するのに最適です。
  • トラフィック制御イングレス/エグレス: ネットワーク インターフェイスに接続できるトラフィック制御 (tc) イングレス フックに接続された BPF プログラム。このフックはネットワーク スタックの L3 の前に実行され、ネットワーク パケットのメタデータのほとんどにアクセスできます。 L3/L4エンドポイント[^1]ポリシーの適用やエンドポイントへのトラフィックの転送など、このノードでの処理操作に適しています。 CNI は通常、VM イーサネット インターフェイス ペア (veth) を使用して、コンテナーをホストのネットワーク名前空間に接続します。ホスト側の veth に接続された tc イングレス フックを使用すると、コンテナから出るすべてのトラフィックを監視し、ポリシーを適用できます。別の BPF プログラムを tc egress フックに接続することで、Cilium はノードに出入りするすべてのトラフィックを監視し、ポリシーを適用できます。
  • ソケット操作: ソケット操作フックは特定の cgroup に接続され、TCP イベントに対して動作します。 Cilium は、BPF ソケット オペレーターをルート cgroup に接続し、それを使用して TCP 状態遷移、特に ESTABLISHED 状態遷移を監視します。ソケットの状態が ESTABLISHED に変更されると、TCP ソケットのピアも現在のノード (またはローカル プロキシ) 上にある場合は、ソケットの送信/受信プログラムが接続されます。
  • ソケットの送信/受信: このフックは、TCP ソケットによって実行されるすべての送信操作で実行されます。この時点で、フックはメッセージを検査し、それをドロップするか、TCP 層に送信するか、別のソケットにリダイレクトすることができます。 Cilium はこれを使用してデータ パスのリダイレクトを高速化します。

これらのフックは後ほど使用するので、ここで詳しく説明します。

環境構築

前回の記事では、k3s を使用し、CNI プラグインを手動でインストールして実験環境を構築しました。今回は、k8eがデフォルトのCNI実装としてCiliumを使用しているため、k8e[5]を直接使用します。

私は今でもホームラボにデュアルノード クラスター (ubuntu-dev2: 192.168.1.12、ubuntu-dev3: 192.168.1.13) を作成しています。

マスターノード:

 curl - sfL https://getk8e.com/install.sh | API_SERVER_IP = 192.168 .1 .12 K8E_TOKEN = ilovek8e INSTALL_K8E_EXEC = " server --cluster-init --write - kubeconfig-mode 644 --write-kubeconfig ~/.kube/config" sh -

ワーカーノード:

 curl - sfL https://getk8e.com/install.sh | K8E_TOKEN = ilovek8e K8E_URL = https://192.168.1.12:6443sh -

サンプル アプリケーションをデプロイし、さまざまなノードにスケジュールします。

ノード1 = Ubuntu - dev2
ノード2 = Ubuntu - dev3
kubectl 適用- n デフォルト- f - << EOF
APIバージョン: v1
種類:ポッド
メタデータ:
ラベル:
アプリ: curl
名前:カール
仕様:
コンテナ:
-画像: curlimages / curl
名前:カール
コマンド: [ "sleep" , "365d" ]
ノード名: $NODE1
---
APIバージョン: v1
種類:ポッド
メタデータ:
ラベル:
アプリ: httpbin
名前: httpbin
仕様:
コンテナ:
-画像: kennethreitz / httpbin
名前: httpbin
ノード名: $NODE2
終了

使いやすくするために、サンプル アプリケーション、繊毛ポッド、その他の情報を環境変数として設定します。

ノード1 = ubuntu-dev2
ノード2 = ubuntu-dev3

cilium1=$(kubectl get po -n kube-system -l k8s-app=cilium --field-selector spec.nodeName=$NODE1 -o jsnotallow='{.items[0].metadata.name}')
cilium2=$(kubectl get po -n kube-system -l k8s-app=cilium --field-selector spec.nodeName=$NODE2 -o jsnotallow='{.items[0].metadata.name}')

トラフィックのデバッグ

これは、リクエストの発信元からネットワーク パケットをずっと追跡するという、従来と同じルーチンです。今回は、サービスを使用してアクセスします: curl http://10.42.0.51:80/get。

 kubectl get po httpbin - n デフォルト- o ワイド
名前 準備完了 ステータス 再起動 年齢 IP ノード 指名ノード 準備完了 ゲート
httpbin 1 / 1実行中0 3 m 10.42 .0 .51 ubuntu - dev3 <なし> <なし>

ステップ1: コンテナがリクエストを送信する

ポッドカールのルーティングテーブルを確認します。

 kubectl exec curl -nデフォルト-- ip ルート 取得 10.42.0.51
10.42 .0 .51経由10.42 .1 .247 dev eth0 src 10.42 .1 .80

ネットワーク パケットがイーサネット インターフェイス eth0 に送信され、arp を使用してその MAC アドレス ae:36:76:3e:c3:03 が見つかることがわかります。

 kubectl exec curl -nデフォルト-- arp -n
? ( ​​10.42 .1 .247 ) ae : 36 : 76 : 3 e : c3 : 03 [ ether ] eth0

インターフェース eth0 の情報を表示します。

 kubectl exec curl -nデフォルト-- ip リンク show eth0
42 : eth0@if43 : <ブロードキャストマルチキャストアップロウアーアップ M -ダウン> mtu 1500 qdisc キューなし 状態 UP qlen 1000
リンク/イーサ f6 : 00 : 50 : f9 : 92 : a1 brd ff : ff : ff : ff : ff : ff

MAC アドレスが ae:36:76:3e:c3:03 ではないことがわかります。名前の @if43 から、その veth ペアのインデックスが 43 であることがわかります。次に、ノード NODE1 にログインして、インデックス インターフェイスの情報を照会します。

 IPリンク| grep -A1 ^ 43
43 : lxc48c4aa0637ce@if42 : < BROADCAST MULTICAST UP LOWER_UP > mtu 1500 qdisc noqueue 状態 UP モード DEFAULTグループデフォルト qlen 1000
リンク/イーサ ae : 36 : 76 : 3 e : c3 : 03 brd ff : ff : ff : ff : ff : ffリンク- netns cni - 407 cd7d8 - 7 c02 - cfa7 - bf93 - 22946 f923ffd

このインターフェース lxc48c4aa0637ce の MAC はまさに ae:36:76:3e:c3:03 であることがわかります。

過去の経験[6]によれば、この仮想イーサネットインターフェースlxc48c4aa0637ceは、ホストのルートネットワーク名前空間に配置された仮想イーサネットポートです。一方では、トンネルを介してコンテナのイーサネット インターフェイス eth0 に接続されており、いずれかの端に送信されたネットワーク パケットは、もう一方の端に直接到達します。一方、ホスト名前空間内のブリッジに接続されているはずですが、上記の結果にはブリッジの名前が見つかりません。

IPリンクから表示:

 1 : lo : < LOOPBACK  UP  LOWER_UP > mtu 65536 qdisc noqueue 状態UNKNOWNモード DEFAULTグループデフォルト qlen 1000
リンク/ループバック00 : 00 : 00 : 00 : 00 : 00 brd 00 : 00 : 00 : 00 : 00 : 00
2 : eth0 : < BROADCAST MULTICAST UP LOWER_UP > mtu 1500 qdisc fq_codel 状態 UP モード DEFAULTグループデフォルト qlen 1000
リンク/イーサ fa : cb : 49 : 4 a : 28 : 21 brd ff : ff : ff : ff : ff : ff
3 : cilium_net@cilium_host : < BROADCAST MULTICAST NOARP UP LOWER_UP > mtu 1500 qdisc noqueue 状態 UP モード DEFAULTグループデフォルト qlen 1000
リンク/イーサ36 : d5 : 5 a : 2 a : ce : 80 brd ff : ff : ff : ff : ff : ff
4 : cilium_host@cilium_net : < BROADCAST MULTICAST NOARP UP LOWER_UP > mtu 1500 qdisc noqueue 状態 UP モード DEFAULTグループデフォルト qlen 1000
リンク/イーサ12 : 82 : fb : 78 : 16 : 6 a brd ff : ff : ff : ff : ff : ff
5 : cilium_vxlan : < BROADCAST MULTICAST UP LOWER_UP > mtu 1500 qdisc noqueue 状態UNKNOWNモード DEFAULTグループデフォルト qlen 1000
リンク/イーサ fa : 42 : 4 d : 22 : b7 : d0 brd ff : ff : ff : ff : ff : ff
25 : lxc_health@if24 : < BROADCAST MULTICAST UP LOWER_UP > mtu 1500 qdisc noqueue 状態 UP モード DEFAULTグループデフォルト qlen 1000
リンク/イーサ3 e : 4 f : b3 : 56 : 67 : 2 b brd ff : ff : ff : ff : ff : ffリンク- netnsid 0
33 : lxc113dd6a50a7a@if32 : < BROADCAST MULTICAST UP LOWER_UP > mtu 1500 qdisc noqueue 状態 UP モード DEFAULTグループデフォルト qlen 1000
リンク/イーサ32 : 3 a : 5 b : 15 : 44 : ff brd ff : ff : ff : ff : ff : ff リンク- netns cni - 07 cffbd8 - 83 dd - dcc1 - 0 b57 - 5 c59c1c037e9
43 : lxc48c4aa0637ce@if42 : < BROADCAST MULTICAST UP LOWER_UP > mtu 1500 qdisc noqueue 状態 UP モード DEFAULTグループデフォルト qlen 1000
リンク/イーサ ae : 36 : 76 : 3 e : c3 : 03 brd ff : ff : ff : ff : ff : ffリンク- netns cni - 407 cd7d8 - 7 c02 - cfa7 - bf93 - 22946 f923ffd

複数のイーサネット インターフェイス (cilium_net、cilium_host、cilium_vxlan、cilium_health) と、コンテナー ネットワーク名前空間のイーサネット インターフェイスへのトンネル ピア lxcxxxx が表示されます。

繊毛交差節

ネットワーク パケットは lxcxxx に到達した後どのように進むべきでしょうか?次はeBPFが登場する番です。

cilium_net、cilium_host、cilium_health についてはこの記事では取り上げないので、次の図には示されていないことに注意してください。

ステップ2: Pod1 LXC BPF 入力

現在のノードの繊毛ポッド(先ほど設定した変数 $cilium1)に入り、bpftool コマンドを使用して、veth にアタッチされている BPF プログラムを確認します。

 kubectl exec - n kube -システム $cilium1 - c cilium -エージェント-- bpftool net show dev lxc48c4aa0637ce
翻訳:

tc :
lxc48c4aa0637ce ( 43 ) clsact / ingress bpf_lxc .o : [ from - container ] id 2901

フローディセクタ:

ノード $NODE1 にログインし、tc コマンドを使用してクエリを実行することもできます。記事の冒頭にあるデータパス セクションで、ここでイングレスを指定していることに注意してください。コンテナの eth0 とホスト ネットワーク名前空間の lxc がチャネルを形成するため、コンテナの出力トラフィックは lxc の入力トラフィックになります。同様に、コンテナの入力トラフィックは lxc の出力トラフィックです。

 #NODE1 の場合
tc フィルター show dev lxc48c4aa0637ce イングレス
フィルタ プロトコル すべての優先1 bpf チェーン0
フィルター プロトコル すべての pref 1 bpf チェーン0ハンドル0x1 bpf_lxc .o : [ from - container ] direct - action not_in_hw id 2901 tag d578585f7e71464b jited

詳細情報はプログラム ID 2901 からご覧いただけます。

 kubectl exec - n kube -システム $cilium1 - c cilium -エージェント-- bpftool prog show id 2901
2901 : sched_cls 名前 handle_xgress タグ d578585f7e71464b gpl
loaded_at 2023-01-09 T19 : 29 : 52 + 0000 uid 0
xlated 688 B jited 589 B memlock 4096 B map_ids 572 , 86
btf_id 301

ここで、BPF プログラム bpf_lxc.o のコンテナからの部分がロードされていることがわかります。 Ciliumソースコードbpf_lxc.c[7]の__section("from-container")セクションに移動すると、プロシージャ名はhandle_xgressです。

ハンドル_xgress #1
ethertype を検証する( ctx & proto )
テールハンドル_ipv4 #2
ハンドル_ipv4_from_lxc #3
lookup_ip4_remote_endpoint => ipcache_lookup4 #4
ポリシーアクセス可能 #5
TUNNEL_MODE #6の場合
encap_and_redirect_lxc
ctx_redirect ( ctx , ENCAP_IFINDEX , 0 )
ENABLE_ROUTINGの場合
ipv4_l3
CTX_ACT_OK を返します

(1):ネットワークパケットのヘッダー情報がhandle_xgressに送信され、L3プロトコルがチェックされます。

(2):すべてのIPv4ネットワークパケットはtail_handle_ipv4によって処理されます。

(3): コアロジックはhandle_ipv4_from_lxcにあります。 tail_handle_ipv4 が handle_ipv4_from_lxc にジャンプする方法。ここではテイルズコール[8]が使われます。 Tails 呼び出しを使用すると、BPF プログラムが完了し、特定の条件が満たされたときに、元のプログラムに戻らずに、別の指定されたプログラムが実行されるように構成できます。ここでは詳細には触れませんが、興味のある方は公式ドキュメント[9]を参照してください。

(4):次に、eBPFマップcilium_ipcacheからターゲットエンドポイントを照会し、トンネルエンドポイント192.168.1.13を見つけます。このアドレスはターゲットが配置されているノードの IP アドレスであり、タイプはです。

 kubectl exec - n kube - system $cilium1 - c cilium -エージェント-- cilium マップ get cilium_ipcache | grep 10.42.0.51
10.42 .0 .51 / 32アイデンティティ= 15773暗号化キー= 0トンネルエンドポイント= 192.168 .1 .13同期

(5): policy_can_access これはエクスポートポリシーを実行するためのチェックですが、この記事では取り上げておらず、詳しく説明しません。

(6):その後の処理には2つのモードがある。

  • ダイレクト ルーティング: カーネル ネットワーク スタックによって処理されるか、基盤となる SDN によってサポートされます。
  • トンネル: ネットワーク パケットは再度カプセル化され、vxlan などのトンネルを介して送信されます。

ここでもトンネルモードを使用します。ネットワーク パケットは、トンネル エンドポイントをトンネル ピアとして使用して、処理のために encap_and_redirect_lxc に渡されます。最後に、イーサネット インターフェイス cilium_vxlan である ENCAP_IFINDEX (この値は、cilium-agent の起動時に取得されるインターフェイスのインデックス値) に転送されます。

ステップ3: ノード1 vxlan BPF 出力

まず、このインターフェース上の BPF プログラムを見てみましょう。

 kubectl exec -n kube -システム $cilium1 -c cilium -エージェント--bpftool net show dev cilium_vxlan
翻訳:

tc :
cilium_vxlan ( 5 ) clsact / ingress bpf_overlay .o : [ from - overlay ] id 2699
cilium_vxlan ( 5 ) clsact / egress bpf_overlay .o : [ to - overlay ] id 2707

フローディセクタ:

コンテナの出力トラフィックは cilium_vxlan の出力でもあるため、ここでの手順は to-overlay です。

プログラムは`bpf_overlay.c`[10]にあります。このプログラムの処理は非常に簡単です。 IPv6 プロトコルの場合、パケットは IPv6 アドレスを使用して一度カプセル化されます。こちらは IPv4 で、直接 CTX_ACT_OK を返します。ネットワーク パケットはカーネル ネットワーク スタックに渡され、eth0 インターフェイスに入ります。

ステップ4: NODE1 NIC BPF 出力

まずBPFプログラムを見てみましょう。

 kubectl exec -n kube -システム $cilium1 -c cilium -エージェント--bpftool net show dev eth0
翻訳:

tc :
eth0 ( 2 ) clsact /イングレス bpf_netdev_eth0 .o : [ from - netdev ] id 2823
eth0 ( 2 ) clsact /出力 bpf_netdev_eth0 .o : [ to - netdev ] id 2832

フローディセクタ:

出力プログラムto-netdevは`bpf_host.c`[11]にあります。実際には、重要な処理は行われません。 CTX_ACT_OK を返してカーネル ネットワーク スタックに渡してさらに処理します。つまり、ネットワーク パケットを vxlan トンネルのもう一方の端、つまりノード 192.168.1.13 に送信します。中間データの送信では、実際には、ホストの eth0 インターフェイスから基盤ネットワークを経由してターゲット ホストの eth0 インターフェイスまで、基盤ネットワークが使用されます。

ステップ5: NODE2 NIC BPFイングレス

vxlan ネットワーク パケットがノードの eth0 インターフェイスに到着すると、BPF プログラムもトリガーされます。

 kubectl exec -n kube -システム $cilium2 -c cilium -エージェント--bpftool net show dev eth0
翻訳:

tc :
eth0 ( 2 ) clsact /イングレス bpf_netdev_eth0 .o : [ from - netdev ] id 4556
eth0 ( 2 ) clsact /出力 bpf_netdev_eth0 .o : [ to - netdev ] id 4565

フローディセクタ:

今回のトリガーはbpf_host.c[12]にあるfrom-netdevです。

から
VLANの場合
許可VLAN
CTX_ACT_OKを返す

vxlan トンネル モードの場合、ここでのロジックは非常に単純です。ネットワーク パケットが vxlan であり、vlan が許可されていると判断された場合、直接 CTX_ACT_OK を返し、カーネル ネットワーク スタックに処理を渡します。

ステップ6: NODE2 vxlan BPF イングレス

ネットワーク パケットはカーネル ネットワーク スタックを通過し、インターフェイス cilium_vxlan に到達します。

 kubectl exec - n kube -システム $cilium2 - c cilium -エージェント-- bpftool net show dev cilium_vxlan
翻訳:

tc :
cilium_vxlan ( 5 ) clsact / ingress bpf_overlay .o : [ from - overlay ] id 4468
cilium_vxlan ( 5 ) clsact / egress bpf_overlay .o : [ to - overlay ] id 4476

フローディセクタ:

このプログラムは`bpf_overlay.c`[13]にあります。

オーバーレイから
検証_イーサタイプ
テールハンドル_ipv4
ハンドル_ipv4
ルックアップ_ip4_エンドポイント1 #
マップ検索要素
ipv4_local_delivery 2 #
テールコールダイナミック3 #

(1): lookup_ip4_endpointは、ターゲットアドレスがeBPFマップcilium_lxc内の現在のノードにあるかどうかを確認します(このマップは現在のノード内のエンドポイントのみを格納します)。

 kubectl exec - n kube - system $cilium2 - c cilium -エージェント-- cilium マップ get cilium_lxc | grep 10.42.0.51
10.42 .0 .51 : 0 id = 2826 flags = 0x0000 ifindex = 29 mac = 96 : 86 : 44 : A6 : 37 : EC nodemac = D2 : AD : 65 : 4 D : D0 : 7 B 同期

ここで、ターゲット エンドポイント情報 (ID、イーサネット ポート インデックス、MAC アドレス) を見つけることができます。 NODE2 ノードでインターフェース情報を確認し、このネットワーク ポートが仮想イーサネット デバイス lxc65015af813d1 であることを確認します。これは、ポッド httpbin インターフェース eth0 のちょうど反対側の端です。

 IPリンク| grep - B1 - i d2 : ad
29 : lxc65015af813d1@if28 : < BROADCAST MULTICAST UP LOWER_UP > mtu 1500 qdisc noqueue 状態 UP モード DEFAULTグループデフォルト qlen 1000
リンク/イーサ d2 : ad : 65 : 4 d : d0 : 7 b brd ff : ff : ff : ff : ff : ff リンク- netns cni - 395674 eb - 172 b - 2234 - a9ad - 1 db78b2a5beb

kubectl exec - n デフォルト httpbin -- ip リンク
1 : lo : < LOOPBACK UP LOWER_UP > mtu 65536 qdisc noqueue 状態UNKNOWNモード DEFAULTグループデフォルト qlen 1000
リンク/ループバック00 : 00 : 00 : 00 : 00 : 00 brd 00 : 00 : 00 : 00 : 00 : 00
28 : eth0@if29 : < BROADCAST MULTICAST UP LOWER_UP > mtu 1500 qdisc noqueue 状態 UP モード DEFAULTグループデフォルト qlen 1000
リンク/イーサ96 : 86 : 44 : a6 : 37 : ec brd ff : ff : ff : ff : ff : ffリンク- netnsid

(2)ipv4_local_deliveryのロジックは`l3.h`[14]にあり、エンドポイントのLXC ID(29)にあるBPFプログラムを末尾呼び出しします。

ステップ7: Pod2 LXC BPF出力

次のコマンドを実行しても、期待される出力 to-container (および from-container) が見つかりません。

 kubectl exec -n kube -system $cilium2 -c cilium -agent --bpftool net show |グレップ 29
lxc65015af813d1 ( 29 ) clsact / ingress bpf_lxc .o : [ from - container ] id 4670

以前使用されていた BPF プログラムはすべてインターフェースに接続されていましたが、ここでは vxlan 接続プログラムが直接末尾呼び出されます。 to-containerは`bpf-lxc.c`[15]にあります。

コンテナへのハンドル
テール_ipv4_to_endpoint
ipv4_ポリシー #1
ポリシーがイングレスにアクセスできる
リダイレクト
ctx_リダイレクト

(1)ipv4_policyは設定されたポリシーを実行する

(2):ポリシーが通過すると、redirect_epが呼び出され、ネットワークパケットが仮想イーサネットインターフェースlxc65015af813d1に送信されます。 veth に入ると、それに接続されているコンテナの eth0 インターフェースに直接到達します。

ステップ8: ポッド2に到達する

ネットワーク パケットが pod2 に到着します。完成写真を添付し​​ます。

繊毛パケットフロー

要約する

私の個人的な意見を述べさせてください。この記事で紹介したコンテンツは、Cilium の氷山の一角にすぎません。カーネルの知識と C 言語の知識が不足しているため、勉強するのは非常に困難です。 Cilium には、まだ詳細に研究されていないコンテンツが多数あります。 Cilium は本当に複雑だと言わざるを得ません。私の知る限り、Cilium はエンドポイント、ノード、ポリシー、ルート、接続ステータス、その他多くのデータなど、BPF マップ内に独自のデータセットを保持しており、これらはすべてカーネルに保存されています。さらに、BPF プログラムの開発および保守コストは、機能の複雑さに応じて増大します。 BPF プログラムを使用して L7 機能を開発することがどれほど複雑になるかは想像しにくいです。おそらくこれが、L7 シナリオを処理するためにプロキシを使用する理由です。

最後に、Cilium を学習した私の経験を共有したいと思います。

最初のステップは、BPF プログラムを読むことです。プロジェクト内の bpf コードは静的コードであり、構成関連の if else ステートメントが多数含まれています。実行時に構成に従ってコンパイルされます。この場合、Cilium pod に入ることができます。 /run/cilium/state/templates ディレクトリには、アプリケーション構成後のソース ファイルがあり、コードの量が大幅に少なくなります。 /run/cilium/state/globals/node_config には現在使用されている構成があり、これらの構成と組み合わせてコードを読み取ることができます。

脚注

  • [^1]: Cilium はコンテナに IP アドレスを割り当てることで、コンテナをネットワーク上で利用できるようにします。 Kubernetes Pod が複数のコンテナを持つことができ、それらのコンテナがネットワーク名前空間を共有し、同じ IP アドレスを使用するのと同様に、複数のコンテナが同じ IP アドレスを共有できます。 Cilium は、同じアドレスを共有するこれらのコンテナーをエンドポイントに結合します。
  • [^2]: eBPF マップはデータの保存に使用できます。 Cilium では、cilium-agent が api-server を監視し、情報をマップに書き込みます。たとえば、cilium_lb4_services_v2 はすべての Kubernetes サービスの情報を保持します。

参考文献

[1] 「Cilium で Kubernetes ネットワークセキュリティを強化する」: https://atbug.com/enhance-kubernetes-network-security-with-cilium/

[2] 繊毛: https://cilium.io

[3] eBPF: https://ebpf.io

[4] CiliumリファレンスドキュメントeBPFデータパス: https://docs.cilium.io/en/stable/concepts/ebpf/intro/

[5] k8e: https://getk8e.com

[6] 過去の経験: https://atbug.com/deep-dive-k8s-network-mode-and-communication/

[7] bpf_lxc.c: https://github.com/cilium/cilium/blob/1c466d26ff0edfb5021d024f755d4d00bc744792/bpf/bpf_lxc.c#L1320

[8] テイルズコール: https://docs.cilium.io/en/stable/bpf/#tail-calls

[9] 公式ドキュメント: https://docs.cilium.io/en/stable/bpf/#tail-calls

[10] bpf_overlay.c: https://github.com/cilium/cilium/blob/1c466d26ff0edfb5021d024f755d4d00bc744792/bpf/bpf_overlay.c#L528

[11] bpf_host.c: https://github.com/cilium/cilium/blob/1c466d26ff0edfb5021d024f755d4d00bc744792/bpf/bpf_host.c#L1081

[12] bpf_host.c: https://github.com/cilium/cilium/blob/1c466d26ff0edfb5021d024f755d4d00bc744792/bpf/bpf_host.c#L1040

[13] bpf_overlay.c: https://github.com/cilium/cilium/blob/1c466d26ff0edfb5021d024f755d4d00bc744792/bpf/bpf_overlay.c#L430

[14] l3.h: https://github.com/cilium/cilium/blob/1c466d26ff0edfb5021d024f755d4d00bc744792/bpf/lib/l3.h#L114

[15] bpf-lxc.c: https://github.com/cilium/cilium/blob/1c466d26ff0edfb5021d024f755d4d00bc744792/bpf/bpf_lxc.c#L2131

<<:  プライベートクラウドの構築には、ALLINONE と階層独立構築・最適化のどちらを使うべきでしょうか?

>>:  異なる Kubernetes バージョンでの ServiceAccount トークンの使用

推薦する

道教の思想を参考に

長い歴史を持つ偉大な国として、中国文化は非常に広大かつ奥深いため、毎年多くの外国人学者が中国を訪れ、...

1 つの記事で Yandex SEO を理解する: ロシアの対外貿易はここから始まります

画像出典: Tuchong Creative Yandex はロシアで最も広く使用されている検索エン...

#12.12# cloudcone、ロサンゼルスの高トラフィック VPS、年間 14 ドル、KVM/1G メモリ/1 コア/20g SSD/5T トラフィック/1Gbps 帯域幅

CloudconeはDouble 12の特別プロモーションを開始しました。3つの安価なVPSは5Tト...

ライブストリーミングeコマースは「1ムーあたり1万キロ」の時代に突入したのか?

「国民が大胆になればなるほど、土地の生産性は高まる」。この言葉は、インターネット時代の電子商取引ライ...

3月にドメイン名販売業者から提供されたプロモーション オファーの一覧

長い間、ドメイン名には注目していませんでした。一般的なドメイン名販売業者のプロモーション情報をお送り...

WebSound - $34/年/kvm/256m メモリ/10gSSD/2T トラフィック/ロサンゼルス

WebSound.co.uk という会社は英国に登録されています。本当に英国人によって開設されたかど...

インターネットプロモーションはインターネットだけに頼ることはできません。オンラインとオフラインを組み合わせてみてはいかがでしょうか。

SEO 担当者として、このタイトルを見て、ナンセンスだと思いますか? ネットワーク プロモーションは...

クラウドコンピューティングの3大巨人が互いに競争しています。あなたの「運命の人」は誰ですか?

最も影響力のある 3 つのクラウド コンピューティング ベンダーについて話すとき、人々は間違いなく ...

IBMは、数百億のパラメータを持つモデルを柔軟に展開およびトレーニングするためのクラウドネイティブAIスーパーコンピューターVelaを開発しました。

ChatGPTはインターネット上で人気を博しており、その背後にあるAIモデルのトレーニングも広く注目...

「ICT+AR」で遠隔操作も可能に

[51CTO.com からのオリジナル記事] 今年、この流行病は世界に多大な影響をもたらし、人々の生...

なぜ Baidu は 20 日以上経ってもウェブサイトの 3 ページしかインデックスしなかったのでしょうか?

多くの初心者は、検索エンジンに含まれない問題に悩まされています。誰もが初心者の頃にこの状況を経験した...

トラフィックが制限された大きな帯域幅と、トラフィックが無制限の小さな帯域幅のどちらが適していますか?

新年を迎えた今、マシンを購入する際に、トラフィック制限のある大きな帯域幅を選択するか、トラフィック制...

ウェブサイトはスパイダートラップを避けるように注意する必要がある

自分のウェブサイトをデザインするときは、ウェブサイトがスパイダー トラップに陥らないように、いくつか...

1日の広告売上は1000万を突破。ミニゲームはどうやって収益化を実現しているのか?

WeChatのミニゲームには現在独自のシステムがあり、商業広告は無視できない重要な要素となっています...

国家著作権局: 360 総合検索は百度コンテンツをクロールするために許可を得る必要がある

百度と奇虎360の間の検索紛争を受けて、国家著作権局は最近、360 Searchが百度のコンテンツを...