1. 程式人生 > >KVM總結-KVM效能優化之記憶體優化

KVM總結-KVM效能優化之記憶體優化

  1. EPT 技術
  2. 大頁和透明大頁
  3. KSM 技術
  4. 記憶體限制

EPT技術

EPT也就是擴充套件頁表,這是intel開創的硬體輔助記憶體虛擬化技術。我們知道記憶體的使用,是一個邏輯地址跟實體地址轉換的過程。虛擬機器內部有邏輯地址轉成成實體地址的過程,然後再跳出來,虛擬機器這塊記憶體又跟宿主機存在邏輯到物理的轉換。有了EPT技術,那麼能夠將虛擬機器的實體地址直接翻譯為宿主機的實體地址,從而把後面那個轉換過程去掉了,增加了效率。

那麼這項技術,現在的伺服器都支援,只要在BIOS打開了intel 的VT設定,這個也一起打開了。

所以這個基於硬體的優化,目前不需要做額外的什麼操作。
這裡寫圖片描述

大頁和透明大頁

我們先解釋什麼叫大頁。

所謂的大頁指的是記憶體的大頁面。當然,有大頁面必然有對應的小頁面… 我們知道記憶體採用的是分頁機制,當初這個機制提出的時候,計算機的記憶體大小也就幾十M,所以當時記憶體預設的頁面大小都是4KB,那麼這個4KB 也就是所謂的小頁面。但是隨著計算機的硬體發展,現在的記憶體基本上都是幾十G 甚至上百G了,雖然,如果還是4KB小頁的方式,那麼必然會存在一些問題。那麼會有哪些問題呢?作業系統如果還是小頁存在,那麼將會產生較多的TLB Miss和缺頁中斷,從而大大影響效能。

為什麼小頁就存在較多的Miss和缺頁中斷呢?比如說系統裡的一個應用程式需要2MB的內容,如果作業系統還是以4KB小頁為單位,那麼記憶體裡就要有512個頁面(512*4KB=2M),所以在TLB裡就需要512個表項以及512個頁表項,因此作業系統就要經歷512次的TLB miss和512次的缺頁中斷才能將2MB的應用程式空間全部對映到實體記憶體裡。想想,2MB記憶體的需要就要經歷512次的操作,如果記憶體需求大呢?必然運算元量會大大增加,從而間接的影響效能。

如果把這個4KB變成2MB呢?那就很輕鬆了,一次TLB Miss和缺頁中斷操作就完成了,大大的增加了效率。

所以,虛擬機器可以通過分配巨型頁也就是剛才說的大頁來提高執行效能。

那麼具體怎麼操作呢?也就是說如何把這個4KB的小頁變成2MB甚至1GB的大頁,然後把這個大頁賦給虛擬機器使用?

我們可以先通過命令 cat /proc/meminfo | grep HugePages檢視當前系統有多少個大頁:
這裡寫圖片描述
我們看到,當前數量是0。

那麼如何設定大頁的數量呢?也就是上面的HugePages_Total的數量。

只要執行echo 2000 > /proc/sys/vm/nr_hugepages 這個命令即可:
這裡寫圖片描述


已經變成了2000了。

當然這樣重啟會失效,我們執行這個命令讓它永久生效 :

sysctl -w vm.nr_hugepages=2000
  • 1

運行了這個命令系統重啟的話,大頁的數量也將是保持2000,不會變。
接下來,我們還得把大頁進行掛載,我們執行:

# mount -t hugetlbfs hugetlbfs /dev/hugepages 
  • 1

這個hugetlbfs 是一種特殊檔案系統,那至於為什麼採用這樣的檔案系統是因為這樣花費的代價小。

通過這幾步操作,開啟->設定大頁數量->掛載, 那麼宿主機這塊就沒什麼問題了。

如果我們KVM裡面的某個虛擬機器要使用宿主機的大頁,那麼我們還得做如下操作:

  1. 重啟下libvirtd服務
  2. 虛擬機器也開啟透明巨型頁
  3. 關閉虛擬機器編輯虛擬機器XML設定虛擬機器可以使用宿主機的巨型頁數量

我們先看看,當前的大頁是沒程序用的, hugepages_free是2000:
這裡寫圖片描述

我們先把libvirtd服務重啟:systemctl restart libvirtd.service

然後,我們看看虛擬機器的透明大頁有沒有開啟,一般預設系統是開啟的,我們確認下
這裡寫圖片描述
我們看到是always狀態,那麼就是開啟的,OK,我們進行下一步。

編輯虛擬機器XML檔案,讓它使用宿主機的大頁。

我們先把虛擬機器關閉,然後 virsh edit vmname 命令修改,新增下圖中紅色框框的內容:
這裡寫圖片描述

修改後,儲存,然後開啟虛擬機器,注意這個虛擬機器的記憶體是2G的配置。

最後我們在宿主機執行cat /proc/meminfo | grep -i HugePages 檢視下大頁的使用情況
這裡寫圖片描述

我們發現hugepages_free 已經變成了912個了,那麼使用了2000-912=1088 個。

