Skip to content
Published on

MultusとセカンダリネットワークはKubeVirtでどう接続されるか

Authors

はじめに

プライマリ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

このファイルのGenerateCNIAnnotationGenerateCNIAnnotationFromNameSchemeが核心である。役割は非常に明確である。

  • セカンダリMultusネットワークを見つける
  • Podインターフェース名を計算する
  • NetworkSelectionElementリストを作成する
  • これをJSONアノテーション文字列にシリアライズする

つまりcontrollerは単に「NAD名がある」で終わらず、Pod内でどの名前のインターフェースとしてアタッチすべきかまで計算する。

インターフェース名の計算がなぜ重要か

KubeVirtは論理ネットワーク名とPodインターフェース名を同一には使わない。nameschemeレイヤーを通じてハッシュ名を作る。この方式の目的は:

  • インターフェース名の長さ制限への対応
  • 予測可能なネーミング
  • セカンダリネットワークが増えても衝突を最小化

network-binding-plugin.mdもセカンダリネットワーク側でpod-hashtap-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がどのようなコントロールプレーン過程を経て準備されるかを見ていく。