13.2. 解決方法
このセクションを使用して、エミュレーターのスレッドの固定を調査および設定します。
13.2.1. qemu-kvm エミュレータースレッド
エミュレータースレッドは、仮想マシンのハードウェアエミュレーションの割り込み要求およびノンブロッキングプロセスを処理します。vCPU を実行していないスレッドは、qemu-kvm
エミュレータースレッドです。以下の例を参照してください。
[root@overcloud-compute-0 ~]# ps -Tp `pgrep -f instance-00000009` PID SPID TTY TIME CMD 364936 364936 ? 00:00:02 qemu-kvm 364936 364946 ? 00:00:00 qemu-kvm 364936 364952 ? 00:00:52 CPU 0/KVM 364936 364953 ? 00:00:26 CPU 1/KVM 364936 364954 ? 00:00:30 CPU 2/KVM 364936 364956 ? 00:00:00 vnc_worker
Linux CFS (完全に公平なスケジューラー) により、エミュレータースレッドは通常、libvirt のエミュレーターピンセットで定義されている範囲内で、ある pCPU から別の pCPU に定期的に移動します。
NFV コンテキストでは、isolcpus
パラメーターを使用するときにエミュレータースレッドを設定すると、問題が発生する可能性があります。これは、このカーネル設定により、これらの CPU での CFS スケジューリングが無効になるためです。isolcpus parameter
を使用していない場合、エミュレータースレッドがパケットを処理している CPU に割り込むと、パケット損失が発生する可能性があります。
エミュレータースレッドの例は次のとおりです。
- qemu-kvm スレッド
- vnc_worker スレッド
- vhost-<qemu-kvm PID> カーネルスレッド (virtio-net が使用されている場合 (ハイパーバイザー上のカーネルネットワーク))
13.2.2. エミュレータースレッドの固定化に関するデフォルトの動作
デフォルトでは、nova はすべての vCPU に割り当てられた pCPU にまたがるエミュレータースレッドピンセットを設定します。isolcpus
パラメーターを使用していない場合、エミュレータースレッドは任意の pCPU でスケジュールでき、ある pCPU から別の pCPU に定期的に移動します。
virsh dumpxml instance-0000001d (...) <vcpu placement='static'>4</vcpu> <cputune> <shares>4096</shares> <vcpupin vcpu='0' cpuset='34'/> <vcpupin vcpu='1' cpuset='14'/> <vcpupin vcpu='2' cpuset='10'/> <vcpupin vcpu='3' cpuset='30'/> <emulatorpin cpuset='10,14,30,34'/> </cputune> (...)
[root@overcloud-compute-0 ~]# virsh dumpxml instance-00000009 (...) <nova:vcpus>3</nova:vcpus> <vcpu placement='static'>3</vcpu> <vcpupin vcpu='0' cpuset='1'/> <vcpupin vcpu='1' cpuset='2'/> <vcpupin vcpu='2' cpuset='3'/> (...) <emulatorpin cpuset='1-3'/> (...)
したがって、これらの CPU はいずれも、qemu のエミュレータースレッドによってプリエンプションが実行され、パケットドロップのリスクがあります。
エミュレータースレッドの固定化に関する新機能の現在の進捗状況の詳細は、Bug 1468004 および OpenStack Change 510897 を参照してください。
この記事の執筆時点で、ドラフトは次のスレッドポリシーを指定しました。
Valid THREAD-POLICY values are: - ``share``: (default) The emulator threads float across the pCPUs associated to the guest. To place a workload's emulator threads on a set of isolated physical CPUs, set ``share``` and ``[compute]/cpu_shared_set`` configuration option to the set of host CPUs that should be used for best-effort CPU resources. - ``isolate``: The emulator threads are isolated on a single pCPU.
13.2.3. エミュレータースレッドのスケジューリングに対する isolcpus の影響
isolcpus を使用すると、CFS スケジューラーが無効になり、すべてのエミュレータースレッドが最初に使用可能な最もインデックスの少ない pCPU で実行されます。結果として、介入や追加の設定を行わないと、インスタンスの 1 つの vCPU が、エミュレータースレッドとのリソース競合のリスクが高くなります。
詳細は、Kernel.org Bugzilla – Bug 116701 を参照してください。
次のアルゴリズムを使用して、エミュレータースレッドが使用している vCPU を判別します。
PCPU=MIN([EMULATORPINSET]) VCPU=REVERSE_CPUSET(PCPU) REVERSE_CPUSET := SELECT pcpu from `virsh dumpxml <instance name> | grep "cpuset=$PCPU"`
たとえば、この場合、すべてのエミュレータースレッドと子は、デフォルトのエミュレーターピンセットからアフィニティー 1〜3 を継承します。
[root@overcloud-compute-0 ~]# taskset -a -c -p `pgrep -f instance-00000009` pid 364936's current affinity list: 1-3 pid 364946's current affinity list: 1-3 pid 364952's current affinity list: 1 pid 364953's current affinity list: 2 pid 364954's current affinity list: 3 pid 364956's current affinity list: 1-3 [root@overcloud-compute-0 ~]# ps -Tp `pgrep -f instance-00000009` PID SPID TTY TIME CMD 364936 364936 ? 00:00:02 qemu-kvm 364936 364946 ? 00:00:00 qemu-kvm 364936 364952 ? 00:00:51 CPU 0/KVM 364936 364953 ? 00:00:26 CPU 1/KVM 364936 364954 ? 00:00:30 CPU 2/KVM 364936 364956 ? 00:00:00 vnc_worker [root@overcloud-compute-0 ~]# pgrep -f vhost- | xargs -I {} taskset -a -c -p {} pid 364948's current affinity list: 1-3 pid 364949's current affinity list: 1-3 pid 364950's current affinity list: 1-3 [root@overcloud-compute-0 ~]#
isolcpus と組み合わせると、すべてのエミュレータースレッドと vhost- *スレッドが pCPU1 で実行され、再スケジュールされることはありません。
cat /proc/sched_debug | sed '/^cpu#/,/^runnable/{//!d}' | grep vhost -C3 (...) cpu#1, 2099.998 MHz runnable tasks: task PID tree-key switches prio wait-time sum-exec sum-sleep ---------------------------------------------------------------------------------------------------------- watchdog/1 11 -2.995579 410285 0 0.000000 5025.887998 0.000000 0 / migration/1 12 0.000000 79 0 0.000000 3.375060 0.000000 0 / ksoftirqd/1 13 5172444.259776 54 120 0.000000 0.570500 0.000000 0 / kworker/1:0 14 5188475.472257 370 120 0.000000 14.707114 0.000000 0 / kworker/1:0H 15 8360.049510 10 100 0.000000 0.150151 0.000000 0 / kworker/1:1 2707 5045807.055876 16370 120 0.000000 793.611916 0.000000 0 / kworker/1:1H 2763 5187682.987749 11755 100 0.000000 191.949725 0.000000 0 / qemu-kvm 364936 3419.522791 50276 120 0.000000 2476.880384 0.000000 0 /machine.slice/machine-qemu\x2d6\x2dinstance\x2d00000009.scope/emulator qemu-kvm 364946 1270.815296 102 120 0.000000 23.204111 0.000000 0 /machine.slice/machine-qemu\x2d6\x2dinstance\x2d00000009.scope/emulator CPU 0/KVM 364952 52703.660314 53709 120 0.000000 52715.105472 0.000000 0 /machine.slice/machine-qemu\x2d6\x2dinstance\x2d00000009.scope/vcpu0 vnc_worker 364956 123.609634 1 120 0.000000 0.016849 0.000000 0 /machine.slice/machine-qemu\x2d6\x2dinstance\x2d00000009.scope/emulator vhost-364936 364948 3410.527677 1039 120 0.000000 84.254772 0.000000 0 /machine.slice/machine-qemu\x2d6\x2dinstance\x2d00000009.scope/emulator vhost-364936 364949 3407.341502 55 120 0.000000 2.894394 0.000000 0 /machine.slice/machine-qemu\x2d6\x2dinstance\x2d00000009.scope/emulator vhost-364936 364950 3410.395220 174 120 0.000000 10.969077 0.000000 0 /machine.slice/machine-qemu\x2d6\x2dinstance\x2d00000009.scope/emulator cpu#2, 2099.998 MHz runnable tasks: task PID tree-key switches prio wait-time sum-exec sum-sleep ---------------------------------------------------------------------------------------------------------- watchdog/2 16 -5.995418 410285 0 0.000000 5197.571153 0.000000 0 / migration/2 17 0.000000 79 0 0.000000 3.384688 0.000000 0 / ksoftirqd/2 18 -7.031102 3 120 0.000000 0.019079 0.000000 0 / kworker/2:0 19 0.119413 39 120 0.000000 0.588589 0.000000 0 / kworker/2:0H 20 -1.047613 8 100 0.000000 0.086272 0.000000 0 / kworker/2:1 2734 1475469.236026 11322 120 0.000000 241.388582 0.000000 0 / CPU 1/KVM 364953 27258.370583 33294 120 0.000000 27269.017017 0.000000 0 /machine.slice/machine-qemu\x2d6\x2dinstance\x2d00000009.scope/vcpu1 cpu#3, 2099.998 MHz runnable tasks: task PID tree-key switches prio wait-time sum-exec sum-sleep ---------------------------------------------------------------------------------------------------------- watchdog/3 21 -5.996592 410285 0 0.000000 4970.777439 0.000000 0 / migration/3 22 0.000000 79 0 0.000000 3.886799 0.000000 0 / ksoftirqd/3 23 -7.035295 3 120 0.000000 0.014677 0.000000 0 / kworker/3:0 24 17.758583 38 120 0.000000 0.637152 0.000000 0 / kworker/3:0H 25 -1.047727 8 100 0.000000 0.077141 0.000000 0 / kworker/3:1 362530 154177.523420 83 120 0.000000 6.544285 0.000000 0 / CPU 2/KVM 364954 32456.061889 25966 120 0.000000 32466.719084 0.000000 0 /machine.slice/machine-qemu\x2d6\x2dinstance\x2d00000009.scope/vcpu2
13.2.4. エミュレータースレッドの最適な位置
このセクションでは、エミュレータースレッドを次のネットワークに配置する方法について説明します。
- インスタンス内の DPDK ネットワーキングと Open vSwitch の netdev データパス
- インスタンス内の DPDK ネットワーキング、Open vSwitch のシステムデータパス、ハイパーバイザーのカーネルスペースネットワーキング
- Open vSwitch のインスタンス内カーネルネットワーキングと netdev データパス
13.2.4.1. Open vSwitch のインスタンスと netdev データパス内の DPDK ネットワーキングによるエミュレータースレッドの最適な配置
DPDK がインスタンス内で実行される場合、パケット処理は完全にユーザー空間で実行されます。PMD を vCPU0 で実行するようにスケジュールしないでください。これは、OS と割り込み処理のために残しておく必要があります。インスタンス内の PMD CPU はアクティブループを実行し、CPU の 100% を必要とするため、プリエンプトしないでください。これらの vCPU のいずれかがプリエンプトされると、パケット損失が発生する可能性があります。したがって、emulatorpin cpuset は、1 以上の番号が付けられた仮想 CPU を処理する物理 CPU とオーバーラップしないように設定する必要があります。
インスタンス内の DPDK ネットワーキングでは、エミュレータースレッドの最適な場所は、vCPU 0 を処理する pCPU か、仮想 CPU をまったく処理しない専用の物理 CPU のいずれかです。
OVS-DPDK がハイパーバイザーとインスタンス内の DPDK で使用されている場合は、エミュレータースレッドを vCPU0 に配置します。
13.2.4.2. Open vSwitch における DPDK ネットワーキングを用いたエミュレータースレッドのインスタンスおよびシステムデータパス内への最適配置
ハイパーバイザーでカーネルスペースネットワーキングが使用されている場合、ハイパーバイザーでのパケット処理はカーネル内で実行されます。
インスタンス内の DPDK ネットワーキングでは、エミュレータースレッドの最適な場所は、vCPU 0 を処理する pCPU か、仮想 CPU を処理しない専用の物理 CPU のいずれかです。
このシナリオでは、vNIC キューのパケット処理は、ハイパーバイザーの vhost-<qemu-kvm PID>
カーネルスレッド内で実行されることに注意してください。トラフィックが多い場合、これらのカーネルスレッドはかなりの CPU 負荷を発生させる可能性があります。エミュレータースレッドの最適な場所は、ケースバイケースで決定する必要があります。
[root@overcloud-compute-0 ~]# ps aux | grep vhost- root 364948 0.0 0.0 0 0 ? S 20:32 0:00 [vhost-364936] root 364949 0.0 0.0 0 0 ? S 20:32 0:00 [vhost-364936] root 364950 0.0 0.0 0 0 ? S 20:32 0:00 [vhost-364936]
13.2.4.3. Open vSwitch のインスタンスと netdev データパス内でのカーネルネットワーキングを利用したエミュレータースレッドの最適な配置
インスタンス内のカーネルネットワークでは、2 つのオプションがあります。
- インスタンス内の softirqs など、割り込み分散を最適化します。このような場合、エミュレータースレッドに追加の pCPU を割り当てる必要はなく、ネットワーク割り込みを処理していない pCPU にエミュレータースレッドを割り当てることができます。
- エミュレータースレッド用に同じ NUMA ノードで専用の pCPU を使用します。
最初のオプションは複雑であるため、2 番目のオプションをお勧めします。