Hugepagesize是2M,也就是每頁頁面的大小,使用了1088個頁面,那麼2*1088=2176M 正好跟虛擬機器記憶體的大小2G差不多。

如果想讓虛擬機器釋放大頁,那麼只要把這個虛擬機器關機或者刪除XML裡剛才新增的配置。

剛才的操作,我們只是針對一個虛擬機器的,也就是說我們把大頁面賦給了一個虛擬機器。如果我們要賦予多個虛擬機器怎麼辦?

那麼要讓大頁同時讓多個虛擬機器享用,有以下兩步要做:

  1. 給NUMA 各個node節點分配多個2MB或者1GB的大頁
  2. 編輯虛擬機器xml檔案以使用node裡分配好的大頁

我們可以執行下面兩個命令就可以給宿主機各個NUMA Node分配大頁

# echo 4 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages
# echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
  • 1
  • 2

這兩個命令的意思就是先給node0裡分配4個1GB的大頁,然後再給node1分配1024個2MB的大頁。

然後執行相關掛載操作,這跟剛才我們做的操作類似:

# mkdir /dev/hugepages1G
# mount -t hugetlbfs -o pagesize=1G none /dev/hugepages1G
# mkdir /dev/hugepages2M
# mount -t hugetlbfs -o pagesize=2M none /dev/hugepages2M
  • 1
  • 2
  • 3
  • 4

掛載成功後,重啟下libvirtd服務,然後虛擬機器就可以使用了,但是這裡要注意的是,1GB的大頁,虛擬機器是不能直接使用的,需要在XML裡指定。

那麼怎麼指定? 我們目前宿主機NUMA node1和node2裡面分別有4個1GB的和1024個2MB的大頁。因此,只要跑在這兩node上的虛擬機器都可以享用了。

比如剛才我們那虛擬機器,我們要讓它使用1GB的大頁,我們只需要在XML裡這樣定義:

<memoryBacking>      
  <hugepages/>          
    <page size="1" unit="G" nodeset="0-3,5"/>          
    <page size="2" unit="M" nodeset="4"/>      
  </hugepages> 
</memoryBacking>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

紅色的部分就是要新增的引數,size是1,表示第一個使用的page;然後單位unit是G,nodeset=”0-3,5” 意思是虛擬機器的NUMA node0,node1, node2 , node3和node5將使用1GB的大頁 ; 虛擬機器的node4將用2MB的大頁。

注意,這裡的nodeset指的是虛擬機器的節點,同時還要注意的是,如果宿主機大頁面不夠用了,你這樣配置了,虛擬機器是會起不來的。

以上就是給虛擬機器分配大頁的方法。當然如果你想把宿主機的大頁關閉,只要執行:

# sysctl vm.nr_hugepages=0
# umount hugetlbfs
  • 1
  • 2

接下來我們講下透明大頁。

從Centos6開始,linux系統自帶了一技術叫透明巨型頁(transparent huge page),它允許所有的空餘記憶體被用作快取以提高效能,而且這個設定是預設開啟的,我們不需要手動去操作。

Centos下,我們用cat /sys/kernel/mm/transparent_hugepage/enabled可以檢視
這裡寫圖片描述

我們看到這個中括號把這個always括起來了,說明這機器的透明巨型頁的功能是開啟的。當有512個頁面可以整合的時候,就會合成一個2MB的大頁;如果是在括號把never括起來了,那麼就是關閉狀態;madvise的話就是避免改變記憶體佔用。

當然,如果你想改變透明巨型頁的狀態,比如說關閉它,那麼執行下面的命令即可:

# echo never >/sys/kernel/mm/transparent_hugepage/enabled
  • 1

這裡寫圖片描述

最後要注意的是透明巨型頁跟剛才我們說的hugetlbfs 檔案掛載大頁是不衝突的,如果你沒做任何大頁的指定和掛載,那麼KVM就會使用透明大頁的方式。

那麼說到這,大家就會疑問,既然有透明大頁,我為何還要費勁的去做相關大頁的指定? 其實這兩種方式都差不多,區別就是一個是手動的一,個是自動的。如果你對你宿主機資源把握的更加精準,推薦的還是手動指定。

KSM 技術

KSM是什麼呢?KSM(Kernel SamePage Merging),也就是所謂的相同頁面記憶體壓縮技術。

KSM服務在linux系統裡預設是開啟的,它的作用就是讓記憶體利用的更加高效,我們知道記憶體是分頁的,如果多個程式中用的記憶體都是相同的頁面,那麼KSM就會把相同的記憶體合併,這樣就能騰出更多的空間。

KSM在系統裡有個守護程序,它的作用就是不斷的掃描宿主機的記憶體情況,檢測有相同的頁面就會合並,這或多或少會消耗CPU。

下面有幾個命令設定大家要了解:
首先是開關KSM服務:

systemctl start|stop ksmd
systemctl start|stop ksmtuned 
systemctl enable|disable ksmd
systemctl enable|disable ksmtuned
  • 1
  • 2
  • 3
  • 4

