KVM總結-KVM效能優化之CPU優化
前言
任何平臺根據場景的不同,都有相應的優化。不一樣的硬體環境、網路環境,同樣的一個平臺,它跑出的效果也肯定不一樣。就好比一輛法拉利,在高速公路里跑跟鄉村街道跑,速度和激情肯定不同…
所以,我們做運維工作,也是如此。首先你得充分了解你所用的軟體平臺,然後根據你現有的生產環境去充分的測試,最後得出結果,做最優的調整。
KVM也是一樣,首先要做的是充分的瞭解它,看看有哪些引數和設定我們可以做出調整,最終應用以求發揮最高的效能。
那麼KVM的效能調優,我們可以從四個方面入手 —— CPU、記憶體、磁碟IO、網路。
KVM CPU效能調優
CPU這塊我們是針對NUMA這塊的調優,那麼什麼是NUMA呢?NUMA是英文 Non Uniform Memory Access Architecture 的縮寫,意思就是非統一記憶體訪問,它是一種解決多CPU共同工作的解決方案。我們知道現在的伺服器配置都比較高了,CPU很多都是多路多核的,而且CPU是需要跟儲存器進行資料互動的,以往的年代,那時候的CPU運算速率不高,而且都是單CPU模式,那麼儲存器裡的資料要放到CPU裡進行運算這是完完全全跟得上的。但是現在的CPU運算速度大大增強了,而且都是多CPU模式,於是就出現了不平衡,那就是儲存器裡的資料完全不夠讓CPU消化,並且還會出現多個CPU搶食儲存器的情況… 這種情況下CPU就表現得非常的飢渴… 資料不夠享用,而且儲存器還不夠分配。
因此電腦科學家為了提升計算機的效能,就認真的研究了下CPU和儲存器之間的協調互動模式。總體核心思想就是尋找一個多CPU模式下,如何讓CPU能最大化的“享用”更多來自多個儲存器的資料。
於是就設計出了以下幾套解決方案:
1. SMP技術
最開始是SMP技術,SMP(Symmetric Multi-Processing )技術就是對稱多處理結構,這種結構的最大特點就是CPU共享所有資源,比如匯流排,記憶體,IO系統等等。
既然是共享所有的資源,所以,各個CPU之間是平等的關係,然後作業系統管理著這些CPU對資源的訪問(通常是用佇列的形式去管理)。每個CPU依次的去處理佇列中的程序,如果兩個CPU同時訪問,那麼一般是通過軟體鎖的機制去解決爭奪的問題,軟體鎖這概念跟開發裡的執行緒安全鎖機制道理是一樣的,當一個CPU處理著一程序,一般會先鎖住,處理完再釋放。
所以說到這裡,這裡的對稱指的就是CPU之間是平等的無主從,訪問資源也是平等的。我們可以看下面這張圖:
這個結構是最早出現的方案,但是就是因為最早出現,所以它的弊端很快就顯現出來了,那就是它的擴充套件能力不強。我們看上面這張圖就明顯感覺到,如果伺服器要提升效能增加CPU,那麼記憶體(記憶體最大化的情況下)就明顯不夠了,因為是共享模式,多一個CPU就多一個吃記憶體資料的人… 因此多增加的CPU沒法享受到記憶體的資料,就會停歇,這樣就造成了CPU的浪費。
有實驗資料表明,SMP型的伺服器CPU最好是2-4顆就OK了,多餘的就浪費了。
由此可見,這種方式是有缺陷的。。。因此科學家又想到了另外一個結構方案,那就是NUMA。
2. NUMA技術
NUMA剛才我們在前面說了是非統一記憶體訪問的意思,它的出現就很好的解決了SMP的擴充套件問題。有了NUMA技術那麼就可以把幾十個甚至上百個CPU組合在一個伺服器內。
NUMA架構設計圖:
從圖中我們發現,每個CPU模組之間都是通過互聯模組進行連線和資訊互動,CPU都是互通互聯的,同時,每個CPU模組平均劃分為若干個Chip(不多於4個),每個Chip都有自己的記憶體控制器及記憶體插槽。
在NUMA中還有三個節點的概念:
1. 本地節點: 對於某個節點中的所有CPU,此節點稱為本地節點。
2. 鄰居節點:與本地節點相鄰的節點稱為鄰居節點。
3. 遠端節點:非本地節點或鄰居節點的節點,稱為遠端節點。
鄰居節點和遠端節點,都稱作非本地節點(Off Node)。
這裡要注意的是,CPU訪問不同型別節點記憶體的速度是不相同的,訪問本地節點的速度最快,訪問遠端節點的速度最慢,即訪問速度與節點的距離有關,距離越遠訪問速度越慢,此距離稱作Node Distance。正是因為有這個特點,所以我們的應用程式要儘量的減少不同CPU模組之間的互動,也就是說,如果你的應用程式能有方法固定在一個CPU模組裡,那麼你的應用的效能將會有很大的提升。
因此KVM也是一樣,我們在CPU優化這塊就是要讓KVM繫結在指定的CPU上,這樣減少跨CPU的互動使用,讓KVM的效能提升。現在我們的伺服器還有linux作業系統都是預設走NUMA模式,所以我們接下來說說如何去做CPU的繫結。
那麼具體如何操作?
3. numactl 命令講解
我們這裡用一臺真實的物理機演示,這臺物理機的是IBM 3650M4。
首先我們用numactl命令檢視NUMA的情況,如果你係統沒有這個命令,用 yum install numactl 安裝下即可。
# numactl --h
numactl 幫助命令,主要引數如下:
--interleave=nodes, -i nodes
這個選項用於設定記憶體的交織分配模式。
也就是說系統在為多個節點分配記憶體空間的時候,將會以輪詢分發的方式被分配給這多個節點。如果在當前眾多的交織分配記憶體節點中的目標節點無法正確的分配記憶體空間的話,記憶體空間將會由其他的節點來分配。多節點可以通過 --interleave , --membind 和 --cpunodebind 命令來指定。
--membind=nodes, -m nodes
選項 '--membind' 僅用來從節點中分配記憶體空間所用。 如果在這些節點中無法分配出所請求的空間大小的話該分配操作將會失敗.
上述命令中指定需要分配空間的 nodes 的方式可以遵照上述 N,N,N , N-N ,N 這種方式來指定.
--cpunodebind=nodes, -N nodes
這命令僅用於施加在執行與 cpu 上的程序。
這個命令用於顯示 cpu 的個數,cpu 數目資訊同樣記錄在系統中的存放處理器領域資訊的 /proc/cpuinfo 資料夾下,或者是按照關聯的中央處理器資訊 在當前的中央處理器集中所存放。
--localalloc, -l 這個命令選項通常是為當前的節點分配記憶體的。 --preferred=node 該命令由於指定優先分配記憶體空間的節點,如果無法將空間分配給該節點的話,應該分配給該節點上的空間將會被分發到其他的節點上 。 該命令選項後面僅接收一個單獨的節點標號. 相關的表示方式也可以使用。 --show, -s 該命令用於顯示 NUMA 機制作用在當前執行的那些程序上。 --hardware, -H 該命令用於顯示當前系統中有多少個可用的節點。 --huge 當建立一個基於大記憶體頁面的系統級的共享記憶體段的時候使用--huge 這個選項,注意這選項僅在 --shmid 或是 --shm 命令的後面使用才有效。 --offset 該引數選項用於指定共享記憶體段中的位移量的偏移。 預設的情況下偏移量是 0 。 有效的偏移量單位是 m (用於表示 MB) g (用於表示 GB) , k (用於表示 KB ), 其他沒有指定的被認為是以位元組為單位。 --strict 這個引數選項 當施加了 NUMA 排程機制的共享記憶體段區域的頁面被施加了另一個機制而導致錯誤的時候,使用 --strict 選項將會把錯誤資訊顯示出來. 預設情況是不使用該選項的。 --shmmode shmmode 該選項僅在 --shmid 或是 --shm 之前使用才會生效。 當建立一個共享記憶體段的時候,通過整型數值來指定共享記憶體的共享的模式型別。 --shmid id 通過ID 號碼來建立或使用一個共享記憶體段。(如果共享記憶體段已經存在,那麼通過 shmid 來指定下面要使用某個 ID 的共享記憶體段;如果該 ID 對應的共享記憶體段並不存在的話,那麼就建立一個)。 --shm shmkeyfile 通過存放在 shmkeyfile(共享記憶體-鍵檔案)中的 ID 號碼來建立或者是使用一個共享記憶體段。訪問 shmkeyfile 檔案的程序是通過 fork(3 arguments) 方法來實現的。 --file tmpfsfile 將 numa 機制施加於檔案上面, 這個檔案屬於 tmpfs或者是 hugetlbfs 這種特殊的檔案系統。 --touch 通過將 numa 機制施加於剛剛頁面上來實現記憶體的早期 numa 化。預設情況下是不使用該選項,如果存在對映或是訪問頁面的應用的話,將會使用該早期實行 NUMA 機制的這種方法。 --dump 該選項用於廢除將已經 numa 化的特定區域上的 NUMA性質. --dump-nodes nodes 所指定的節點以外的所有節點上的 NUMA 特性全都會被移除 all 用於將所有的節點上的 NUMA 特性移除 number 通過指定 node 後接的數值來廢除該數字對應的 node number1(number2) node number1(node number2)上的 NUMA 特性將會被移除 number1-number2 node number1 -- node number2 區間上的所有存在的 node 的 NUMA 特性將會被移除 !nodes 除了 nodes 所指定的節點以外的所有節點上的 NUMA 特性全都會被移除
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
以上是numactl的詳細命令,那麼接下來我們先看看當前伺服器CPU的numa情況:
我們執行lscpu命令可以檢視到一些CPU資訊:
我們用numactl --hardware
可以檢視,如這裡我準備了兩臺IBM的伺服器,一個3650M4另外一個是3850M2。
我們可以從命令返回的情況看出,這臺伺服器numa有2個node(node0和node1):
我們再看另外一個伺服器,這是一臺IBM 3850M2,那麼它就只有一個node:
通過這個numactl --hardware
命令,我們可以看出上面那臺機器每個node有81894 MB的記憶體可以使用(大概79G),而IBM 3850M2這個伺服器node有131070MB(120多G)記憶體可用(基本上是整個伺服器的記憶體)
那麼接下來我們可以看下cpu numa的排程分配情況:
我們執行numastat命令可以查到:
3650M4
3850M2
引數解釋:
● numa_hit 使用本節點記憶體次數
● num_miss 計劃使用本節點記憶體而被排程到其他節點次數
● num_foregin 計劃使用其他節點記憶體而使用本地記憶體次數
● interleave_hit 交叉分配使用的記憶體中使用本節點的記憶體次數
● local_node 在本節點執行的程式使用本節點記憶體次數
● NB other_node 在其他節點執行的程式使用本節點記憶體次數
接著我們看下這個命令:numastat -c , 這個命令c 後面跟上程序名就能看到相關程序的NUMA記憶體使用情況。比如:numastat -c qemu-kvm,這樣我們就知道了qemu-kvm這個程序,它在node0 和node1上使用的記憶體大小,單位是MB:
通過這幾個命令我們可以檢視一些numa的基本狀態和使用情況。那麼針對CPU Numa技術,linux作業系統本身呢也有自身對這塊的設計。拿linux來說,它預設使用的就是NUMA自動平衡策略,也就是說,系統會自動的調配numa的記憶體使用,以求一個平衡。
當然,這個設定是可以使用者自己控制的,如果我們想關閉,直接執行
# echo 0 > /proc/sys/kernel/numa_balancing
即可 # echo 1 > /proc/sys/kernel/numa_balancing
開啟
4. CPU繫結操作
說到這,既然我們的作業系統還有CPU特性都採用了NUMA架構,那麼我們完全可以通過調整KVM對應的NUMA關係來達到KVM CPU這方面的優化。這裡,我們一般是通過CPU繫結的方法來做相關操作的。
那麼具體的操作是怎麼樣的呢?那麼接下來我們通過一個例子來演示。這裡是一臺物理機,之前我們看過了,現在上面裝好了KVM,然後執行著幾個虛擬機器,我們用 virsh list 命令可以檢視到當前執行的虛擬機器列表。
比如我們要看這個Win7-ent虛擬機器裡vCPU對應物理CPU的情況,那麼可以執行: # virsh vcpuinfo Win7-ent
可以檢視
這個虛擬機器是2個vCPU 雙核的,然後都是跑在了物理機的CPU8上,使用的時間是2964.6s。最後一個是CPU的親和性,這個yyyyy 表示的是使用的物理CPU內部的邏輯核,一個y就代表其中一個CPU邏輯核。全部是y ,那麼說明這臺物理機的24個CPU核,這個CPU都能排程使用。
當然,我們可以進入vrish ,然後執行emulatorpin Win7-ent, 通過這個命令我們可以更詳細的得到這個虛擬機器可以用哪幾個核:
我們可以看到目前這個虛擬機器0-23的CPU它都能排程使用。
那麼以上就是檢視虛擬機器CPU NUMA排程的資訊,如果我們要把虛擬機器繫結到固定的CPU上,我們就要做以下操作: # virsh emulatorpin Win7-ent 18-23 --live
通過這個命令,我們把這個win7的虛擬機器vCPU繫結在了18-23這6個CPU之間的核上。
我們用命令檢視下
emulatorpin Win7-ent
我們也可以用virsh dumpxml Win7-ent 檢視確認:
這是讓虛擬機器裡的vCPU一起繫結的方法。
那麼有的人會疑問,一個虛擬機器我有兩個vCPU, 比如這個win7 ,它就是雙核的,我想讓裡面的vCPU1和vCPU2分別繫結在不同的物理CPU上可以嗎?怎麼操作呢?這也是可以的,我們通過下面的方法可以進行相關的vCPU分別繫結
# virsh vcpupin Win7-ent 0 22
# virsh vcpupin Win7-ent 1 23
# virsh dumpxml Win7-ent
- 1
- 2
- 3
# virsh vcpuinfo Win7-ent
- 1
這裡要注意的是,你把虛擬機器用reboot重啟,這個繫結配置還是生效的,但是你shutdown的話,CPU繫結的效果會失效。我們要讓VM關機然後起來也生效,就必須把引數寫入到虛擬機器的XML裡,然後儲存,這樣關機了也不會失效,這裡要注意下
# virsh edit vm1
- 1
新增:
<cputune>
<vcpupin vcpu='0' cpuset='22'/> <vcpupin vcpu='1' cpuset='23'/> </cputune>
- 1
- 2
- 3
- 4
以上就是CPU繫結技術的操作。通過這樣的操作,我們可以在一臺多CPU的物理機上固定幾個CPU給虛擬機器用。當然,至於為什麼可以這樣做,前面我們提到了關於NUMA的原理,如果固定了虛擬機器的CPU,那麼它就不會去找遠端節點了,另外就是有些場景下,一物理機多個CPU,如果前面幾個CPU負載很高,利用率大,後面幾個CPU利用率低,那麼我們可以協調下,做CPU的繫結,平衡下CPU的負載。
以上是CPU的繫結,接下來我們講講CPU的熱新增。
5. CPU 熱新增
首先我們先了解下什麼叫熱新增,熱新增就是在虛擬機器執行不關機的情況下,做CPU的新增操作。那麼要注意的是,這個熱新增是在Redhat7.0以後才出現的,之前是沒有的。所以要享用這功能那必須要求KVM宿主機和虛擬機器都得在7.0版本以後。那麼具體怎麼操作我們通過一個演示給大家操作下。
比如目前這個虛擬機器,這是一個CentOS7.1的。我們先看下目前虛擬機器的CPU的數值,我們可以進系統檢視,cat /proc/cpuinfo| grep "processor"| uniq| wc -l
,我們看到當前是2個CPU:
然後我們解釋下這個最大CPU分配數是怎麼個意思,它的意思就是給這個虛擬機器最大預留的CPU個數,這個設定很重要,如果你想給虛擬機器熱新增,那麼這個設定必須寫。比如我們這裡寫的4,那麼我們可以給虛擬機器最大熱新增到4個CPU,而且4是上限。
那麼接下來說下,具體怎麼熱新增。我們先在宿主機裡先給這個虛擬機器新增第三個CPU,原來是2個,現在再新增一個變成3個: setvcpus VM3_CentOS7.1 3 --live
然後我們到虛擬機器裡面把這個CPU啟用 :
echo 1 >/sys/devices/system/cpu/cpu2/online
- 1
我們再執行檢視,發現已經變成3個了。
如果要減少,那麼只能在虛擬機器裡減少剛才的CPU
# echo 0 >/sys/devices/system/cpu/cpu2/online
- 1
但是在宿主機層面看這個虛擬機器的vCPU數還是3個,也就是說不支援熱減少,我們執行
vcpuinfo VM3_CentOS7.1
- 1
命令發現還是3個:
同理,Windows的新增也是如此,直接在宿主機裡新增第三個CPU即可
# setvcpus VM4_Win2008 3 --live
- 1
然後虛擬機器裡不用操作,它會自動重新整理成3個CPU,我們也可以一個windows虛擬機器做相關的演示,具體的可以由讀者自己操作了。
到這為止, 以上就是KVM CPU方面的優化。總結起來就兩點,一個是CPU繫結,還有一個就是熱新增。
CPU繫結首先得了解NUMA技術,然後站在整個宿主機CPU資源的層面去調節。熱新增,當你某個虛擬機器正在執行,然後突然業務壓力增大了,可以通過這方法達到0停機提升虛擬機器CPU效能。
轉載自雲技術實踐微信公眾號,作者寶哥。