Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

How is Cilium Tested?

How is Cilium Tested?

Yutaro Hayakawa

December 07, 2024
Tweet

More Decks by Yutaro Hayakawa

Other Decks in Technology

Transcript

  1. Ciliumのアーキテクチャおさらい 3 Node (Linux) Agent Node (Linux) Agent External Network

    Node (Linux) Agent Data Path (Linux/eBPF) Data Path (Linux/eBPF) Data Path (Linux/eBPF) Operator
  2. Ciliumのアーキテクチャおさらい 4 Node (Linux) Agent Node (Linux) Agent External Network

    Node (Linux) Agent Data Path (Linux/eBPF) Data Path (Linux/eBPF) Data Path (Linux/eBPF) Operator Cilium Agent 各ノードに常駐. Node-Localな処理 を担うコンポーネント. Data Path (Linux/eBPF) の設定, BGP, DNS Interception, L7 Proxy等.
  3. Ciliumのアーキテクチャおさらい 5 Node (Linux) Agent Node (Linux) Agent External Network

    Node (Linux) Agent Data Path (Linux/eBPF) Data Path (Linux/eBPF) Data Path (Linux/eBPF) Operator Data Path eBPFだけでやっていると思われがち だが実際にはLinuxのNetwork Stack (IP routing, iptables, etc) も組み合わせて機能を作り込ん でいる.
  4. Ciliumのアーキテクチャおさらい 6 Node (Linux) Agent Node (Linux) Agent External Network

    Node (Linux) Agent Data Path (Linux/eBPF) Data Path (Linux/eBPF) Data Path (Linux/eBPF) Operator Cilium Operator Clusterで1つ (HAできるがリーダ選出で1つに見 える). Cluster-Wideな処理を担う (IPAM, Cluster-wideなリソースの生成等)
  5. Unit Test • 数秒 - 1,2分以内に終わるくらいの小規模なテスト ◦ フィードバックループの速さが大事 • Goのパッケージごとのテスト

    ◦ 普通のGoの単体テスト ◦ eBPFのユーザスペースコードやNetlinkを叩くコードのテストはどうする? ▪ Privileged Testと呼ばれていて特権がなければスキップされる ◦ Kubernetes Controllerのテストはどうする? ▪ クラスタを立てて本物のAPIサーバを使ってテストするのはなるべく避けたい • eBPFのテスト ◦ どうやってeBPFを単体テストする? ◦ Ciliumを丸ごと立ち上げてパケットを通すテストは避けたい ▪ セットアップが難しく, 実行に時間がかかるため 8
  6. BPF_PROG_TEST_RUN • bpf(2)の機能でLoadしたeBPFのプログラム をAttachせずに実行できる (ref) ◦ まさにeBPFの単体テストのために作られた機能 • そのままでも使えるが, ちょっとテスト走らせるま

    での手続きが面倒くさい ◦ Goでパケット作ったりパースしたり ◦ eBPFプログラムをロードしたり ◦ もう少しテストを書くのに専念したい 9 eBPF Program Test Runner In Pkt Out Pkt bpf(BPF_PROG_TEST_RUN) User Kernel
  7. eBPF Unit Test Framework • eBPFの単体テストを書くための自作フレームワーク (ref) • PKGENのコードの中でパケット (skb)

    を作る • SETUPで実際のコードにskbを通す • CHECKで出力が意図通りか確認する ◦ ちゃんとNATされたか, 返り値 (PASS, DROP, REDIRECT) が意図通りか等 • eBPFのコードのみでテストを書き切ることができる 10 PKTGEN Program Test Runner Empty InPkt SETUP Program InPkt OutPkt CHECK Program OutPkt Result bpf(BPF_PROG_TEST_RUN)
  8. Kubernetes Controllerのテストどうする? • 実際のクラスタにデプロイするところまではやりたくない ◦ Unit Testはフィードバックループの速さが大事 ◦ Kindを使ってもデプロイには2-3分かかる ◦

    依存するコンポーネントだけを動かしてテストを書きたい ◦ Kubernetes APIは本物を使わない. でもClientのコードはそのまま使いたい. 12
  9. Hive/Cell Dependency Injection Framework • DIフレームワーク (cilium/hive) ◦ Go向けのいわゆるConstructor Injection

    ◦ Hive == DIコンテナ, Cell == Constructor (蜂の巣のイメージ) ◦ Cilium AgentやOperatorはHiveを中心にしたモジュラーモノリス構造 • モジュール間の依存解決や初期化をDI任せにできる ◦ Ciliumの機能の必要なSubsetだけを集めて動かすことができる ◦ FakeClient (本物のClientと同じIfaceを実装している) もDIで本物とすげかえられる ◦ 本物のAPIサーバがなくてもControllerのテストができる • Demo 13
  10. E2E Test • k8sクラスタも含めた実環境に近い環境でのテスト ◦ 実行に30分くらいかかる大きなテスト ◦ ユーザが実際にCiliumを使う時と同じようなシナリオ ◦ 本物のKubernetes環境を作って実際にトラフィックも作ってテストしたい

    ◦ DPlaneのテストは実際にカーネルに設定を入れてパケットを通してテストしたい ◦ k8sのRBACやCRDのバリデーションのルールなどを本物を使ってテストしたい ◦ 三大クラウドのAPIに依存した機能は本物のクラウドでなければテストできない • (余談) Kubernetesの標準APIを正しく実装しているかどうかもテストされる ◦ NetworkPolicy, Service, Ingress, GatewayAPI等 ◦ Conformance Testなどと呼ばれている 14
  11. Connectivity Test • Ciliumが動いているクラスタでCiliumの機能 を一通り動かして疎通確認するテストを走らせら れる ◦ 新しい機能を作ったらここにシナリオを増やす ◦ どんなk8sクラスタでも動かせる

    ◦ ユーザがプロダクションで動かしてもOK • CiliumのE2Eテストの基本的な構成はGHAで 環境構築をしてConnectivity Testを走らせ るという流れ • Demo 15
  12. LinuxカーネルバージョンごとのE2Eテスト • E2Eテストでは複数のLinuxカーネルでテストをしている ◦ CiliumはRHELカーネルとアップストリームのLTSカーネルで動作確認をしている ◦ 基本的にLinuxは互換性を壊さないのになぜテストするのか? ▪ 新しいカーネルのバージョンにしかない機能を使うことがある ▪

    Verifierへの変更等によってLoadできていたプログラムができなくなることがたまにある ▪ Network Stackのバグを引くこともたまにある ◦ カーネルがリリースされる前に問題を発見するためにbpf-nextツリーのカーネルもテストしている • どうやって複数バージョンのカーネルをテストする? 16
  13. Little VM Helper (LVH) • CIに使うためだけの最小構成のVMを動かすQEMUラッパー (ref) ◦ OCIフォーマットのイメージに入ったQCoWイメージを動かせる ◦

    コンテナレジストリにVMイメージをPushして配布できる ◦ Dockerのような使用感でVMが動く • カーネルを自動ビルドしてレジストリにPushするパイプラインが常に動いている (ref) • Demo 17
  14. E2Eテストの課題: テストケースの組み合わせ爆発 • Ciliumは多機能な上にサポートしている動作環境が多い ◦ 機能の組み合わせ * 動作環境 • クラウド環境

    ◦ GCP, AWS, Azure, etc… • Linuxカーネルのバージョン ◦ ディストリビューション固有カーネル (RHELカーネルなど), LTSカーネル数バージョン • Kubernetesのバージョン ◦ アップストリームのバージョン3つ ◦ クラウドの固有環境 (GKE, EKS, AKS, etc...) • Cilium自身のバージョン ◦ Upgrade/Downgradeテスト • 最新のUpgrade/DowngradeテストはMatrixの数が25 ◦ もちろん並列実行されるが1 Matrix当たり平均25分前後かかる • 時間的にも経済的にも (CloudやGHAの使用料) コストが高い 18
  15. E2Eテストの課題: Flakyなテスト • テストがFlakyになりがち ◦ E2Eテストは様々な要因で失敗する ▪ CI環境の問題 ▪ 確率的に発現するバグ

    ▪ テストコードそのものの不備 ◦ 動いているものが多いので失敗の原因を突き止めるのが非常に難しい ▪ Ciliumは非常にたくさんのgoroutine (手元では381あった) が並行・並列に動く ▪ 動きは全く決定的ではないのでRace Conditionなどは起きやすいし見逃しやすい 19
  16. Flakyなテストの弊害 • PRを出した時は `Required` とタグされたテストは全て通さなくてはマージできない • Flakyなテストがあるとそのテストの失敗が自分の変更が原因でなのかそうでないのかわからない ◦ 他の開発者が作ってしまったFlakeを自分がたまたま引いているだけかも ◦

    逆も然りで, 自分がFlakeを作ってもたまたまテストが成功してマージしてしまうかもしれない • 現状PRでテストを走らせるとほぼ毎回何かのテストが失敗する ◦ テストの失敗はリトライする前にGitHubのIssueで報告することになっている (ref) ◦ リトライにも30分以上かかるのでCIを通すのがPRの時間の中で支配的になることも ◦ テストを信頼できないと皆がテストの失敗に無頓着になってしまうので本物のエラーが発見しづらくなる 20
  17. Flakyテストに対する取り組み • CI Health Manager ◦ Flakyなテストを直すローテーションワーク (ref) ◦ テスト実行の統計情報を見て失敗率の高いテストを直す

    ◦ 現状はIsovalentの人がやっている ▪ (コミュニティの中でやる人がいてもいいなと個人的には思う) • E2Eテストの削減 ◦ 一般的な話としてE2Eテストは減らした方がいい ◦ E2Eテストが充実しているのは安心感があるが, 時間がかかり, Flakyになりやすく金銭的なコ ストも高い ◦ なるべくUnit TestやIntegration Testでカバーできるケースを増やす 21