手当たり次第に書くんだ

飽きっぽいのは本能

VM の CPU / NUMA 設計 – vCPU pinning とメモリ配置を確認する

VM の CPU 性能は、vCPU 数だけでは決まりません。vCPU thread がどのホスト CPU で実行されるか、ゲストメモリがどの NUMA node から割り当てられるか、QEMU の emulator thread や I/O thread がどこで動くかによって、同じ vCPU 数でも待ち時間と揺らぎが変わります。

この記事では KVM / libvirt を前提に、CPU topology の確認、vCPU pinning、emulatorpinnumatune、HugePages、IRQ と I/O thread の配置を対応付けます。pinning は常に性能を上げる設定ではなく、共有資源を専有に近づける代わりに柔軟性を減らす設計です。

vCPU、ホスト CPU、補助 thread を分ける

要素実体設計時に決めること
vCPUゲストへ見せる仮想 CPU個数、topology、ホスト CPU への affinity
ホスト CPUsocket、core、SMT thread同じ core の sibling と NUMA node
emulator threadQEMU のデバイス・管理処理vCPU と分ける CPU 範囲
I/O thread仮想ディスクなどの I/O 処理対象デバイスと CPU affinity
IRQ / softirqNIC やストレージの割り込み処理dataplane CPU と競合させるか
ゲストメモリVM が使うホストメモリNUMA node、page size、予約方法

libvirt の vcpupin は vCPU ごとの affinity、emulatorpin は QEMU emulator thread の affinity を指定します。vCPU だけを固定しても、補助 thread や IRQ が同じ CPU で競合すると、tail latency が不安定になることがあります。

pinning を使う条件

状況pinning の判断理由
低遅延、NFV、高 packet rate候補になるスケジューリング待ちと実行場所の変動を抑えたい
性能保証が必要な専有 VM候補になる他 VM との CPU 競合範囲を限定したい
一般的な業務 VM測定して判断するscheduler の柔軟な共有が有利な場合がある
高い CPU overcommit が前提固定範囲を慎重に決める固定先が混雑すると空いている CPU を使えない
ライブマイグレーションを頻繁に使う移行先も含めて設計するCPU ID と topology がホストごとに異なる可能性がある

pinning の目的は平均 CPU 使用率を下げることではありません。run queue、steal、vCPU wait、p95 / p99 latency、packet drop など、改善したい指標を先に決めます。

ホストの CPU topology と NUMA を確認する

CPU 番号だけを見て固定先を決めず、socket、core、SMT sibling、NUMA node の対応を確認します。SMT sibling を別々の専有コアとして数えると、同じ物理 core の実行資源を競合させる可能性があります。

lscpu -e=CPU,NODE,SOCKET,CORE,ONLINE
lscpu
numactl --hardware
virsh nodeinfo
virsh capabilities
lspci -tv
cat /proc/interrupts
  • 対象 CPU がどの socket、core、NUMA node に属するか
  • SMT sibling を同じ VM に渡すか、housekeeping 用に残すか
  • NIC、NVMe、HBA がどの NUMA node に近いか
  • ホスト OS、libvirt、QEMU、IRQ、監視用に使う CPU を残しているか
  • 他 VM と固定 CPU が重複していないか

VM の現在の affinity を確認する

設定 XML と実行中の affinity を分けて確認します。永続設定だけ変更した場合は次回起動まで反映されず、live 設定だけ変更した場合は再起動後に戻る可能性があります。

virsh vcpuinfo vm01
virsh vcpupin vm01
virsh emulatorpin vm01
virsh numatune vm01
virsh domstats vm01 --cpu-total --vcpu --memory
virsh dumpxml vm01

virsh vcpupin は vCPU ごとの許可 CPU、virsh emulatorpin は emulator thread、virsh numatune は NUMA memory policy を確認します。実際にどの CPU で実行されたかは、ホストのプロセス・thread 統計や負荷計測も合わせて見ます。

libvirt XML で vCPU と emulator を分ける

次は 2 vCPU の VM を、同じ NUMA node に属するホスト CPU 2 と 3 へ固定し、emulator thread を CPU 0 と 1 へ分ける例です。CPU ID は例なので、実際の topology と予約方針に合わせて変更します。

<vcpu placement='static'>2</vcpu>
<cputune>
  <vcpupin vcpu='0' cpuset='2'/>
  <vcpupin vcpu='1' cpuset='3'/>
  <emulatorpin cpuset='0-1'/>
