8.3. KSM (Kernel Same-page Merging)

KVM ハイパーバイザーが使用する Kernel same-page Merging (KSM) により、KVM ゲストは同一メモリーページを共有することが可能になります。このような共有ページは通常、共通のライブラリーか、使用頻度の高い同一データです。KSM はメモリー重複を防ぐことで同一または類似のゲストオペレーティングシステムのゲストの密度を高めることができます。
最近のオペレーティングシステムでは共有メモリーという概念が一般的になってきました。たとえば、プログラムが初めて起動する際に、そのプログラムはその親プログラムとすべてのメモリーを共有します。子プログラムまたは親プログラムのいずれかがメモリーの変更を試行すると、カーネルによって新しいメモリー領域が割り当てられ、元のコンテンツがコピーされます。これにより、プログラムがこの新たな範囲を変更できるようになります。これはコピーオンライト (copy on write) と呼ばれます。
KSM はこの概念を逆方向で用いる Linux の機能になります。カーネルにすでに実行中の複数のプログラムを検査させ、メモリーの比較を行います。そのメモリーの範囲またはページが同一の場合は、その複数存在している同じメモリーページを 1 つのページに減らします。このページにコピーオンライトのマークが付けられます。ページの内容がゲスト仮想マシンによって変更される場合は、そのゲスト用に新しいページが作成されます。
KSM は KVM を使った仮想化に便利です。ゲスト仮想マシンの起動時点では、ホストの qemu-kvm プロセスからのメモリーしか継承しません。同じオペレーティングシステムやアプリケーションを複数のゲストが実行している場合、ゲストの実行時にゲストのオペレーティングシステムイメージのコンテンツが共有されるようになります。KSM の機能によって KVM は同一ゲストのメモリー領域が共有されるよう要求することができるようになります。
KSM によってメモリーの速度やその用途が広がります。KSM を使用すると、共通の処理データはキャッシュやメインメモリーに格納されます。これにより KVM ゲストのキャッシュミスが低減されるため、一部のアプリケーションやオペレーティングシステムのパフォーマンスを向上させることができます。また、メモリーを共有することによりゲストの全体的なメモリー使用を抑えるため、より多くのリソースを有効に活用できるようになります。

注記

Red Hat Enterprise Linux 7 より、KSM は NUMA 対応になりました。これにより、ページコアレッシングの実行時に NUMA ローカリティーが考慮されることになり、リモートノードに移行されるページに関連するパフォーマンスの低下を防ぐことができるようになります。Red Hat は、KSM の使用時にはノード間のメモリーマージを控えることを推奨します。KSM が使用中の場合には、/sys/kernel/mm/ksm/merge_across_nodes 調整可能パラメーターを 0 に変更し、複数の NUMA ノード間でのページのマージを防ぎます。これは、virsh node-memory-tune --shm-merge-across-nodes 0 コマンドを使って実行できます。多量のノード間マージが実行されると、カーネルメモリーのアカウンティング統計は相反する結果となる可能性があります。そのため、numad も KSM デーモンが多量のメモリーをマージした後に混乱する可能性があります。システムに大量の空きメモリーがある場合、KSM デーモンをオフにし、無効にすることでパフォーマンスを向上させることができます。NUMA の詳細は、「9章NUMA」を参照してください。

重要

KSM を考えに含めなくてもコミットする RAM に対して swap サイズが十分であることを確認してください。KSM は同一または類似ゲストの RAM 使用量を低減します。十分なスワップ領域がなくても KSM を使ってゲストをオーバーコミットすることはおそらく可能ですが、ゲスト仮想マシンのメモリー使用によってページが共有されなくなる可能性があるため推奨されません。
Red Hat Enterprise Linux では、KSM の管理に以下の 2 種類の方法を使用しています。
  • ksm サービス は、KSM カーネルスレッドの起動と停止を行います。
  • ksmtuned サービス は、ksm サービスの制御と調整を行い、same-page merging を動的に管理します。ksmtunedksm サービスを起動し、メモリー共有が必要ない場合には ksm サービスを停止します。新規のゲストが作成された場合またはゲストが破棄された場合には、retune パラメーターで ksmtuned に実行の指示を出さなければなりません。
いずれのサービスも標準のサービス管理ツールで制御されます。

注記

Red Hat Enterprise Linux 6.7 では、KSM はデフォルトで無効になっています。

8.3.1. KSM サービス

  • ksm サービスは qemu-kvm パッケージに含まれています。
  • ksm サービスを起動していない場合、Kernel same-page merging (KSM) により 2000 ページしか共有されません。このデフォルト値では、メモリー節約で得られる利点が限られます。
  • ksm サービスを起動すると、KSM により最大でホストシステムのメインメモリーの 50% まで共有されるようになります。ksm サービスを起動して KSM がより多くのメモリーを共有できるようにしてください。
# systemctl start ksm
Starting ksm:                                              [  OK  ]
ksm サービスをデフォルトのスタートアップ順序に追加することができます。systemctl コマンドを使って ksm サービスを永続化します。
# systemctl enable ksm

8.3.2. KSM チューニングサービス

