Skip to content
Published on

VM、VMI、Migration CRDはそれぞれ何を表現するのか

Authors

はじめに

KubeVirtの構造を辿ると最初に出会うタイプがVirtualMachineVirtualMachineInstanceVirtualMachineInstanceMigrationだ。名前が似ているため最初は混乱するが、この3つのオブジェクトを区別できなければ、その後のcontroller、migration、状態追跡ロジックもすべてぼやけてしまう。

この記事はstaging/src/kubevirt.io/api/core/v1/types.goschema.goを中心に、各オブジェクトが意図実行中インスタンス一回限りの移動リクエストのどれを表すのか整理する。

なぜオブジェクトを3つに分けるのか

Kubernetesの基本パターンを思い出せば理解しやすい。

  • Deploymentは「望ましい状態」を表現する。
  • Podは「現在実行中のインスタンス」を表現する。
  • Jobは「一度実行する作業」を表現する。

KubeVirtも同様の分離を採用する。

  • VirtualMachine:長期的なVM意図と運用ポリシー
  • VirtualMachineInstance:今生きているゲストインスタンス
  • VirtualMachineInstanceMigration:特定のVMIを別のノードに移すための作業オブジェクト

この分離があるからこそ、start、stop、restart、migration、eviction、ステータス反映が互いに絡まない。

VirtualMachineは「持続的な意図」だ

VirtualMachineは「このVMをどのような形で維持したいか」を表現する上位オブジェクトだ。ユーザーは通常ここにtemplate、run strategy、data volume接続ポリシーを宣言する。

核心ポイントはVirtualMachineがゲストプロセスそのものを意味するわけではないという点だ。実際の実行主体はVirtualMachineInstanceだ。

VirtualMachineが有用な場面

  • VMをオフにしてオンにしても同じ意図を維持したい場合
  • 運用ポリシーを状態と分離したい場合
  • startまたはstopリクエストを宣言的に管理したい場合

つまりVirtualMachineは「このVMは存在すべきか」を扱い、VirtualMachineInstanceは「今現在どこでどのように実行中か」を扱う。

VirtualMachineInstanceは実行中ゲストの実体だ

VirtualMachineInstance、略してVMIはKubeVirtの核心ランタイムオブジェクトだ。types.goでこのオブジェクトはspecとstatusを併せ持つruntime definitionとして説明される。

実際にcontrollerとnode agentが最も頻繁に観察するオブジェクトもVMIだ。理由は簡単だ。Pod作成、ノード割り当て、ネットワークステータス、migration状態、guest agent情報などの実行中状態の中心がVMIだからだ。

VMI specの重要なフィールド

  • domain:CPU、メモリ、ディスク、NICなどのゲストハードウェア要件
  • nodeSelectoraffinitytolerations:どのノードに行けるか
  • volumes:どのストレージをゲストに接続するか
  • networks:どのネットワークをゲストNICに接続するか
  • terminationGracePeriodSeconds:終了シグナルと強制終了の間の猶予時間

つまりVMI specは「このゲストを今実行するためにランタイムは何を準備すべきか」を示す。

VMI statusはなぜこんなに多いのか

VirtualMachineInstanceStatusは思ったより豊富だ。これが重要な理由は、KubeVirtが単一のモノリシックデーモンではなく、複数のcontrollerとnodeコンポーネントがコレオグラフィ方式で協力するからだ。各コンポーネントはstatusを見て次の行動を決定する。

代表的に重要なフィールドは以下の通り。

  • NodeName:現在VMIがどのノードで実行中か
  • Phase:Pending、Scheduling、Runningなどの上位状態
  • Conditions:paused、agent connected、migratableなどの詳細フラグ
  • Interfaces:ゲストとPodインターフェースのマッピング状態
  • MigrationState:migration進行状況
  • MigrationMethod:live migrationかblock migrationか
  • MigrationTransport:どのtransportを使用するか
  • ActivePods:一つのVMIに対してどのlauncher Podが生きているか

特にActivePodsはmigration時に重要だ。通常はVM一台にPod一つのように見えるが、migration中はsource Podとtarget Podが一時的に共存できる。

VirtualMachineInstanceMigrationは「作業リクエスト」だ