如果你的環境,記憶體資源比較豐富,VM又不多,這個功能開不開啟都無所謂;如果不夠,又想跑多一點的虛擬機器,那麼可以開啟這個功能。但是你一定要注意,這個是一種記憶體超用的方案,如果一臺宿主機裡大部分虛擬機器記憶體變化比較頻繁,那麼要慎重開啟,因為KSM會頻繁的做記憶體掃描,不停的做記憶體合併操作,這會大量的消耗CPU資源,如果記憶體不夠還會用到swap,那麼最終會嚴重影響虛擬機器效能。

當然,也有設定能讓虛擬機器不受宿主機KSM的影響,具體操作如下:

編輯虛擬機器的XML檔案,新增:

<memoryBacking>
    <nosharepages/>
</memoryBacking>
  • 1
  • 2
  • 3

這樣,這個KSM就不會去合併這個虛擬機器的記憶體了。

總的來說,如果你的環境硬體配置比較高,同時又追求VM數量,把KSM開啟是一個很不錯的選擇(但是一定要做好相關資源的實時監控,特別是CPU)。在筆者維護過的專案中,遇到過只追求數量而不追求效能的場景,當時我們就開啟了KSM服務,伺服器配置是雙路E5-2690 [email protected] 48core、512G記憶體,當每臺計算節點到80個VM的時候(VM大部分配置為4c8G,windows和linux各佔50%)。用htop命令監控檢視CPU每個核基本上都是99%滿負載,此時,虛擬機器體驗十分不好,後來降到60個左右,CPU負荷在60%-70%,這樣情況才有明顯好轉。

所以,用不用KSM視你自己的生產環境和客戶需求具體而定,這配置還是得慎重。

記憶體限制技術

通過虛擬機器記憶體限制,可以讓虛擬機器的記憶體使用限制在一定範圍內。

那麼這個操作有什麼作用呢?比如你的一臺KVM宿主機,裡面跑著多個業務的虛擬機器,有的虛擬機器業務比較大,吃得記憶體多,有的業務比較低,用不了多少記憶體,那麼我們可以通過記憶體限制技術來手動調節宿主機的記憶體分配。

當然這裡要說明的是,使用這個必須對你虛擬化環境特別清楚,比如宿主機平時的負載情況以及各個虛擬機器的負載情況。

那麼具體如何操作呢?我們通過memtune命令或者通過改虛擬機器的XML檔案來設定記憶體的限制。

這個memtune命令有以下4個引數
這裡寫圖片描述
hard_limit:強制設定虛擬機器最大使用記憶體,單位為KB
soft_limit:可用最大記憶體,單位為KB
swap_hard_limit:虛擬機器最多使用的記憶體加上swap的大小,單位為KB
min_guarantee:強制設定虛擬機器最低使用的記憶體,單位為KB

最後一個引數雖然OPTIONS裡有列出,但是實測是發現CentOS7.0 以上系統不能支援,執行的時候會報下面這樣的錯誤:
這裡寫圖片描述

–config : 寫入配置檔案中,虛擬機器重啟後生效
–live :讓設定立即生效,但是虛擬機器重啟後,效果消失 (如果不加–config –live –current 那麼預設是這個)
–current :影響關機或者執行狀態的虛擬機器,如果當前虛擬機器正在執行,那麼虛擬機器停止後,效果會消失

例:

# memtune VM3_CentOS7.1  --hard-limit 9437184 --config

給虛擬機器VM3_CentOS7.1 設定最大使用記憶體為9G

# memtune VM3_CentOS7.1  --soft-limit 8388608 --config

給虛擬機器VM3_CentOS7.1 設定最大可用記憶體為8G

# memtune VM3_CentOS7.1 --swap-hard-limit 10485760 --config

限制虛擬機器VM3_CentOS7.1最大內加可以使用的宿主機swap不超過10GB記憶體,注意設定這個值的時候必須大於hard-limit的所設定的值。

這個設定可以慎用,因為虛擬機器使用了swap那麼速度效能肯定會下降很多,而且要注意的是,這裡設定的記憶體大小必須大於hard-limit

# memtune VM3_CentOS7.1  --min-guarantee 4194304 --config

這個命令我們可以操作下,但是演示會發現前面所說的error

以上是通過命令的方式,我們剛才說了,還可以通過修改XML的方式來現在虛擬機器的記憶體。

我們在XML裡新增下面這個配置即可:

<memtune>
      <hard_limit unit='KiB'>9437184</hard_limit>
      <soft_limit unit='KiB'>8388608</soft_limit>
      <swap_hard_limit unit='KiB'>10485760</swap_hard_limit>
</memtune>

注意第四個引數min_guarantee加里面會報錯,虛擬機器啟動不了。

以上幾點就是KVM在記憶體方面的相關除錯設定。作為工程師首先要做的是熟悉底層各種引數,然後根據生產環境和客戶需求做出最優配置,這樣才能得出最強的效能。

效能調優,這個很吃經驗,所以第一步還是熟悉下平臺裡原生有哪些設定引數以及它們的作用吧!

轉載自雲技術實踐微信公眾號,作者寶哥。