めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

RHEL7/CentOS7のLinux KVMリソース割り当て機能

RHEL7/CentOS7では、virshコマンドから仮想マシンに対するリソース割り当てを制御できるようになっていますので、そのあたりを説明します。

CPU Pinning

仮想マシンに割り当てた仮想CPUごとに、その仮想CPUが使用する物理コア(その仮想CPUの処理に割り当てられる物理コア)を制限することができます。

たとえば、物理4コアの環境で、仮想CPUを2個割り当てた仮想マシン「vm01」を作成します。デフォルトでは、すべての仮想CPUは、すべての物理コアを使用することができます。

# virsh vcpuinfo vm01
VCPU:           0
CPU:            0
状態:         実行中
CPU 時間:     24.2s
CPU アフィニティー: yyyy

VCPU:           1
CPU:            3
状態:         実行中
CPU 時間:     5.8s
CPU アフィニティー: yyyy

上記の「CPUアフィニティー」が、4個の物理コアに対する使用許可を「y(yes)」「-(no)」で示しています。「CPU」は上記のコマンドを実行したタイミングで、仮想CPUに割り当てられていた物理コアの番号を示します。どの物理コアを使用するかは、ホストLinuxのスケジューラーが動的に選択します。

ここで、「仮想CPU0」「仮想CPU1」のそれぞれに対して使用する物理コアを「0〜1」に制限すると、次のようになります。

# virsh vcpupin vm01 0 0-1
# virsh vcpupin vm01 1 0-1

# virsh vcpuinfo vm01
VCPU:           0
CPU:            1
状態:         実行中
CPU 時間:     24.5s
CPU アフィニティー: yy--

VCPU:           1
CPU:            0
状態:         実行中
CPU 時間:     6.1s
CPU アフィニティー: yy--

CPU shares

複数の仮想マシンの仮想CPUに対して、同一の物理コアが割り当てられた場合、どちらの仮想CPUに優先的に処理時間を割り当てるかを設定します。それぞれの仮想マシンに「cpu_shares」の値が設定されており、この値の比率でCPU時間が配分されます。

# virsh schedinfo vm01
スケジューラー: posix
cpu_shares     : 1024
vcpu_period    : 100000
vcpu_quota     : -1
emulator_period: 100000
emulator_quota : -1

上記の「cpu_shares」がこれに当たります。デフォルトでは、すべての仮想マシンに「1024」が設定されています。たとえば、これを「2048」に変更すると、他の仮想マシンと物理コアが競合した場合、他の仮想マシンの2倍の処理時間が割り当てられるようになります。

# virsh schedinfo vm01 --set cpu_shares=2048
スケジューラー: posix
cpu_shares     : 2048
vcpu_period    : 100000
vcpu_quota     : -1
emulator_period: 100000
emulator_quota : -1

CPU quota

仮想マシンに対するCPU処理時間の割り当てについて、上限を設定します。「period(μsec)」と「quota(μsec)」を設定すると、periodの期間中にCPU割り当ての総時間がquotaに達すると、(periodの期間が終わるまでは)それ以上はCPU処理時間が割り当てられなくなります。

複数の仮想CPUを持つ場合は、それぞれの仮想CPUの時間が合計されるので、「period < quota」に設定する場合もあり得ます。次は、仮想CPUが2個の場合の例です。

・period=100000, quota=200000 ⇒ 2個の仮想CPUは常にCPU処理時間を割り当てられる(物理コアが空いている場合。)
・period=100000, quota=100000 ⇒ 2個の仮想CPUに対して、トータルとして、1物理コア分の処理時間が割り当てられる。

次は、実際に「period」と「quota」を設定する例です。

# virsh schedinfo vm01 --set vcpu_period=50000 vcpu_quota=50000
スケジューラー: posix
cpu_shares     : 2048
vcpu_period    : 50000
vcpu_quota     : 50000
emulator_period: 100000
emulator_quota : -1

制限をかけない場合は、「vcpu_quota」に「-1」を設定します。

IO tuning

仮想ディスクに対するIO性能の上限を設定します。スループット(MB/sec)、もしくは、IOPS(IO/sec)で設定します。IOPSは、一回のIOで転送するデータ量が少ない場合は、スループットは小さいけれどもIO回数が多くなります。このような際に、IO回数で上限をセットするためにIOPSを用います。次は、仮想ディスク「vda」に対する設定の確認例です。

# virsh blkdeviotune vm01 vda
total_bytes_sec: 0
read_bytes_sec : 0
write_bytes_sec: 0
total_iops_sec : 0
read_iops_sec  : 0
write_iops_sec : 0

スループット(bytes_sec)とIOPS(iops_sec)それぞれについて、Read/Write/Totalでの上限が設定できます。デフォルト値の「0」は制限無しの意味になります。次は、書き込みのスループットを 50MB/sec に設定する例です。

# virsh blkdeviotune vm01 --write_bytes_sec $((50*1024*1024)) vda
# virsh blkdeviotune vm01 vda
total_bytes_sec: 0
read_bytes_sec : 0
write_bytes_sec: 52428800
total_iops_sec : 0
read_iops_sec  : 0
write_iops_sec : 0

ちなみに、仮想マシンに接続された仮想ディスクは、次のコマンドで一覧表示できます。

# virsh domblklist vm01
ターゲット ソース
------------------------------------------------
vda        /var/lib/libvirt/images/pool01/vm01-vol01.qcow2

ネットワークトラフィックのシェーピング

仮想NICを出入りするパケットのシェーピングを行います。次のように仮想NICのMACアドレスを指定して、パラメータを取得・設定します。

# virsh domiftune vm01 52:54:00:d0:9a:df
inbound.average: 0
inbound.peak   : 0
inbound.burst  : 0
outbound.average: 0
outbound.peak  : 0
outbound.burst : 0

入力(inbound)と出力(outbound)について、「peak(KB/sec)」「burst(KB)」「average(KB/sec)」を設定します。

大量のトラフィックが流れた場合、スループットがpeak(KB/sec)の値で抑えられて、さらにその状態でトータルburst(KB)のデータが流れるとさらにaverage(KB/sec)まで抑えられます。つまり、一時的にはpeakまで許可するけどもそれが長く続くと、averageまで抑え込まれるという考え方です。

設定は次のように、--inbound、もしくは、--outboundオプションに続けて、「average(KB/sec)」「peak(KB/sec)」「burst(KB)」の3つの値を指定します。

# virsh domiftune vm01 52:54:00:d0:9a:df --inbound 1024,4096,$((1024*20)) --config --live 

この例では、4MB/secの受信トラフィックが約5秒つづくと(つまり、トータル20MB受信すると)、受信速度が1MB/secまで抑えられます。--configと--liveは、永続設定、および、稼働状態への設定の指定です。

ちなみに、仮想NICのMACアドレスをホストLinuxから確認する際は、tapinfoを使ってください。

# wget https://raw.githubusercontent.com/enakai00/tapinfo/master/tapinfo.py
# chmod u+x tapinfo.py 
# ./tapinfo.py 
Domain           Tap          MAC Address        Network      Bridge      
------------------------------------------------------------------------------
vm02             vnet1        52:54:00:c4:26:64  default      virbr0      
------------------------------------------------------------------------------
vm01             vnet0        52:54:00:d0:9a:df  default      virbr0