はじめに
運用の観点から、KubeVirtの本当の難しさはVMを起動する瞬間ではなく、障害を扱う瞬間に現れる。Podは再スケジューリングすれば済むことが多いが、VMはメモリ状態、ディスク、ネットワークセッション、ゲストの実行コンテキストまで一緒に考慮する必要がある。そのためdrainとeviction、マイグレーション障害はKubeVirtの内部設計を最もよく示す場面である。
本記事では「何が障害と見なされるか」と「障害をKubeVirtがどう標準化して表面化するか」を見ていく。
1. KubeVirtはdrainを直ちにkillとして処理しない
API型の`EvictionStrategy`アノテーションを見ると、node drainの状況でどの戦略を使うか定義されている。つまりKubeVirtはdrainを単純なKubernetes evictionイベントとして見ず、VM専用のポリシー判断が必要なイベントとして扱っている。
その理由は明確である。
- migratableであればまず移すほうがよい。
- non-migratableであれば中断や保留が必要かもしれない。
- 外部コントローラが所有するVMであれば別の処理モデルが必要かもしれない。
つまりKubeVirtにおいてdrainは「Pod一つを空ける」ことではなく、「このVMをどの方法で退避させるか」という問いである。
2. EvictionRequestedとEvacuationNodeNameは運用者が必ず確認すべき
`VirtualMachineInstanceStatus`には`EvacuationNodeName`があり、conditionタイプには`EvictionRequested`が定義されている。これはevictionが単なるイベントログに残るだけでなく、VMI statusに構造化されたシグナルとして残ることを意味する。
運用者がこの値を見るべき理由は以下の通り。
- drainが始まったか
- どのノードからevacuateしようとしているか
- その後マイグレーションが続くべきか
- 外部コントローラがフォローアップアクションを取るべきか
つまりKubeVirtはdrainをstatus-first方式で表面化する。
3. ライブマイグレーション不可の理由を事前にreasonとして残す
KubeVirt API型にはnon-migratable reasonが非常に多く定義されている。
- `DisksNotLiveMigratable`
- `InterfaceNotLiveMigratable`
- `HotplugNotLiveMigratable`
- `VirtIOFSNotLiveMigratable`
- `HostDeviceNotLiveMigratable`
- `SEVNotLiveMigratable`
- `SecureExecutionNotLiveMigratable`
- `TDXNotLiveMigratable`
- `HypervPassthroughNotLiveMigratable`
- `PersistentReservationNotLiveMigratable`
この設計が優れているのは、障害を事後のランタイムエラーとしてのみ見ないからである。KubeVirtはcondition reasonで事前に「なぜこのVMは移行できないか」を伝える。
つまり運用者はマイグレーションを発行して障害ログを待つ前に、API状態だけで大まかな制約を読み取ることができる。
4. MigrationStateは障害分析の中心軸である
`VirtualMachineInstanceMigrationState`には障害分析に必要な情報が多く含まれている。
- ソースノードとソースPod
- ターゲットノードとターゲットPod
- 同期アドレス
- ダイレクトマイグレーションポート
- 完了状態
- 失敗状態
- 中断リクエスト状態
- 中断ステータス
- 障害理由
- 現在のマイグレーションモード
この構造を見ると、KubeVirtがマイグレーションを単純なブーリアン状態として見ていないことがわかる。マイグレーションはソースとターゲットが時間と共に変わる分散プロトコルであり、障害も複数の段階で発生する。
5. pre-copyは失敗しても回復の余地があるが、post-copyはより危険
前の記事で見たように、pre-copyはソースに元のメモリが残った状態で段階的に転送する。一方、post-copyはターゲットが先に実行を開始し、必要なページを後からソースから取得する。
そのためpost-copy障害ははるかに危険である。`pkg/virt-handler/vm.go`には`formatIrrecoverableErrorMessage`があり、post-copy障害でdomainがpaused状態になると「VMI is irrecoverable due to failed post-copy migration」というメッセージが生成される。
これは非常に強いシグナルである。単にマイグレーションジョブが失敗したのではなく、**実行中のVM状態自体が回復不可能な方向に崩壊する可能性がある**ことを意味する。
つまりpost-copyは忙しいワークロードを移すための強力なツールだが、障害コストもより大きい。
6. abortも一つの状態マシンである
`VirtualMachineInstanceMigrationState`には`AbortRequested`と`AbortStatus`があり、abort状態もSucceeded、Failed、Abortingと別途モデル化されている。
この設計は現実的である。マイグレーション中断はボタン一つ押せばすぐ終わる作業ではない。
- まだ中断可能な段階か
- すでにターゲットがハンドオフを受けたか
- ストレージやネットワークのサイドエフェクトがどこまで進んだか
によって結果が変わる。つまりKubeVirtはabortも通常のAPIキャンセルではなく、別の状態マシンとして扱う。
7. マイグレーション障害はコントロールプレーンとデータプレーンの両方で発生する
障害原因を大きく分けると二つある。
コントロールプレーン側の障害
- ターゲットPodがスケジュールされない
- 適切なnode selectorを満たせない
- クォータやポリシーに引っかかる
- ユーティリティボリュームやバックアップによりブロックされる
データプレーン側の障害
- ダーティページ率が高すぎてpre-copyが収束しない
- post-copy切り替え後にソースとターゲットの同期が壊れる
- マイグレーションソケットまたはプロキシ経路の問題
- ターゲットでのドメイン準備が遅い
つまり「migration failed」の一行だけでは不十分で、どのプレーンで障害が起きたかを分けて見る必要がある。
8. セキュリティ機能はマイグレーションの柔軟性と衝突することが多い
API レベルですでに明らかなように、SEV、Secure Execution、TDX、ホストデバイスパススルーなどの機能はマイグレーション制約と頻繁に衝突する。
これは偶然ではない。これらの機能は大体次のいずれかを要求する。
- 特定のホストハードウェアとの強い結合
- ゲストメモリの特殊な保護方式
- 外部から再現しにくいデバイス状態の使用
つまりセキュリティを強化したりハードウェア性能を最大化するほど、「どのノードにでも無停止移動」という特性と衝突しやすくなる。
9. マイグレーション中の複数Pod存在は障害分析をより困難にする
`ActivePods`がなぜ重要かは障害モードでより明確になる。マイグレーション中はソースとターゲットのlauncher Podが一時的に共存するため、ログや状態を見るときにどのPodが本当の現在のソースか混乱しやすい。
障害を見るときは最低限以下を一緒に見る必要がある。
- VMIの`activePods`
- マイグレーションCRフェーズ
- ターゲットPod名
- ソースPod名
- VMIの`migrationState`
この情報を照合しなければ、すでにクリーンアップされたPodのログを見て現在の問題だと誤解しやすい。
10. drain運用戦略はワークロード特性に応じて変えるべき
すべてのVMに同じeviction strategyを適用してはいけない。例えば:
- ステートレスに近いテストVM
- SR-IOVとホストデバイスを使うパフォーマンス敏感なVM
- RWXボリュームとライブマイグレーションが可能な一般業務VM
- post-copy許可の可否が重要なメモリwrite-intensive VM
は障害コストと許容可能な対処が全く異なる。
つまりdrain戦略はインフラのデフォルトではなく、VM特性に合わせた運用ポリシーであるべきである。
運用者が覚えるべき要点
- drainはPod除去ではなくVM退避戦略の問題である。
- `EvictionRequested`、`EvacuationNodeName`、`MigrationState`を一緒に見る必要がある。
- non-migratable reasonは障害後のログではなく、事前判断シグナルである。
- post-copy障害はirrecoverable状態につながる可能性があるため、はるかに慎重に扱う必要がある。
まとめ
KubeVirtは障害を隠さず状態マシンとして構造化する。drainはeviction戦略と連携し、ライブマイグレーション可否はcondition reasonで事前に表面化され、実際のマイグレーション進行状況と障害理由は`MigrationState`に蓄積される。特にpost-copy障害をirrecoverableとして分離した点は、KubeVirtがVM障害を単純なPod再起動問題とは異なる視点で見ていることをよく示している。
次の記事ではシリーズを締めくくりながら、KubeVirtソースコードをどの順序で読めばこの全体構造を最速で理解できるか、ソース読み取りマップを整理する。
현재 단락 (1/87)
運用の観点から、KubeVirtの本当の難しさはVMを起動する瞬間ではなく、障害を扱う瞬間に現れる。Podは再スケジューリングすれば済むことが多いが、VMはメモリ状態、ディスク、ネットワークセッション...