KVM 核心功能:CPU 虛擬化



1 vCPU 簡介

CPU 負責計算機程序指令的執行。QEMU-KVM 提供對虛擬機 CPU 的模擬,對於虛擬機來說,其擁有的 CPU 是真實的, 和物理 CPU 沒有區別。
實際上,虛擬機在 host 上表現為一個 qemu 進程,而虛擬機的 vCPU (從 host 上看是 vCPU) 則是該進程下的一個線程。
 
使用 qemu-kvm 創建一個虛擬機:
[root@lianhua qemu-kvm]# /usr/libexec/qemu-kvm -smp 2 -m 1G lianhua.qcow -monitor stdio
QEMU 2.6.0 monitor - type 'help' for more information
(qemu) VNC server running on '::1;5900'
 
(qemu) info cpus
* CPU #0: pc=0x000000003fefa56a thread_id=1019305
  CPU #1: pc=0x00000000000fd374 (halted) thread_id=1019307
(qemu) info cpus
* CPU #0: pc=0x000000003ff0d4ea (halted) thread_id=1019305
  CPU #1: pc=0x00000000000fd374 (halted) thread_id=1019307
 
[root@lianhua home]# ps -eLf | grep qemu
root     1019294 1014044 1019294  0    5 12:53 pts/0    00:00:00 /usr/libexec/qemu-kvm -smp 2 -m 1G lianhua.qcow -monitor stdio
root     1019294 1014044 1019300  0    5 12:53 pts/0    00:00:00 /usr/libexec/qemu-kvm -smp 2 -m 1G lianhua.qcow -monitor stdio
root     1019294 1014044 1019305  6    5 12:53 pts/0    00:00:12 /usr/libexec/qemu-kvm -smp 2 -m 1G lianhua.qcow -monitor stdio
root     1019294 1014044 1019307  0    5 12:53 pts/0    00:00:00 /usr/libexec/qemu-kvm -smp 2 -m 1G lianhua.qcow -monitor stdio
root     1019294 1014044 1019309  0    5 12:53 pts/0    00:00:00 /usr/libexec/qemu-kvm -smp 2 -m 1G lianhua.qcow -monitor stdio
 
可以看到,虛擬機的 CPU 0 和 1 分別對應線程 1019305 和 1019307。並且,它們都是進程 1019294 的子線程,而進程 1019294 則是通過 qemu-kvm 創建的虛擬機進程。
同時,也可看到虛擬機的子進程數要大於 CPU 數目,因為虛擬機需要一些單獨的進程來處理專門的任務,比如 I/O 任務等。

2 vCPU 配置

這里 vCPU 的配置都是使用硬件輔助的虛擬化技術,首先要保證內核已加載 kvm 模塊。當然 qemu 也得運行起來。
 
配置 vCPU 有兩種方式,第一種直接使用 qemu-kvm 命令行指定 vCPU 信息,第二種通過 virsh XML 配置 vCPU 信息。兩種方式如下所示:
 
1) vCPU 配置如上例所述,可通過 smp 指定 cpu 的信息來配置:
[root@lianhua qemu-kvm]# /usr/libexec/qemu-kvm -smp 2 -m 1G lianhua.qcow -monitor stdio
該配置會創建一個有兩個 vCPU 的虛擬機,且計算機架構為 SMP 架構(計算機架構主要有 SMP 和 NUMA,參考這里了解更多)。
 
[root@lianhua qemu-kvm]# /usr/libexec/qemu-kvm -smp 3,sockets=3,cores=1,threads=1 -m 1G lianhua.qcow -monitor stdio
該配置會創建一個具有 3 個 vCPU 的虛擬機。對於虛擬機來說,它有 3 個 socket,每個 socket 有 1 個核,且核上未開啟超線程,threads 為 1。
 
2) 通過在 virsh 的 XML 文件中配置 vCPU 信息:
<vcpu placement='static'>6</vcpu>
<cputune>
<shares>6144</shares>
<vcpupin vcpu='0' cpuset='9'/>
<vcpupin vcpu='1' cpuset='37'/>
<vcpupin vcpu='2' cpuset='11'/>
<vcpupin vcpu='3' cpuset='39'/>
<vcpupin vcpu='4' cpuset='34'/>
<vcpupin vcpu='5' cpuset='6'/>
<emulatorpin cpuset='6,9,11,34,37,39'/>
</cputune>
 
如上所示,虛擬機配有 6 個 vCPU,並且在 cputune 標簽中設置了 vCPU 和 host 上物理 CPU 的映射關系,即 0 - 9,1 - 37...
 
在 XML 文件的 cpu mode 標簽中可詳細定義 cpu 的配置類型:
<cpu mode='host-model'>
<model fallback='allow'/>
<topology sockets='3' cores='1' threads='2'/>
<numa>
  <cell id='0' cpus='0-5' memory='33554432' unit='KiB' memAccess='shared'/>
</numa>
</cpu>
 
如上所示,cpu mode 為 host-model,即根據 host 的 cpu 特性為 domain 選擇最接近標准的 CPU 型號(看這里了解 cpu mode 標簽)。同時,topology 標簽定義了 cpu 的 sockets/cores 和 threads 情況,這里也配置了 numa node,指定 cpu 配置在 numa0 上,cpu 使用的內存為 33554432 和使用的方式 shared。
 
cpu 配置好之后登陸到 domain 虛擬機中查看 cpu 的配置是否生效:
$ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 61
model name      : Intel Core Processor (Broadwell)
stepping        : 2
microcode       : 0x1
cpu MHz         : 2394.454
cache size      : 4096 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 1
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt arat
bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit srbds
bogomips        : 4788.90
clflush size    : 64
cache_alignment : 64
address sizes   : 46 bits physical, 48 bits virtual
power management:
...
 
