こんにちは!国内外の最新クラウド技術や、Kubernetesをはじめとするコンテナネットワークの深淵を日々追いかけているSRE兼クラウドアーキテクトの執筆陣です。
クラウドインフラを支える「仮想化技術」。AWSの EC2 や、ローカル環境の VirtualBox、VMware など、私たちは日常的に仮想マシン(VM)を使っていますよね。
しかし、その裏側で「メモリがどのように管理されているか」を覗いたことはありますか?
仮想マシンの中で動く「ゲストOS」は、自分が本物の物理メモリを独占していると思い込んでいます。しかし実際には、その下で動く「ハイパーバイザー」という大家さんが、物理メモリを切り分けて貸し出しているのです。
この「だまし絵」のような世界を実現するために、かつて大活躍し、今でも仮想化の基礎知識として欠かせない仕組みが「シャドウページテーブル(Shadow Page Table)」です。
今回は、このシャドウページテーブルの動く仕組みと、どうしても避けられない「同期コスト(オーバーヘッド)」の正体を、身近な例え話を使って世界一わかりやすく紐解いていきましょう!一歩ずつ、一緒に理解を深めていきましょうね。
—
1. そもそも「ページテーブル」ってなに?(郵便配達で例えてみる)
シャドウページテーブルの話に入る前に、まずはコンピュータがメモリを扱う基本の仕組みをおさらいしましょう。
コンピュータのメモリ管理は、よく「郵便配達」に例えられます。
- 仮想アドレス(住所):「東京都渋谷区〇〇 101号室」のような、私たちが普段使っている宛先。
- 物理アドレス(実際の部屋):マンションの「南棟の3階の、手前から4番目のドア」という、物理的に実在する具体的な場所。
プログラム(アプリ)は、「仮想アドレス」を使ってデータを読み書きします。しかし、CPUが実際にデータを届けるためには、それを具体的な「物理アドレス」に変換しなければなりません。
この「住所(仮想アドレス)から、実際の部屋(物理アドレス)への変換表」のことを、コンピュータの世界では「ページテーブル(Page Table)」と呼びます。
【通常のコンピュータ(非仮想化環境)】
[アプリの仮想アドレス] ──(ページテーブルで変換)──> [物理メモリの実アドレス]
これなら変換は1回だけで済むので、とてもシンプルですよね!
—
2. 仮想マシンの登場で「住所の変換」がカオスに!
では、ここに「仮想マシン(ゲストOS)」がやってくるとどうなるでしょうか?
ゲストOSは、自分が本物のコンピュータだと思い込んでいるので、自分の中に独自の「住所(ゲスト仮想アドレス)」と「実際の部屋(ゲスト物理アドレス)」の変換表を作ります。
しかし、ハイパーバイザー(大家さん)から見れば、ゲストOSが「ここが実際の部屋だ!」と思っている場所は、本物の物理メモリ(ホスト物理アドレス)ではありません。
つまり、以下のように2段階の変換が必要になってしまうのです。
1. ゲスト仮想アドレス(アプリが使う住所)
↓(ゲストOSのページテーブルで変換)
2. ゲスト物理アドレス(ゲストOSが「本物のメモリ」と信じ込んでいる中間の住所)
↓(ハイパーバイザーの管理表で変換)
3. ホスト物理アドレス(本物の物理メモリの場所)
【仮想化環境の二重変換】
[ゲスト仮想アドレス]
│ (ゲストOSが変換したい)
▼
[ゲスト物理アドレス]
│ (ハイパーバイザーが変換したい)
▼
[ホスト物理アドレス(本物のメモリ)]
CPUは、1段階の変換(ページテーブル)しか直接読むことができません。このままだと、CPUは本物の物理メモリにたどり着けず、迷子になってしまいます。
そこで登場するのが、今回の主役「シャドウページテーブル」です!
—
3. シャドウページテーブルは「特製の合体住所録」
ハイパーバイザーは、CPUが迷子にならないように、先ほどの2段階の変換をあらかじめガッチャンコした「特製の合体住所録」を裏で作っておきます。
これこそが「シャドウ(影)ページテーブル」です。
【シャドウページテーブルの役割】
[ゲスト仮想アドレス] ──(シャドウページテーブル)──> [ホスト物理アドレス(本物のメモリ)]
ゲストOSの知らないところで、ハイパーバイザーが「影」のように寄り添い、1発で本物の物理メモリまでたどり着ける表をCPUに渡してあげるのです。
これにより、CPUは二重変換の迷路に迷い込むことなく、超高速にメモリへアクセスできるようになります。「めでたしめでたし!」と言いたいところですが……ここで、ある大きな問題が発生します。
それが、今回のもう一つのテーマである「同期コスト(オーバーヘッド)」です。
—
4. なぜ重くなる?「同期コスト」の泥臭い舞台裏
ゲストOSは、メモリの中で新しいアプリが立ち上がったり、メモリが解放されたりするたびに、自分の「住所録(ゲストページテーブル)」を頻繁に書き換えます。
しかし、ゲストOSが勝手に住所録を書き換えても、ハイパーバイザーが作っている「合体住所録(シャドウページテーブル)」が更新されなければ、住所がズレてパケットやデータが届かなくなってしまいますよね。
そこで、ハイパーバイザーは以下のような泥臭い監視と同期を行います。
同期プロセスの流れ
1. 書き込み禁止にする
ハイパーバイザーは、ゲストOSが持っている住所録のメモリ領域をこっそり「書き込み禁止」に設定します。
2. ゲストOSが書き換えを試みる
ゲストOSが住所録を書き換えようとすると、書き込み禁止なので「エラー(ページフォールト)」が発生します。
3. ハイパーバイザーへの強制送還(VM-Exit)
エラーが発生した瞬間、CPUの制御がゲストOSからハイパーバイザーへと強制的に切り替わります。これをVM-Exitと呼びます。
4. ハイパーバイザーが代理で書き換える
ハイパーバイザーは「おっと、住所録を書き換えようとしたね?」と察知し、ゲストOSの書き込みを許可しつつ、自分側の「シャドウページテーブル」も全く同じ内容に同期します。
5. ゲストOSの処理を再開する(VM-Entry)
同期が終わったら、何事もなかったかのようにゲストOSに処理を戻します(VM-Entry)。
この一連のドタバタ劇を、現実世界で想像してみてください。
あなたがノート(ゲストページテーブル)に文字を書こうとするたびに、背後に立つ家庭教師(ハイパーバイザー)が「ちょっと待った!」とペンを奪い取り、自分のノート(シャドウページテーブル)に同じ内容を書き写してから「はい、続けていいよ」とペンを返してくるようなものです。
これでは、ノートに文字を書くスピードがガクンと落ちてしまいますよね。この割り込み処理(VM-Exit / VM-Entry)の多発こそが、シャドウページテーブルの「同期コスト(オーバーヘッド)」の正体なのです。
—
5. 現代の救世主:ハードウェアが助けてくれる「EPT / NPT」
「シャドウページテーブルの同期が重すぎる……」
この課題を解決するために、IntelやAMDといったCPUメーカーが立ち上がりました。CPUのハードウェア自体に、先ほどの「二重の変換」を自動で行う回路を組み込んでくれたのです。
- Intel製CPU:
EPT (Extended Page Tables) - AMD製CPU:
NPT (Nested Page Tables)またはRVI
これらは総称して「SLAT (Second Level Address Translation)」と呼ばれます。これに対応している現代のCPUでは、ハイパーバイザーが泥臭いシャドウページテーブルの同期をしなくても、CPUがハードウェアの力で一瞬にして「ゲスト仮想 ➔ ゲスト物理 ➔ ホスト物理」の変換を行ってくれます。
現在の設定を確認してみよう(Linux / KVMの例)
実務でLinuxサーバー(KVM)を構築する際、このハードウェア支援(EPT)が有効になっているかどうかを確認するコマンドをご紹介します。
お手元のLinuxターミナルで、以下のコマンドを実行してみてください。
# Intel製CPUでEPT(Extended Page Tables)が有効になっているか確認する
cat /sys/module/kvm_intel/parameters/ept
もし、実行結果として Y(または 1)が返ってくれば、重いシャドウページテーブルではなく、高速なハードウェア変換(EPT)が有効になっています!
Y
万が一、古い環境などで N になっている場合は、以下のようにカーネルモジュールのパラメータを設定して有効化します。
# /etc/modprobe.d/kvm.conf に設定を書き込む(なければ新規作成)
# ept=1 を指定することで、ハードウェア支援による高速なメモリ変換を強制します
sudo bash -c 'echo "options kvm_intel ept=1" >> /etc/modprobe.d/kvm.conf'
# 設定を反映させるため、モジュールを再読み込み(またはOS再起動)
sudo rmmod kvm_intel
sudo modprobe kvm_intel
*※注:実稼働中のプロダクション環境で rmmod を実行すると、起動中のVMが強制終了するので、必ずメンテナンス時間やテスト環境で実行してくださいね。*
また、仮想化ソフトウェアの定義ファイル(XML形式)などで
コメント