Skip to content
Published on

Live Migration 2:pre-copy、post-copy、ダーティページ、auto-convergeの実際の意味

Authors

はじめに

いよいよライブマイグレーションの本当に難しい区間に入る。target Podを立ち上げるところまではKubernetesコントロールプレーンの問題だった。その先からはlibvirtとQEMUがゲストのメモリ、CPU状態、一部のディスク状態をどう移すか決定するデータ転送の問題になる。

この区間の核心コードはpkg/virt-launcher/virtwrap/live-migration-source.goである。ここでKubeVirtはlibvirtマイグレーションフラグを構築し、進行状態をモニタリングし、必要に応じてpost-copyやpauseなどの補助戦略を発動する。

マイグレーションデータプレーンで実際に移されるもの

ライブマイグレーションといっても「VM全体を一度にコピーする」わけではない。実際には:

  • ゲストメモリページ
  • CPU実行状態
  • 一部のデバイス状態
  • 必要に応じてローカルボリューム関連データ

が移される。

共有ストレージがあればディスクデータ全体をコピーする必要はないが、メモリと実行状態は継続して転送する必要がある。ここで最も難しい問題はゲストが継続的にメモリをダーティにし続けることである。

pre-copyとは何か

pre-copyは最も基本的なマイグレーション戦略である。

  1. ソースVMは実行を続ける。
  2. 同時にメモリページをターゲットにコピーする。
  3. コピー中に再度変更されたページは次のラウンドで再コピーする。
  4. 十分に収束したら短いstop-and-copy切り替えを行う。

この方式の利点はゲストがほとんどの時間実行を続けることである。欠点はゲストがメモリを高速に変更するとコピーが永遠に追いつけない可能性があることである。

ここで登場する概念がダーティページレートである。

ダーティページレートがなぜ重要か

live-migration-source.gologMigrationInfoを見ると、libvirt job statsから以下の情報を読み取っている。

  • DataRemaining
  • MemProcessed
  • MemRemaining
  • MemDirtyRate
  • Downtime

つまりKubeVirtはマイグレーションを「成功か失敗か」だけで見ず、今どれだけ残っているか、ゲストがどれだけ速くメモリを再びダーティにしているかを継続的に観察している。

VMが非常にwrite-heavyな場合、コピーしたページがすぐにダーティになりpre-copyが収束しない可能性がある。高性能データベースやメモリ集約ワークロードがここで難しい。

libvirtマイグレーションフラグは何を教えてくれるか

generateMigrationFlagsを見ると、KubeVirtがマイグレーション時にlibvirtにどのモードを要求するかがわかる。

  • MIGRATE_LIVE
  • MIGRATE_PEER2PEER
  • MIGRATE_PERSIST_DEST
  • ブロックマイグレーションの場合 MIGRATE_NON_SHARED_INC
  • auto-converge許可時 MIGRATE_AUTO_CONVERGE
  • post-copy許可時 MIGRATE_POSTCOPY
  • パラレルマイグレーションの場合 MIGRATE_PARALLEL

つまりマイグレーション方式は漠然とした概念ではなく、結局libvirtフラグの組み合わせとして具体化される。

migration monitorがやること

migrationMonitorはデータプレーンを監視する心臓部である。ここでKubeVirtは:

  • 残りデータを追跡し
  • 進行が止まったか判断し
  • 許容完了時間を超えたか確認し
  • 必要に応じてpost-copyやpause戦略を発動し
  • 完全にstuckなら中断する

この構造は非常に現実的である。マイグレーションは「始めれば最後まで行く」ではなく、進捗ベースの適応型制御が必要である。

いつpost-copyに切り替わるか

コードを見ると、マイグレーションが長時間stallしていて、AllowPostCopyが有効で、VFIO VMIでなければdom.MigrateStartPostCopyが呼ばれる。つまりKubeVirtは最初からpost-copyで始めるのではなく、通常pre-copyで始めた後、収束しなければpost-copyに切り替える。

post-copyの意味

  • ソースがすべてのページを事前にコピーしようとするのをやめる
  • ターゲットがアクティブワークロードをより早く受け取る
  • 必要なページを後から取得できる