ksmtuned サービスは、ksm をループおよび調整して kernel same-page merging (KSM) の設定を微調整します。また、ゲスト仮想マシンが作成または破棄された場合は、そのことが libvirt によって ksmtuned サービスに通知されます。ksmtuned サービスにオプションはありません。
# systemctl start ksmtuned
Starting ksmtuned:                                         [  OK  ]
ksmtuned サービスは retune パラメーターを使って調整することができます。パラメーターの指示によって ksmtuned は手動によるチューニング機能を実行します。
/etc/ksmtuned.conf ファイルは ksmtuned サービスの設定ファイルになります。デフォルトの ksmtuned.conf ファイルの出力を以下に示します。
# Configuration file for ksmtuned.
# How long ksmtuned should sleep between tuning adjustments
# KSM_MONITOR_INTERVAL=60

# Millisecond sleep between ksm scans for 16Gb server.
# Smaller servers sleep more, bigger sleep less.
# KSM_SLEEP_MSEC=10

# KSM_NPAGES_BOOST - is added to the `npages` value, when `free memory` is less than `thres`.
# KSM_NPAGES_BOOST=300

# KSM_NPAGES_DECAY - is the value given is subtracted to the `npages` value, when `free memory` is greater than `thres`.
# KSM_NPAGES_DECAY=-50

# KSM_NPAGES_MIN - is the lower limit for the `npages` value.
# KSM_NPAGES_MIN=64

# KSM_NPAGES_MAX - is the upper limit for the `npages` value.
# KSM_NPAGES_MAX=1250

# KSM_THRES_COEF - is the RAM percentage to be calculated in parameter `thres`.
# KSM_THRES_COEF=20

# KSM_THRES_CONST - If this is a low memory system, and the `thres` value is less than `KSM_THRES_CONST`, then reset `thres` value to `KSM_THRES_CONST` value.
# KSM_THRES_CONST=2048

# uncomment the following to enable ksmtuned debug information
# LOGFILE=/var/log/ksmtuned
# DEBUG=1
/etc/ksmtuned.conf ファイルの npages により、ksmd デーモンが非アクティブになるまでに ksm がスキャンするページ数が設定されます。この値は、/sys/kernel/mm/ksm/pages_to_scan ファイルでも設定されます。
KSM_THRES_CONST の値は、ksm をアクティブ化する際のしきい値として使われる、利用可能なメモリー容量を表します。以下のいずれかの状況になった場合に、ksmd がアクティブ化されます。
  • 空きメモリー容量が KSM_THRES_CONST で設定されたしきい値を下回った場合
  • コミットしたメモリー容量と KSM_THRES_CONST のしきい値の合計が、総メモリー容量を超えた場合

8.3.3. KSM の変数とモニタリング

Kernel same-page merging (KSM) はモニタリングデータを /sys/kernel/mm/ksm/ ディレクトリーに格納します。このディレクトリー内のファイルはカーネルによって更新されるため、KSM の使用状況と統計値の正確な記録となります。
上述のように、以下に示す変数は /etc/ksmtuned.conf ファイルでも設定可能です。

/sys/kernel/mm/ksm/ に含まれるファイル:

full_scans
実行された完全スキャン数
merge_across_nodes
異なる NUMA ノードからページをマージできるかどうかを指定します。
pages_shared
共有されたページの合計数
pages_sharing
現在共有されているページ数
pages_to_scan
スキャンされなかったページ数
pages_unshared
共有されなくなったページ数
pages_volatile
揮発性のページ数
run
KSM プロセスが実行しているかどうか
sleep_millisecs
スリープのミリ秒数
これらの変数は virsh node-memory-tune コマンドを使用して手動で調整できます。たとえば、共有メモリーサービスがスリープ状態になる前にスキャンするページの数を指定します。
# virsh node-memory-tune --shm-pages-to-scan number
/etc/ksmtuned.conf ファイルに DEBUG=1 の行を追加すると、KSM チューニングのアクティビティーが /var/log/ksmtuned ログファイルに格納されます。LOGFILE パラメーターを使用するとログファイルの場所を変更することができます。ただし、ログファイルの場所の変更は、SELinux 設定に特殊な構成を必要とする場合があるためお勧めできません。

8.3.4. KSM の非アクティブ化

Kernel same-page merging (KSM) にはパフォーマンス上のオーバーヘッドがあり、特定の環境やホストシステムには負荷が大きすぎる場合があります。また、KSM はサイドチャネルを生成する恐れがあり、ゲスト間に情報を漏洩するために使用される可能性があります。これが懸念される場合には、ゲストごとに KSM を無効にすることができます。
ksmtunedksm サービスを停止して、KSM を非アクティブ化することができます。ただし、再起動後は元に戻ります。KSM を非アクティブ化するには、ターミナルから root として以下のコマンドを実行します。
# systemctl stop ksmtuned
Stopping ksmtuned:                                         [  OK  ]
# systemctl stop ksm
Stopping ksm:                                              [  OK  ]
ksmtunedksm を停止すると KSM は非アクティブ化されますが、再起動後は元に戻ります。KSM を完全に非アクティブ化するには、systemctl コマンドを使用します。
# systemctl disable ksm
# systemctl disable ksmtuned
KSM を無効にする場合、KSM を非アクティブ化する前に共有されていたすべてのメモリーページは、引き続き共有されます。システムからすべての PageKSM を削除するには、以下のコマンドを使用します。
# echo 2 >/sys/kernel/mm/ksm/run
これを実施した後に、khugepaged デーモンは KVM ゲストの物理メモリーに Transparent Hugepage を再ビルドできます。# echo 0 >/sys/kernel/mm/ksm/run を使用すると、KSM は停止しますが、以前に作成されたすべての KSM ページは共有されたままです (これは # systemctl stop ksmtuned コマンドと同じです)。