- Authors

- Name
- Youngju Kim
- @fjvbn20031
- はじめに
- 基本的なアイデア
- 核心コード:pkg/network/multus/annotation.go
- インターフェース名の計算がなぜ重要か
- アノテーションには何が入るか
- Podがセカンダリネットワークを受け取った後に何が起こるか
- InfoSourceがなぜ重要か
- セカンダリネットワークの変更がマイグレーションを引き起こすこともある
- Multusとバインディングプラグインの関係
- 実務でよく起きる問題
- よくある誤解
- まとめ
はじめに
プライマリPodネットワークだけでは不十分な場合が多い。データプレーン、ストレージプレーン、管理網、NFV用途のようにVMに複数のNICが必要になることがある。KubeVirtはこの問題を独自のマルチネットワークシステムで解決せず、MultusとNetworkAttachmentDefinitionエコシステムを再利用している。
本記事ではセカンダリネットワークがVMI specからPodアノテーション、Podインターフェース、VMI statusに至る経路を整理する。
基本的なアイデア
プライマリネットワークは通常Podデフォルトのdefault CNIが提供する。セカンダリネットワークはMultusが追加でアタッチする。KubeVirtはVMI specを読み、必要なMultusアノテーションを生成してlauncher Podに載せる。
つまり流れは次の通り。
- ユーザーがVMI specにセカンダリネットワークを記述する。
- KubeVirtがPodアノテーションを生成する。
- Multusがアノテーションを読み、該当NADに従って追加インターフェースをアタッチする。
- KubeVirtがPodネットワークstatusを読んでVMI statusを更新する。
この構造のおかげでKubeVirtはマルチネットワーク機能をコアで作り直す必要がない。
核心コード:pkg/network/multus/annotation.go
このファイルのGenerateCNIAnnotationとGenerateCNIAnnotationFromNameSchemeが核心である。役割は非常に明確である。
- セカンダリMultusネットワークを見つける
- Podインターフェース名を計算する
NetworkSelectionElementリストを作成する- これをJSONアノテーション文字列にシリアライズする
つまりcontrollerは単に「NAD名がある」で終わらず、Pod内でどの名前のインターフェースとしてアタッチすべきかまで計算する。
インターフェース名の計算がなぜ重要か
KubeVirtは論理ネットワーク名とPodインターフェース名を同一には使わない。nameschemeレイヤーを通じてハッシュ名を作る。この方式の目的は:
- インターフェース名の長さ制限への対応
- 予測可能なネーミング
- セカンダリネットワークが増えても衝突を最小化
network-binding-plugin.mdもセカンダリネットワーク側でpod-hashやtap-hashのような名前規則を説明している。
つまり名前規則は単なる見た目の問題ではなく、launcher PodとCNIプラグイン、libvirtドメインが互いに同じインターフェースを指すようにする契約である。
アノテーションには何が入るか
Multus用のNetworkSelectionElementには通常以下の情報が入る。
- namespace
- NAD名
- インターフェースリクエスト
- 必要に応じてMACリクエスト
バインディングプラグインが付く場合はCNIArgsも入りうる。annotation.goはプラグインバインディングの場合に論理ネットワーク名をCNI argとして入れる。
これはプラグインバインディングとセカンダリネットワークモデルが単純な並列関係ではなく、アノテーション段階で互いに結合しうることを意味する。
Podがセカンダリネットワークを受け取った後に何が起こるか
KubeVirtはPodアノテーションを書いて終わりではない。Podが実際にセカンダリネットワークを受け取った後、その結果をVMI statusに反映する必要がある。
この役割を担うコードがpkg/network/controllers/vmi.goである。
ここでは:
- PodのMultusネットワークstatusアノテーションを読み
- プライマリインターフェースstatusを計算し
- セカンダリインターフェースstatusを計算し
- VMI statusの
Interfacesに反映する
つまりVMI statusは「ゲストがネットワークをどう見るべきか」だけでなく、「Podが実際にどのセカンダリインターフェースを受け取ったか」も含む。
InfoSourceがなぜ重要か
vmi.goを見るとインターフェースstatusにInfoSource概念がある。これは情報がどこから来たかを区別するための仕組みである。
- PodのMultusネットワークstatusから来たか
- libvirtドメインから来たか
- ゲストエージェントから来たか
この区別は非常に重要である。例えばインターフェースがPod側にはあるがドメインにはまだ反映されていなければ、ネットワークhotplugが進行中か未完了の可能性がある。
つまりInfoSourceは単なるメタデータではなくreconciliation判断材料である。
セカンダリネットワークの変更がマイグレーションを引き起こすこともある
pkg/network/migration/evaluator.goは興味深い事実を見せる。セカンダリインターフェースのhotplugやunplug、NAD参照の変更は場合によってVMIをmigration-required状態にすることがある。
なぜこれが重要か?
ネットワーク構成が変わると、現在のlauncher Pod上で安全に反映しにくい場合がある。このときKubeVirtは:
- 即時マイグレーション必要
- 一時pending後マイグレーション必要
といった判断を下し、新しいtarget Podでネットワーク構成を整理して反映しようとする。
つまりセカンダリネットワークは単なるCNIアタッチの問題ではなく、VM再配置戦略とも接続される動的状態である。
Multusとバインディングプラグインの関係
多くの人がMultusとバインディングプラグインを別物と考えるが、実際にはかなり頻繁に一緒に登場する。
- Multusはセカンダリネットワークアタッチメカニズム
- バインディングプラグインはゲストワイヤリング方法
一方はPodにネットワークエンドポイントを持ち込む役割で、もう一方はそのエンドポイントをゲストNICとどう結びつけるかを定める役割である。
この二つが合わさって「セカンダリネットワークがゲストでどのデバイスとして見えるか」が完成する。
実務でよく起きる問題
1. NADは正しいがインターフェースstatusが空
Podアノテーションは作成されたがMultusアタッチ結果が期待通り入っていない可能性がある。
2. Podにはインターフェースがあるがゲストでは見えない
Pod段階とドメイン段階がずれている。InfoSourceを確認すべきである。
3. hotplug後にmigration requiredが付く
動的ネットワーク更新が現在のPodで安全に完了できず再配置が必要だという意味かもしれない。
よくある誤解
誤解1:セカンダリネットワークはPodにアタッチされればゲストでも自動
いいえ。Podアタッチとゲストワイヤリングは異なる段階である。
誤解2:Multusがゲストネットワークまですべて責任を持つ
いいえ。MultusはPodにネットワークをアタッチし、ゲストワイヤリングはKubeVirtバインディングとドメイン設定が責任を持つ。
誤解3:インターフェースstatusは見栄えの良い出力用
いいえ。ソース別状態を合わせてreconcile判断に使われる重要なデータである。
まとめ
KubeVirtにおいてセカンダリネットワークはMultusとNADを通じてPodに入り、KubeVirtがその結果をアノテーション、ネーミングスキーム、インターフェースstatus、ゲストワイヤリングへとつないで完成させる。つまりMultusはエンドポイントプロビジョニング、KubeVirtはゲスト統合を担う分業構造である。この構造を理解すれば、複数NICを持つVMの問題をはるかに体系的にデバッグできる。
次の記事では、ネットワークからマイグレーションへ移り、migration CRが作成された後にtarget Podがどのようなコントロールプレーン過程を経て準備されるかを見ていく。