【実務・中級編】 ライブマイグレーション(Live Migration)の通信シーケンスとメモリ転送 – クラウドインフラと仮想化ネットワーク実践ガイド

ゼロダウンタイムの魔法:ライブマイグレーションの裏側にある「メモリ同期」の執念

「VMを落とさずに物理ホストを移動させる」。クラウドネイティブな世界にどっぷり浸かっていると、ライブマイグレーションは当たり前の機能に思えるかもしれない。だが、裏側で何が起きているかを知れば、その「執念深さ」に戦慄するはずだ。

今日は、ハイパーバイザーの深淵、ライブマイグレーションのメモリ転送シーケンスについて深掘りしよう。これは単なる技術解説ではない。パケットロスを許さない、エンジニアたちの泥臭い戦いの記録だ。

—

1. ライブマイグレーションの正体:メモリの「追いかけっこ」

ライブマイグレーションの基本戦略は、「全メモリをコピーしつつ、コピー中に書き換えられた差分を追いかけ続ける」というものだ。これには大きく分けて3つのフェーズがある。

1. Iterative Pre-copy(反復事前コピー): まだVMが動いている状態でメモリをコピーする。
2. Stop-and-Copy(最終転送): VMを数ミリ秒だけ停止し、最後に残った「Dirty Pages(書き換えられたメモリ領域)」を転送する。
3. Resume(再開): 移行先でVMの実行を再開し、元のホストのメモリを解放する。

ネットワークエンジニアとして注目すべきは、この「Dirty Pages」の転送速度だ。もしアプリケーションが激しくメモリを書き換えるタイプ(例えば大規模なインメモリキャッシュや高負荷のDB)だと、追いかけっこが終わらず、ライブマイグレーションがいつまでも完了しない「スタベーション」を引き起こす。

—

2. 通信シーケンスのリアル:Dirty Pageの追跡

ハイパーバイザー(KVM/QEMUなど)は、メモリの変更を検知するために dirty bitmap という仕組みを使う。

  • ステップ1: ソースホストが全メモリをコピー開始。
  • ステップ2: コピー中もVMは動き続ける。書き換えられたページは dirty bitmap にマークされる。
  • ステップ3: ソースホストは dirty bitmap を見に行き、変更があったページだけを再度転送する。
  • ステップ4: 「残りの転送時間がネットワーク帯域で収まる」と判断されるまで、これを繰り返す。

ここで重要になるのが downtime(ダウンタイム許容値)の設定だ。

QEMUでの設定例(コマンドライン引数)

実際にライブマイグレーションをトリガーする際、QEMU Monitorや管理ツール(libvirtなど)で以下のような設定が飛ぶ。

# ライブマイグレーションの制限設定(QEMUモニター経由のイメージ)
# 転送帯域を1Gbpsに制限し、ダウンタイム許容を300msに設定
migrate_set_speed 1000000000
migrate_set_downtime 0.3
  • migrate_set_speed: 移行専用のネットワーク帯域を占有しすぎないよう調整する。
  • migrate_set_downtime: これが小さすぎると、Dirty Pageが減らずにマイグレーションがタイムアウトする。

—

3. 実務で遭遇する「ライブマイグレーション失敗」の勘所

現場でよくあるのは、「負荷が高い時に限ってライブマイグレーションが失敗する」というケースだ。これをデバッグするためのPythonスクリプトの断片を紹介しよう。QMP(QEMU Machine Protocol)を通じて現在のマイグレーション状態を監視するロジックだ。

import json
# QMPソケット経由でマイグレーション状態を取得する想定
def check_migration_status(qmp_socket):
    # 'query-migrate' コマンドを発行
    status = qmp_socket.execute("query-migrate")
    
    # 転送済みデータ量とDirty Pageの残量を確認
    ram = status.get("ram", {})
    remaining = ram.get("remaining", 0)
    dirty_rate = ram.get("dirty-pages-rate", 0)
    
    print(f"残りデータ量: {remaining} bytes")
    print(f"Dirty Page発生率: {dirty_rate} pages/sec")
    
    if remaining > 1024 * 1024 * 100: # 100MB以上残っていたら警告
        print("警告: 転送が追いついていません。ネットワーク負荷を確認してください")

ネットワークエンジニアへのTips

もし本番環境でライブマイグレーションが失敗し続けるなら、以下の3点を確認してほしい。

1. MTUの不一致: マイグレーションのパケットは巨大になりがちだ。ジャンボフレームが有効か、途中のスイッチで破棄されていないか。
2. 専用NICの分離: 管理用トラフィックとデータプレーンを同じNICで流すと、マイグレーション中に帯域枯渇が起きる。必ずマイグレーション専用の物理NIC/VLANを用意すること。
3. Dirty Rateの監視: アプリケーションの書き込み負荷が高すぎる場合、ライブマイグレーションはそもそも「不可能な作戦」になる。その場合は「一時的にアプリの負荷を落とす」か「オフラインマイグレーションを選択する」という勇気が必要だ。

—

最後に:完璧な技術はない

ライブマイグレーションは、物理的な限界と論理的な一貫性の間を縫うギリギリの操作だ。どんなに優れたハイパーバイザーでも、ネットワーク帯域がなければただの遅いコピーに過ぎない。

今日伝えたかったのは、コマンドを叩くことではなく、「裏でパケットがどのように流れ、どのタイミングでVMが停止するのか」というシーケンスをイメージする力だ。それができれば、インフラ運用はもっと面白くなるし、トラブルシューティングも恐ろしくなくなるはずだ。

次は、マイグレーション中のTCPセッションがなぜ切れないのか、Gratuitous ARPとスイッチのMAC学習のタイミングについて深く掘り下げてみよう。現場からは以上だ。

コメント

タイトルとURLをコピーしました