はじめに
プライマリPodネットワークだけでは不十分な場合が多い。データプレーン、ストレージプレーン、管理網、NFV用途のようにVMに複数のNICが必要になることがある。KubeVirtはこの問題を独自のマルチネットワークシステムで解決せず、**MultusとNetworkAttachmentDefinitionエコシステムを再利用**している。
本記事ではセカンダリネットワークがVMI specからPodアノテーション、Podインターフェース、VMI statusに至る経路を整理する。
基本的なアイデア
プライマリネットワークは通常Podデフォルトのdefault CNIが提供する。セカンダリネットワークはMultusが追加でアタッチする。KubeVirtはVMI specを読み、必要なMultusアノテーションを生成してlauncher Podに載せる。
つまり流れは次の通り。
1. ユーザーがVMI specにセカンダリネットワークを記述する。
2. KubeVirtがPodアノテーションを生成する。
3. Multusがアノテーションを読み、該当NADに従って追加インターフェースをアタッチする。
4. 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がどのようなコントロールプレーン過程を経て準備されるかを見ていく。
현재 단락 (1/62)
プライマリPodネットワークだけでは不十分な場合が多い。データプレーン、ストレージプレーン、管理網、NFV用途のようにVMに複数のNICが必要になることがある。KubeVirtはこの問題を独自のマルチ...