</cputune>
<numatune>
  <memory mode='strict' nodeset='0'/>
</numatune>

strict は指定 node 以外からのメモリ割り当てを許可しないため、対象 node の空きメモリが不足すると VM を起動できない可能性があります。可用性を優先する場合は、preferred や他の memory policy を含めて判断します。

QEMU では、vcpupinemulatorpin は emulator 起動後に適用されます。起動の初期段階では、指定外 CPU の使用が統計に現れる可能性があります。

NUMA memory policy と実メモリ配置を確認する

NUMA では、CPU が属する node に近いメモリを使う方が、一般に遅延と帯域の面で有利です。ただし、CPU affinity だけではゲストメモリの node を保証しません。libvirt の numatune とホストの cpuset 制約、空きメモリを合わせて確認します。

numastat
numastat -c
virsh numatune vm01
virsh dommemstat vm01
grep -i huge /proc/meminfo

Linux の NUMA 統計では、numa_hitnuma_missnuma_foreignlocal_nodeother_node などを確認できます。単一の値だけで判断せず、ワークロード実行中の増加量と CPU affinity を対応付けます。

HugePages は node 配置と予約量を一緒に見る

HugePages は TLB miss を減らす手段ですが、有効にするだけで正しい NUMA node へ配置されるわけではありません。page size、node ごとの予約量、VM のメモリ量、起動順序、他 VM との競合を確認します。

確認項目判断
page size2 MiB または 1 GiB を CPU とワークロードの要件から選ぶ
node ごとの予約vCPU を置く node に必要量が確保されているか
起動失敗strict policy と空き HugePages の不足を確認する
Transparent HugePages明示的 HugePages と同じ効果を前提にせず測定する
ロックメモリDPDK や VFIO を使う場合の制限と権限を確認する

IRQ、I/O thread、デバイスの NUMA node を確認する

SR-IOV、PCI Passthrough、vhost-user、DPDK では、vCPU とメモリだけでなく、NIC、VF、PMD thread、vhost thread、IRQ の配置が影響します。デバイスが node 1 にあるのに VM の vCPU とメモリを node 0 へ固定すると、I/O が NUMA interconnect をまたぐ可能性があります。

  • PCIe デバイスと NUMA node の対応
  • IRQ affinity と irqbalance の方針
  • QEMU emulator thread と I/O thread の CPU
  • vhost、OVS-DPDK、PMD thread の CPU
  • VM の vCPU とメモリがデバイスに近い node にあるか

適用前後を同じ条件で比較する

段階実施すること
1変更前の vcpupin、emulatorpin、numatune、CPU topology を保存する
2同じワークロードで throughput、p95 / p99、CPU wait、drop を測定する
3vCPU、emulator、memory policy を一つずつ変更する
4ホストとゲストの両方で再測定する
5性能、可搬性、障害復旧、他 VM への影響を評価する
6改善しない場合は設定を戻し、別のボトルネックを確認する

よくある失敗

失敗問題確認すること
vCPU だけを固定するemulator、I/O、IRQ が同じ CPU で競合する補助 thread と housekeeping CPU
CPU ID を別ホストへそのまま移すtopology と NUMA node が一致しない移行先ごとの CPU map
全 CPU を VM へ渡すホスト処理の実行場所が不足するOS、QEMU、IRQ 用の予約 CPU
HugePages だけを有効にするNUMA memory policy が未設定node ごとの予約量と numatune
live 設定だけ変更する再起動後に元へ戻るlive と config の両方
平均値だけを見るtail latency と jitter の悪化を見落とす分位点、drop、再送、待ち時間

まとめ

VM の CPU / NUMA 設計では、vCPU、ホスト CPU、emulator thread、I/O thread、IRQ、ゲストメモリ、PCIe デバイスを同じ topology 上で対応付けます。CPU pinning は実行場所を限定できますが、共有の柔軟性と移行性を減らします。

最初に host topology と現在の affinity を記録し、改善したい指標を測定します。その後で vcpupinemulatorpinnumatune、HugePages を一つずつ変更し、性能だけでなくホスト余力、他 VM、障害復旧への影響まで再評価します。

関連する記事
VM の CPU / NUMA 設計 – vCPU pinning とメモリ配置を確認する

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る