はじめに
KubeVirtを運用していると最も難しい質問はこれである。「今このVMは本当にどこまで生きているか?」PodはRunningなのにゲストは止まっているかもしれないし、ゲストは生きていてもマイグレーションが失敗寸前かもしれない。そのためKubeVirtは状態を一箇所ではなく複数の層で収集する。
- Kubernetesオブジェクト状態
- libvirtドメイン状態
- ゲストエージェントが教えてくれるゲスト内部情報
- ネットワークstatusとマイグレーションstatus
- Prometheusメトリクス
本記事ではこの観測レイヤーがどうつながるかを見る。
1. VMI statusは最も重要な運用面である
`staging/src/kubevirt.io/api/core/v1/types.go`の`VirtualMachineInstanceStatus`を見ると運用者が見たい情報がかなり多く含まれている。
- `phase`
- `conditions`
- `interfaces`
- `guestOSInfo`
- `migrationState`
- `qosClass`
- `activePods`
- `selinuxContext`
- `memory`
- `currentCPUTopology`
この型を読むだけでKubeVirtが状態を単に「オンまたはオフ」で見ていないことがわかる。VM状態はKubernetesフェーズとゲスト内部情報、マイグレーション進捗度、ネットワークインターフェース状態が合わさった結果である。
2. phaseだけでは不十分でconditionsを一緒に見る必要がある
`phase`は上位の流れを要約する。Pending、Scheduling、Scheduled、Running、Succeeded、Failed、Unknownのような値は大きな方向を示す。
しかし実際の運用判断は`conditions`と`reason`、`message`から来る。API型には以下のようなconditionとreasonが事前定義されている。
- `LiveMigratable`
- `StorageLiveMigratable`
- `MigrationRequired`
- `EvictionRequested`
- `DataVolumesReady`
- `DisksNotLiveMigratable`
- `InterfaceNotLiveMigratable`
- `HostDeviceNotLiveMigratable`
- `SEVNotLiveMigratable`
- `SecureExecutionNotLiveMigratable`
つまりKubeVirtは「できない」とだけ言うのではなく、**なぜライブマイグレーションができないかまで型システムに標準化**している。
3. activePodsはマイグレーション時に特に重要
`VirtualMachineInstanceStatus.ActivePods`はPod UIDとノード名のマッピングである。コメントにも書かれている通り、マイグレーション中は一つのVMIに複数のPodが同時にかかる場合がある。
このフィールドは「現在どのvirt-launcher Podがソースでターゲットか」を読むのに重要である。実際の運用でマイグレーションタイミングの混乱は大部分ここから始まる。単一VMだと思っていたが、コントロールプレーンの立場からはソースlauncherとターゲットlauncherが同時に存在する短い区間があるからである。
つまり`activePods`はマイグレーションデバッグにおける隠れた重要フィールドである。
4. ネットワーク状態はPodアノテーションとゲスト情報が合わさる
`pkg/network/controllers/vmi.go`を見るとVMI statusの`interfaces`は一箇所からだけ来るのではない。
- Multusネットワークstatusからpodインターフェース名を読み
- プライマリとセカンダリインターフェースを計算し
- 既存statusの中でspecにない項目も保存する
また API型の`VirtualMachineInstanceNetworkInterface`には以下が含まれる。
- ゲストIP
- MAC
- ネットワーク名
- Podインターフェース名
- VM内部インターフェース名
- info source
特に`infoSource`はこの情報がゲストエージェントから来たか、ドメインから来たか、multus-statusから来たかを区別する。この設計のおかげで運用者は「このIPはゲスト内部から報告された値か、CNIが報告した値か」を見分けられる。
5. ゲストエージェントはゲスト内部情報を引き出す窓口
`pkg/virt-launcher/virtwrap/manager.go`の`DomainManager`インターフェースを見るとゲスト関連メソッドがかなり多い。
- `GetGuestInfo`
- `GetUsers`
- `GetFilesystems`
- `GetGuestOSInfo`
- `GuestPing`
これは重要なシグナルである。KubeVirtはlibvirtとQEMUレベルの状態だけでは不十分と考え、ゲストエージェントを通じてOS内部の情報を別途収集している。
`pkg/virt-handler/rest/lifecycle.go`はこのデータをlauncherクライアントを通じて受け取りAPIレスポンスとして出力する。つまり運用者が見るゲスト情報は結局:
- virt-handler RESTエンドポイント
- launcherクライアントRPC
- virt-launcher内部ドメインマネージャー
- QEMUゲストエージェント
を経由した結果である。
6. domain statsはホスト可観測性とゲスト可観測性の中間層
同じ`DomainManager`インターフェースには`GetDomainStats`と`GetDomainDirtyRateStats`もある。これはゲストエージェントとは別にlibvirtが報告するドメインレベル統計を引き出すことを意味する。
この階層はゲスト内部でエージェントが応答しなくてもまだ見られる情報が多い。
- CPU使用量
- メモリ状態
- ブロックI/O
- ネットワークトラフィック
- ダーティページ率
つまりゲストエージェントはゲスト内部の意味を教え、domain statsはハイパーバイザーが観察した実行事実を教える。両者は競合関係ではなく相互補完関係である。
7. Prometheusメトリクスはvirt-handlerから多く出る
`pkg/monitoring/metrics/virt-handler/domainstats`を見ると、CPU、メモリ、ブロック、vcpuなどのドメイン統計をPrometheusメトリクスに変換するcollectorがある。
この構造はかなり現実的である。
- 実際のVMプロセスに最も近い場所はノードである。
- ノードからdomain statsを収集するのが最も容易である。
- そのためメトリクスexportもvirt-handlerに近く付く。
つまりKubeVirtの可観測性は中央controllerより**node-localエージェントでより多くの実行事実を収集する構造**に近い。
8. ゲストエージェントがないと何が減るか
ゲストエージェントがなくてもVMが起動しないわけではない。しかし運用者が見られる意味のある情報がかなり減る。
- ゲスト内部ユーザーリスト
- ファイルシステムリスト
- OS pretty name
- インターフェース名と一部のゲストIP情報
つまりゲストエージェントは必須のブート依存関係ではなく、運用可視性と自動化を豊かにする拡張レイヤーである。
そのため「Podは正常なのにVM内部が見えない」という状況ではゲストエージェントのインストールと接続状態をまず疑うべきである。
9. デバッグはコントロールプレーン、ノード、ゲストを分けて見るべき
KubeVirt問題を見るとき最もよくある間違いはレイヤーを混ぜることである。次のように分けて見るほうがよい。
コントロールプレーンで見ること
- VMI `phase`
- `conditions`
- `migrationState`
- `activePods`
- イベントとmigration CR状態
ノードで見ること
- virt-handlerログ
- virt-launcherログ
- libvirtドメイン状態
- domain stats
- Podネットワークとtap状態
ゲストで見ること
- QEMUゲストエージェント応答の有無
- ゲストOS info
- ユーザー
- ファイルシステム
- 実際のサービスヘルス
つまりKubeVirtデバッグは結局「どのレイヤーのtruthを見ているか」を区別する作業である。
10. statusは常にすぐに真実を反映するわけではない
API型コメントにすでに書かれている通り、`VirtualMachineInstanceStatus`は実際のシステム状態を後追いする場合がある。これは非常に重要な運用ポイントである。
なぜならstatusはinformer、controller、launcher、libvirt、ゲストエージェントを経て更新されるからである。したがって非常に短い瞬間には:
- Podはすでに変わったがstatusが遅れる場合がある
- マイグレーションターゲットは立ち上がったが`phase`がまだ以前の値の場合がある
- ゲストエージェントは死んでいるがドメインはRunningの場合がある
つまりKubeVirtは強い一貫性ではなく、複数の観測面を組み合わせて判断すべきシステムである。
運用者が覚えるべき要点
- `phase`だけでは不十分である。`conditions`、`reason`、`migrationState`を一緒に見る必要がある。
- `activePods`はマイグレーション中のソースとターゲットPodを読むのに重要。
- ネットワーク状態はMultus、ドメイン、ゲストエージェント情報が合わさった結果。
- ゲストエージェントとdomain statsは互いの代替ではなく補完関係。
まとめ
KubeVirtの可観測性は単一の状態値ではなく複数レイヤーの情報を合わせて作られる。VMI statusはKubernetesリソース観点の現在状態を示し、ゲストエージェントはゲスト内部の意味を明らかにし、domain statsとPrometheusメトリクスは実際の実行データプレーンを観察可能にする。そのためKubeVirt運用は「VMが起動したか」を問う作業より、「どのレイヤーでどのシグナルが壊れたか」を区別する作業に近い。
次の記事では、この観測モデルを基に、drain、eviction、マイグレーション障害、non-migratable conditionなどの実際の障害モードを整理する。
현재 단락 (1/110)
KubeVirtを運用していると最も難しい質問はこれである。「今このVMは本当にどこまで生きているか?」PodはRunningなのにゲストは止まっているかもしれないし、ゲストは生きていてもマイグレーシ...