$ /bin/bash cpu.sh
The physical cpu is:  3
core number in a physical cpu:  1
logical cpu number in a physical cpu:  2
The hyper threading is enabled, each core has 2 threads
logical cpu number in host:  6
cpu 配置生效,且 cpu model name 匹配為 Broadwell。

3 vCPU 特性

vCPU 有幾大特性,在部署虛機時合理利用這些特性能夠使得部署更靈活,同時實現效率最大化。

3.1 vCPU overcommit

在實際虛擬機使用時,不是每個虛擬機都在同時工作,這樣就會造成 host 上 cpu 資源的浪費。通過 vCPU 的 overcommit 機制可以有效避免這種資源浪費。
vCPU overcommit,即虛擬機上 vCPU 的個數可以大於 host 上 logical CPU 數目。

3.2 vCPU 熱插拔

如果在生產環境上虛擬機的 cpu 資源不夠了,那么可以通過 vCPU 的熱插拔特性動態的為虛擬機添加 vCPU:
[root@lianhua qemu-kvm]# /usr/libexec/qemu-kvm -smp 3,maxcpus=5,sockets=3,cores=1,threads=1 -m 1G lianhua.qcow -monitor stdio
QEMU 2.6.0 monitor - type 'help' for more information
(qemu) VNC server running on '::1;5900'
 
(qemu) info cpus
* CPU #0: pc=0x000000003fefa56a thread_id=356200
  CPU #1: pc=0x00000000000fd374 (halted) thread_id=356201
  CPU #2: pc=0x00000000000fd374 (halted) thread_id=356203
(qemu) cpu-add 3
(qemu) info cpus
* CPU #0: pc=0x00000000000fc373 (halted) thread_id=356200
  CPU #1: pc=0x00000000000fd374 (halted) thread_id=356201
  CPU #2: pc=0x00000000000fd374 (halted) thread_id=356203
  CPU #3: pc=0x00000000fffffff0 thread_id=357997
 
如上所示,在虛擬機運行時通過 cpu-add 將 3 號 cpu 加載到虛機中。注意,在進行熱插拔時首先要保證有足夠的 cpu 資源可供熱插拔(maxcpus > smp 指定的 logical cpu 數),如果沒有足夠資源則會顯示無法進行熱插拔。

3.3 vCPU 親和性

部署虛擬機時可配置 vCPU 的親和性,即將 vCPU 和 host 上 logical CPU 綁定在一起,使得 vCPU 運行在固定的 logical CPU 上。
 
vCPU 親和性的配置在上節已經介紹了,這里不再贅述。在 host 上查看綁定的 CPU 使用情況:
1) 配置 vCPU 親和性:
<vcpu placement='static'>6</vcpu>
<cputune>
<shares>6144</shares>
<vcpupin vcpu='0' cpuset='9'/>
<vcpupin vcpu='1' cpuset='37'/>
<vcpupin vcpu='2' cpuset='11'/>
<vcpupin vcpu='3' cpuset='39'/>
<vcpupin vcpu='4' cpuset='34'/>
<vcpupin vcpu='5' cpuset='6'/>
<emulatorpin cpuset='6,9,11,34,37,39'/>
</cputune>
vCPU 分別綁定在 host 上 logical cpu 的 6,9,11,34,37,39 上。
 
2) 查看 host 上對應 logical cpu 的使用情況:
[root@lianhua home]# ps -eLo ruser,pid,ppid,lwp,psr,args | grep qemu | grep -v grep
...
 
[root@lianhua home]# ps -eLo ruser,pid,ppid,lwp,psr,args | awk '{if($5==37) print $0}'
root         193       2     193  37 [watchdog/37]
root         194       2     194  37 [migration/37]
root         195       2     195  37 [ksoftirqd/37]
root         196       2     196  37 [kworker/37:0]
root         197       2     197  37 [kworker/37:0H]
root      145760       2  145760  37 [kworker/37:1]
qemu      879955       1  880096  37 /usr/libexec/qemu-kvm -name guest=lianhua ...
 
第一行命令輸出 qemu 創建的進程和線程情況。由於輸出信息太多,這里直接省略了。
第二行輸出指定 logical cpu 上運行的線程,以 37 號 cpu 為例,它上面運行了系統線程 watchdog,migration 等等,同時也運行了一個虛擬機的線程(該線程是 vCPU 線程,可在 qemu monitor 里使用 info cpus 查看線程和 vCPU 的映射關系),且該線程的進程是 879955,該進程即使創建的虛擬機的 qemu 進程。
 
最后,查看 host 上其它 logical cpu 是否有調度到 vCPU 線程:
[root@lianhua home]# ps -eLo ruser,pid,ppid,lwp,psr,args | awk '{if($5==40) print $0}'
root         208       2     208  40 [watchdog/40]
root         209       2     209  40 [migration/40]
root         210       2     210  40 [ksoftirqd/40]
root         212       2     212  40 [kworker/40:0H]
root      390900       2  390900  40 [kworker/40:0]
root      673792       2  673792  40 [kworker/40:1]
root      674097       2  674097  40 [kworker/40:1H]
[root@lianhua home]# ps -eLo ruser,pid,ppid,lwp,psr,args | awk '{if($5==41) print $0}'
root         213       2     213  41 [watchdog/41]
root         214       2     214  41 [migration/41]
root         215       2     215  41 [ksoftirqd/41]
root         216       2     216  41 [kworker/41:0]
root         217       2     217  41 [kworker/41:0H]
沒有調度到 vCPU 線程,說明虛擬機里 vCPU 成功綁定到 logical cpu。
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM