我們說完CPU方面的優化,接着我們繼續第二塊內容,也就是內存方面的優化。內存方面有以下四個方向去着手:
- EPT 技術
- 大頁和透明大頁
- KSM 技術
- 內存限制
1. EPT技術
EPT也就是擴展頁表,這是intel開創的硬件輔助內存虛擬化技術。我們知道內存的使用,是一個邏輯地址跟物理地址轉換的過程。虛擬機內部有邏輯地址轉成成物理地址的過程,然后再跳出來,虛擬機這塊內存又跟宿主機存在邏輯到物理的轉換。有了EPT技術,那么能夠將虛擬機的物理地址直接翻譯為宿主機的物理地址,從而把后面那個轉換過程去掉了,增加了效率。
那么這項技術,現在的服務器都支持,只要在BIOS打開了intel 的VT設置,那么這個也一起打開了。
所以這個基於硬件的優化,目前不需要做額外的什么操作。
2. 大頁和透明大頁
我們先解釋什么叫大頁。
所謂的大頁指的是內存的大頁面。當然,有大頁面必然有對應的小頁面… 我們知道內存采用的是分頁機制,當初這個機制提出的時候,計算機的內存大小也就幾十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
運行了這個命令系統重啟的話,大頁的數量也將是保持2000,不會變。
接下來,我們還得把大頁進行掛載,我們運行:
1
|
# mount -t hugetlbfs hugetlbfs /dev/hugepages
|
這個hugetlbfs 是一種特殊文件系統,那至於為什么采用這樣的文件系統是因為這樣花費的代價小。
那么通過這幾步操作,開啟->設置大頁數量->掛載, 那么宿主機這塊就沒什么問題了。
如果我們KVM里面的某個虛擬機要使用宿主機的大頁,那么我們還得做如下操作:
- 重啟下libvirtd服務
- 虛擬機也開啟透明巨型頁
- 關閉虛擬機編輯虛擬機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里剛才添加的配置。
剛才的操作,我們只是針對一個虛擬機的,也就是說我們把大頁面賦給了一個虛擬機。如果我們要賦予多個虛擬機怎么辦?
那么要讓大頁同時讓多個虛擬機享用,有以下兩步要做:
- 給NUMA 各個node節點分配多個2MB或者1GB的大頁
- 編輯虛擬機xml文件以使用node里分配好的大頁
我們可以運行下面兩個命令就可以給宿主機各個NUMA Node分配大頁
1
2
|
# echo 4 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages
# echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
|
這兩個命令的意思就是先給node0里分配4個1GB的大頁,然后再給node1分配1024個2MB的大頁。
然后執行相關掛載操作,這跟剛才我們做的操作類似:
1
2
3
4
|
# mkdir /dev/hugepages1G
# mount -t hugetlbfs -o pagesize=1G none /dev/hugepages1G
# mkdir /dev/hugepages2M
# mount -t hugetlbfs -o pagesize=2M none /dev/hugepages2M
|
掛載成功后,重啟下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>
紅色的部分就是要添加的參數,size是1,表示第一個使用的page;然后單位unit是G,nodeset=”0-3,5″ 意思是虛擬機的NUMA node0,node1, node2 , node3和node5將使用1GB的大頁 ; 虛擬機的node4將用2MB的大頁。
注意,這里的nodeset指的是虛擬機的節點,同時還要注意的是,如果宿主機大頁面不夠用了,你這樣配置了,虛擬機是會起不來的。
以上就是給虛擬機分配大頁的方法。當然如果你想把宿主機的大頁關閉,只要執行:
1
2
|
# sysctl vm.nr_hugepages=0
# umount hugetlbf
|
接下來我們講下透明大頁。
從Centos6開始,linux系統自帶了一技術叫透明巨型頁(transparent huge page),它允許所有的空余內存被用作緩存以提高性能,而且這個設置是默認開啟的,我們不需要手動去操作。
Centos下,我們用cat /sys/kernel/mm/transparent_hugepage/enabled可以查看
我們看到這個中括號把這個always括起來了,說明這機器的透明巨型頁的功能是打開的。當有512個頁面可以整合的時候,就會合成一個2MB的大頁;如果是在括號把never括起來了,那么就是關閉狀態;madvise的話就是避免改變內存占用。
當然,如果你想改變透明巨型頁的狀態,比如說關閉它,那么運行下面的命令即可:
1
|
# echo never >/sys/kernel/mm/transparent_hugepage/enabled
|
最后要注意的是透明巨型頁跟剛才我們說的hugetlbfs 文件掛載大頁是不沖突的,如果你沒做任何大頁的指定和掛載,那么KVM就會使用透明大頁的方式。
那么說到這,大家就會疑問,既然有透明大頁,我為何還要費勁的去做相關大頁的指定? 其實這兩種方式都差不多,區別就是一個是手動的一,個是自動的。如果你對你宿主機資源把握的更加精准,推薦的還是手動指定。
3. KSM 技術
KSM是什么呢?KSM(Kernel SamePage Merging),也就是所謂的相同頁面內存壓縮技術。
KSM服務在linux系統里默認是開啟的,它的作用就是讓內存利用的更加高效,我們知道內存是分頁的,如果多個程序中用的內存都是相同的頁面,那么KSM就會把相同的內存合並,這樣就能騰出更多的空間。
KSM在系統里有個守護進程,它的作用就是不斷的掃描宿主機的內存情況,檢測有相同的頁面就會合並,這或多或少會消耗CPU。
下面有幾個命令設置大家要了解:
首先是開關KSM服務:
1
2
3
4
|
systemctl start|stop ksmd
systemctl start|stop ksmtuned
systemctl enable|disable ksmd
systemctl enable|disable ksmtuned
|
如果你的環境,內存資源比較豐富,VM又不多,這個功能開不開啟都無所謂;如果不夠,又想跑多一點的虛擬機,那么可以打開這個功能。但是你一定要注意,這個是一種內存超用的方案,如果一台宿主機里大部分虛擬機內存變化比較頻繁,那么要慎重開啟,因為KSM會頻繁的做內存掃描,不停的做內存合並操作,這會大量的消耗CPU資源,如果內存不夠還會用到swap,那么最終會嚴重影響虛擬機性能。
當然,也有設置能讓虛擬機不受宿主機KSM的影響,具體操作如下:
編輯虛擬機的XML文件,添加:
<memoryBacking>
<nosharepages/>
</memoryBacking>
這樣,這個KSM就不會去合並這個虛擬機的內存了。
總的來說,如果你的環境硬件配置比較高,同時又追求VM數量,把KSM打開是一個很不錯的選擇(但是一定要做好相關資源的實時監控,特別是CPU)。在筆者維護過的項目中,遇到過只追求數量而不追求性能的場景,當時我們就開啟了KSM服務,服務器配置是雙路E5-2690 v3@2.60GHz 48core、512G內存,當每台計算節點到80個VM的時候(VM大部分配置為4c8G,windows和linux各占50%)。用htop命令監控查看CPU每個核基本上都是99%滿負載,此時,虛擬機體驗十分不好,后來降到60個左右,CPU負荷在60%-70%,這樣情況才有明顯好轉。
所以,用不用KSM視你自己的生產環境和客戶需求具體而定,這配置還是得慎重。
4. 內存限制技術
通過虛擬機內存限制,可以讓虛擬機的內存使用限制在一定范圍內。
那么這個操作有什么作用呢?比如你的一台KVM宿主機,里面跑着多個業務的虛擬機,有的虛擬機業務比較大,吃得內存多,有的業務比較低,用不了多少內存,那么我們可以通過內存限制技術來手動調節宿主機的內存分配。
當然這里要說明的是,使用這個必須對你虛擬化環境特別清楚,比如宿主機平時的負載情況以及各個虛擬機的負載情況。
那么具體如何操作呢?我們通過memtune命令或者通過改虛擬機的XML文件來設定內存的限制。
這個memtune命令有以下4個參數
hard_limit:強制設置虛擬機最大使用內存,單位為KB
soft_limit:可用最大內存,單位為KB
swap_hard_limit:虛擬機最多使用的內存加上swap的大小,單位為KB
min_guarantee:強制設置虛擬機最低使用的內存,單位為KB
最后一個參數雖然OPTIONS里有列出,但是實測是發現CentOS7.0 以上系統不能支持,執行的時候會報下面這樣的錯誤:
centos6 雖然不會報這個錯,但是這命令貌似也不會有實際效果
官方解釋這是一個bug,大家可以參考下面的鏈接:
https://bugzilla.redhat.com/show_bug.cgi?id=1122455
–config : 寫入配置文件中,虛擬機重啟后生效
–live :讓設置立即生效,但是虛擬機重啟后,效果消失 (如果不加–config –live –current 那么默認是這個)
–current :影響關機或者運行狀態的虛擬機,如果當前虛擬機正在運行,那么虛擬機停止后,效果會消失
例:
1
2
3
4
5
6
7
8
|
# 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
1
|
# 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在內存方面的相關調試設置。作為工程師首先要做的是熟悉底層各種參數,然后根據生產環境和客戶需求做出最優配置,這樣才能得出最強的性能。
性能調優,這個很吃經驗,所以第一步還是熟悉下平台里原生有哪些設置參數以及它們的作用吧!
參考鏈接:
http://blog.csdn.net/summer_liuwei/article/details/6013255
https://www.ibm.com/developerworks/cn/linux/l-cn-hugetlb/
http://lduan.blog.51cto.com/5428084/1716188
http://www.oracle.com/technetwork/cn/articles/servers-storage-dev/hugepages-2099009-zhs.html
https://access.redhat.com/documentation/zh-CN/Red_Hat_Enterprise_Linux/7/html/Virtualization_Tuning_and_Optimization_Guide/chap-Virtualization_Tuning_Optimization_Guide-Introduction.html#sect-Virtualization_Tuning_Optimization_Guide-Introduction-KVM_Overview
原文:雲技術實踐
http://syswift.com/100.html