こんにちは!クラウドインフラの世界へようこそ。
AWSのEC2やGCPのCompute Engineなど、クラウドを使っていると「物理サーバーのメンテナンスが行われますが、お客様の仮想マシン(VM)は停止することなく稼働し続けます」というアナウンスを見かけることがありますよね。
「えっ、物理的な機械を交換したりメンテナンスしたりするのに、その上で動いているシステムが1秒も止まらないなんて、一体どういう魔法を使っているの……?」と不思議に思ったことはありませんか?
この「魔法」の正体こそが、今回ご紹介するライブマイグレーション(Live Migration)という技術です。
この記事では、インフラやネットワークの世界に足を踏み入れたばかりのみなさんに向けて、稼働中の仮想マシンを別の物理サーバーへお引越しさせる2大アプローチ、「Pre-copy(プレコピー)方式」と「Post-copy(ポストコピー)方式」の仕組みを、身近な「お引越し」の例えを交えながら、一歩ずつ紐解いていきます!
—
そもそも仮想マシンのお引越しで一番大変なものとは?
仮想マシン(VM)は、物理サーバーの上で動く「ソフトウェアで再現されたパソコン」です。仮想マシンがお引越し(マイグレーション)するときに運ばなければいけない主な要素は次の3つです。
1. 仮想CPUの状態(今どのプログラムのどの行を実行しているかというレジスタ情報)
2. 仮想ディスク(ハードディスクやSSDに入っているファイルやOSのデータ)
3. メインメモリ(実行中のアプリが作業用に使っているデータ)
この中で、ディスクは「共有ストレージ(みんなで使える巨大な外付けハードディスクのようなもの)」に置いておけば、引っ越し先からそのままアクセスできるので、実は運ぶ必要がありません。また、CPUの状態はほんの数キロバイト程度の小さなメモ書きのようなものなので、一瞬で転送できます。
一番の厄介者は、「ギガバイト単位で存在するメインメモリ」です。
仮想マシンが動いている間、メモリの中身はミリ秒単位で猛烈に書き換わり続けています。「よし、メモリをコピーしよう!」とネットワーク経由でデータを送っている最中にも、元の場所では新しいデータがどんどん書き込まれてしまうのです。
この「動き続ける巨大なメモリ」をどうやって移動させるか。ここで登場するのが「Pre-copy」と「Post-copy」という2つのアプローチです。
—
方式1:安全第一!普段の生活を続けながら少しずつ荷出しする「Pre-copy方式」
現在、世の中で最も広く使われている標準的な方法がPre-copy(事前コピー)方式です。
身近な例えでイメージしてみよう
あなたが今住んでいる部屋(移行元サーバー)から、新しい部屋(移行先サーバー)へ引っ越す場面を想像してください。
1. 第1ラウンド(全量コピー):
生活を続けながら、本棚の本や押し入れの荷物など、部屋にある荷物の大部分を新居へトラックで運びます。
2. 第2ラウンド(差分コピー):
荷物を運んでいる最中にも、部屋でご飯を食べたり料理をしたりして、食器やゴミなど「新しく散らかった物(変更されたメモリ)」が出ますよね。その「散らかった物だけ」をメモしておいて、もう一度新居へ運びます。
3. 繰り返し(反復フェーズ):
「散らかった物」を運んでいる間にも、また少し散らかります。前より散らかる量は減っていくはずなので、差分がごくわずかになるまでこの往復を繰り返します。
4. 最後の仕上げ(スイッチ切り替え):
「よし、散らかった荷物はあとダンボール1箱分だけだ!」となった瞬間に、数ミリ秒だけ生活を完全にストップ(一時停止)します。最後のダンボールと「あなた自身(CPUの状態)」が新居へワープし、新居で生活を再開します!
【移行元ホスト (Source)】 【移行先ホスト (Destination)】
[ 仮想マシン稼働中 ]
│
├─ (1) 全メモリページを送信 ───────► 受信してメモリに配置
│ (VMは動き続けているので
│ 一部のメモリが書き換わる: Dirty Page)
│
├─ (2) 書き換わった差分のみ送信 ───► 受信して上書き
│ (さらに小さく書き換わる)
│
├─ (3) 差分が十分に小さくなるまで反復...
│
[ 一時停止! ] (ダウンタイム: 数十ミリ秒)
├─ (4) 最後の差分 + CPU状態 ─────► [ 仮想マシン再開! ]
技術的なポイント:Dirty Page(ダーティページ)
Pre-copy方式の肝は、メモリの「更新された箇所」をハイパーバイザー(仮想化を管理する親玉ソフトウェア)が見張り続けることです。この「コピー中に書き換わってしまったメモリ領域」のことを専門用語でDirty Page(ダーティページ)と呼びます。
Pre-copyは非常に安全です。なぜなら、万が一ネットワークトラブルでデータ転送が失敗しても、元のサーバーで仮想マシンがそのまま動き続けているため、システムが壊れる心配がないからです。
Pre-copyの弱点:「書き込みが激しすぎるVM」は引っ越しが終わらない?
しかし、この安全なPre-copyにも弱点があります。もし仮想マシンが、ネットワークの転送速度を上回るスピードでメモリをバシバシ書き換えるデータベース(RDBMS)などだった場合どうなるでしょうか?
運ぶスピードより散らかるスピードの方が速いため、いつまで経っても差分がなくならず、引っ越しが永久に終わりません。これを現場では「マイグレーションが収束(コンバージ)しない」と呼びます。
—
方式2:先に体だけワープ!?現地調達型の「Post-copy方式」
そこで登場したもうひとつの強力な武器が、Post-copy(事後コピー)方式です。
身近な例えでイメージしてみよう
Pre-copyとは発想が完全に真逆です。
1. まず身体だけお引越し:
旧居での生活をピタッと止めます。荷物は部屋に全部置いたまま、「あなた自身(CPUの状態)」だけが新居へ一瞬でワープします。
2. 新居で即座に生活スタート:
新居に到着した瞬間から生活(処理)を再開します。
3. 必要なものは都度電話して送ってもらう(オンデマンド):
新居で「あ、歯ブラシがない!」となったら、旧居へ電話をかけて「歯ブラシ(必要なメモリ)を今すぐバイク便で送って!」と頼みます。届いたら歯磨きを続けます。
4. 裏で残りの荷物も運ぶ(バックグラウンド転送):
電話で呼ばれていない荷物も、裏でトラックを使って少しずつ新居へ運び込みます。すべての荷物が新居に揃ったら、引越し完了です!
【移行元ホスト (Source)】 【移行先ホスト (Destination)】
[ 仮想マシン稼働中 ]
│
[ 一時停止! ] (ダウンタイム: 数十ミリ秒)
│
├─ (1) CPU状態だけを先に送信 ─────► [ 仮想マシン即座に再開! ]
│ │
│ 「あ!このメモリがない!」
│ (Page Fault 発生)
│ │
│◄─ (2) 「このページを今すぐちょうだい」 ─┤ (オンデマンド要求)
├─ (3) 要求されたページを最優先で送信 ──► 処理を継続
│
├─ (4) バックグラウンドで残りの全メモリを順次送信 ──► 全て揃えば完了!
技術的なポイント:Page Fault(ページフォールト)とuserfaultfd
新居で動いている仮想マシンが、まだ手元に届いていないメモリを読み書きしようとすると、OSは「あれ?メモリがないぞ!」というエラー(Page Fault)を出します。
Linuxには、このエラーを検知してネットワーク越しに元のサーバーから該当メモリを大至急お取り寄せする仕組み(userfaultfd など)が備わっています。
Post-copyのメリットと最大のリスク
Post-copyの最大のメリットは、「どれだけ激しくメモリが書き換わっていようが、確実に引っ越しを終わらせることができる」という点です。同じメモリを何度も転送する無駄が発生しません。
しかし、最大のデメリットは「ネットワーク切断=VMの死滅」というハイリスクさです。
仮想マシンの「脳(CPU)」は新居にあり、「記憶(メモリ)」の半分は旧居にある状態です。もし途中でネットワークケーブルが抜けたら……記憶がバラバラに引き裂かれ、仮想マシンはクラッシュして元に戻せなくなってしまいます。まさに背水の陣ですね!
—
実践編:Linux環境でライブマイグレーションを制御してみよう
Linux標準の仮想化基盤である KVM と、それを管理する libvirt(コマンド名は virsh)を使うと、これらの動作を実際に試したり、パラメーターを細かくチューニングしたりできます。
1. 基本のPre-copyマイグレーションを実行する
まずは、最も一般的で安全なPre-copy方式での移行コマンドを見てみましょう。
# 仮想マシン「web-server-01」を、移行先ホスト「192.168.10.20」へPre-copyで安全に移行する
virsh migrate --live \
--verbose \
--p2p \
--tunnelled \
web-server-01 \
qemu+ssh://root@192.168.10.20/system
--live: 仮想マシンを停止させずにライブマイグレーションを行います(デフォルトはPre-copy)。--verbose: メモリの転送進捗(何%完了したか)をリアルタイムに表示してくれます。--p2p&--tunnelled: 管理ホストを経由せず、ハイパーバイザー同士が直接安全な通信経路を張ってメモリを転送します。
2. 「終わらない引越し」を救う!Post-copyへの自動切り替え設定
メモリの書き込みがあまりにも激しく、Pre-copyの差分転送が収束しない時のために、最近の環境では「最初は安全なPre-copyで進め、もし一定時間経っても終わらなければ自動的にPost-copyへ切り替える」というハイブリッドな運用が主流になっています。
これを実現するには、移行時に --postcopy フラグを有効化しておきます。
# Post-copyへの切り替えを許可した状態でマイグレーションを開始
virsh migrate --live \
--postcopy \
--verbose \
web-server-01 \
qemu+ssh://root@192.168.10.20/system
もし、ターミナルで進捗を眺めていて「差分転送が全然終わらないな……」と感じたら、別のターミナルから次のコマンドを叩くことで、手動でPost-copyモードへ強制スイッチ(身体だけ先に飛ばすモードへ移行)させることができます。
# 実行中のマイグレーションを、即座にPost-copyモードへ切り替える
virsh migrate-postcopy web-server-01
3. 最大ダウンタイム(サービス停止時間)の制限を設定する
「最後の仕上げ(CPUと最終差分のワープ)」の瞬間に生じる、ほんのわずかな停止時間をダウンタイム(Downtime)と呼びます。この時間を「最大でも◯ミリ秒以内に抑えたい!」とハイパーバイザーにお願いする設定も可能です。
# 移行の最終フェーズで許容する停止時間(ダウンタイム)を最大50ミリ秒に設定する
virsh migrate-setmaxdowntime web-server-01 50
ハイパーバイザーは、「残りの差分メモリ転送にかかる推定時間」がこの 50 ミリ秒を下回るまで、粘り強くPre-copyを反復し、条件が整った瞬間に切り替えを実行してくれます。賢いですね!
—
Pre-copy と Post-copy の違いまとめ
最後に、2つの方式の特徴を表でおさらいしておきましょう。
| 項目 | Pre-copy(事前コピー) | Post-copy(事後コピー) |
| :— | :— | :— |
| 基本的な発想 | 荷物をあらかじめ全部運んでからワープ | 先にワープして、荷物は後から届けてもらう |
| ダウンタイムの発生タイミング | 移行プロセスの最後(切り替え時) | 移行プロセスの最初(開始時) |
| メモリ書き込みの多いVM | 差分コピーが終わらず移行に失敗しやすい | 書き込み量に関係なく確実に完了できる |
| 転送中の障害(耐障害性) | 安全(旧サーバーでそのまま継続可能) | 極めて危険(VMが破損・停止するリスクあり) |
| 転送中のVMの動作速度 | 通常通りスムーズに動作する | ページ要求(Page Fault)待ちで一時的に遅くなる |
—
おわりに
普段私たちが何気なく利用しているメガクラウドの裏側では、物理サーバーの故障予兆を検知した瞬間に、何千・何万もの仮想マシンがこのPre-copyやPost-copyの技術を使って、まるで忍者のように別のサーバーへと飛び移っています。
ネットワーク帯域の太さ、メモリの書き換わる速度、そして耐障害性のバランスを考えながら設計されたこの仕組みを知ると、インフラの泥臭くも美しい技術の結晶にワクワクしてきませんか?
もし手元に検証用のLinux環境があれば、ぜひ virsh コマンドを使って、仮想マシンがネットワークを駆け巡る様子を体感してみてくださいね!
コメント