多くのユーザーがmigrationをVMI status内のボタンのように考えるが、KubeVirtは別のCRDを使用する。VirtualMachineInstanceMigrationオブジェクトを作成するとcontrollerがそれを見てmigration orchestrationを開始する。

この設計の利点は明確だ。

  • migrationを監査可能な独立オブジェクトとして追跡できる
  • ポリシー適用が容易になる
  • 状態遷移を別のライフサイクルとしてモデリングできる
  • 失敗理由を作業単位で残せる

pkg/virt-api/rest/lifecycle.goのmigrate handlerを見ると、実際にmigrateリクエストは内部でVirtualMachineInstanceMigrationオブジェクト作成に変換される。つまりユーザーの「migrate」ボタンクリックは結局「migration CR作成」に変わる。

オブジェクト関係を一つの図で理解する

VirtualMachine
  -> template/spec/policyを持つ長期オブジェクト
  -> 実行が必要な時にVMIを誘導

VirtualMachineInstance
  -> 現在実行中のゲストインスタンス
  -> Pod、ノード、ネットワーク、ストレージ、migration状態の中心

VirtualMachineInstanceMigration
  -> 特定VMIを移すための一回限りの作業オブジェクト
  -> controllerがtarget Pod作成とhandoffを開始

この構造は「desired state」、「runtime instance」、「operation request」を混ぜないようにする意図と理解すればよい。

schema.goに見える設計哲学

schema.goを見るとVMI spec内にネットワークとボリューム、CPU、memory、firmware、launch security、access credentialsなどのフィールドが非常に豊富に定義されている。これはKubeVirtが単純に「QEMU実行ラッパー」ではなく、ゲストハードウェアと運用環境をKubernetes API形式で宣言可能にした層であるということを意味する。

逆にstatus側はオーケストレーション親和的に設計されている。例えばネットワークインターフェースstatus、ゲストOS情報、migration stateはゲスト内部情報とクラスタオーケストレーション状態を共に含む。この点がコンテナPod statusとは異なる質感だ。

なぜVMとVMIを統合しなかったのか

この質問は重要だ。もし一つのオブジェクトにすべて入れたら、実装は単純に見えるかもしれない。しかし実際の運用では以下の問題が生じる。

1. オフにしてオンにしても同じ「意図」を維持しにくい

実行中のインスタンス状態とユーザーの永続的設定が一つのオブジェクトに混ざるとライフサイクルが複雑になる。

2. status churnが大きくなりすぎる

ランタイム状態は頻繁に変わるが、意図は頻繁には変わらない。両者を分離してこそwatch コストとreconcile責任が整理される。

3. migrationのような作業をモデリングしにくい

別の作業オブジェクトがあってこそ、ポリシー、キューイング、優先順位、失敗理由をきれいに扱える。

運用者がstatusで最初に見るべきもの

実務ではこの3つのオブジェクトすべてを見るが、状況ごとに優先順位が異なる。

VMが起動しない場合

  • VirtualMachineのrun strategy
  • VMIが作成されたか
  • VMI phaseがどこまで進んだか

ネットワークやブートがおかしい場合

  • VMI statusのInterfaces
  • Conditions
  • ActivePods

migrationが問題の場合

  • VirtualMachineInstanceMigration status
  • VMI statusのMigrationState
  • source Podとtarget Podの状態

よくある誤解

誤解1:VMとVMIは名前が違うだけで実質同じだ

違う。一つは意図、一つはランタイム実体だ。この違いを理解してこそstart/stop、restart、migration、drainロジックが見える。

誤解2:migrationはVMIフィールドを一つ変えるだけで始まる

違う。別のmigration CRが作成され、controllerがそのオブジェクトを作業単位として消費する。

誤解3:statusは単なるUI用途だ

違う。KubeVirt内部コンポーネント同士が協力するための重要な契約面だ。

まとめ

KubeVirtのオブジェクトモデルは偶然複雑なのではない。VirtualMachineは持続的な意図、VirtualMachineInstanceは実行中のインスタンス、VirtualMachineInstanceMigrationは一回限りの移動リクエストを表現する。この分離があるからこそKubeVirtはKubernetesスタイルの宣言的APIを維持しながらも、VM実行や移動のように状態が多い作業を安定的に処理できる。

次の記事では、これらのオブジェクトが実際のAPI進入点でどのように扱われるか、そしてvirt-apiがどのような検証とsubresource動作を行うかを見ていく。