利点は忙しいVMでも結局移動を完了する可能性が高まることである。しかし欠点は大きい。アクティブ状態がターゲットに移った後にネットワークやターゲット障害が起きるとゲストがより脆弱になる可能性がある。

そのためKubeVirtのドキュメントと設定はpost-copyを強力だが危険なオプションとして扱っている。

auto-convergeとpauseはなぜ必要か

すべての環境でpost-copyが許可されるわけでもなく、すべてのワークロードに適しているわけでもない。そこでKubeVirtは他の補助戦略も使う。

auto-converge

libvirtとQEMUがゲストパフォーマンスにある程度影響を与えてダーティレートを下げる戦略。簡単に言えば「少し遅くなってもマイグレーションを終わらせよう」というアプローチである。

pause

コードではpost-copyが許可されていないか適切でない場合、ゲストを一時的にサスペンドしてマイグレーションを完了させる。これはダウンタイムを犠牲にして完了を得る戦略である。

つまりマイグレーションはパフォーマンス、可用性、成功確率の三角トレードオフである。

VFIOワークロードがなぜより難しいか

live-migration-source.goはVFIOベースのVMIを別途扱う。post-copyが一般的にサポートされない場合があり、代わりに非常に大きなmax downtimeを設定してQEMU内部のswitchoverを誘導する。

これはデバイスパススルーワークロードがメモリだけ移せばいい通常のVMよりはるかに難しいことを意味する。ネットワークSR-IOVやGPUパススルーワークロードでマイグレーション制約が大きい理由がここにある。

マイグレーションがstuckしたと判断する基準

コードは「進捗がなくネットワークまたはQEMU接続の問題が疑われればabort」という非常に実務的な判断をする。つまり単に遅いことと完全に止まったことを区別する。

代表的な二つのケースがある。

  • progress timeout中にDataRemainingが減少しない
  • 全体のacceptable completion timeを超過

前者は通常stuck、後者は収束失敗に近い。

ディスクマイグレーションとメモリマイグレーションが混ざるとき

ブロックマイグレーションやボリュームマイグレーションがあると難易度はさらに上がる。classifyVolumesForMigrationconfigureLocalDiskToMigrateのようなロジックがある理由である。メモリとディスクを同時に移すと帯域幅、完了時間、障害サーフェスが増大する。

ソースコードにもデスティネーションボリュームがソースより小さい場合にマイグレーションが失敗する特別なエラーメッセージ改善ロジックがあるほどで、ストレージはマイグレーション失敗のよくある原因である。

よくある誤解

誤解1:ライブマイグレーションは無停止である

完全な無停止ではなく、ダウンタイムを最小化する移動である。収束しなければpauseやpost-copyに移行し、そのときのトレードオフが生じる。

誤解2:post-copyが無条件により良い

いいえ。成功確率を高めることはできるが、障害時のリスクはより大きい。

誤解3:マイグレーション失敗は大部分ネットワークのせい

ネットワークも原因だが、ダーティレートが高すぎる、ローカルボリューム条件が合わない、デバイスパススルー制約の場合もある。

運用者が必ず見るべき指標

  • 残りデータが減っているか
  • ダーティレートは高いか
  • post-copyに切り替わったか
  • マイグレーションモードがpausedまたはpost-copyに変わったか
  • ボリュームマイグレーションが混ざっているか

これらの指標を見れば「なぜマイグレーションが遅いか」と「なぜマイグレーションが失敗したか」を分離して見ることができる。

まとめ

KubeVirtライブマイグレーションのデータプレーンはpre-copyを基本としつつ、収束しなければauto-converge、pause、post-copyなどの補助戦略を使う適応型システムである。この構造は忙しいVMをできるだけ長く生かしつつ結局移動できるようにするための現実的な妥協である。したがってマイグレーションを正しく理解するにはlibvirtフラグ、ダーティページレート、progress timeout、post-copy切り替え条件を一緒に見る必要がある。

次の記事では、このデータ転送がどのネットワーク経路とソケット、ポートを通じて行われるかをmigration proxyの観点で見ていく。