參考:
《kvm虛拟化技術 實戰解析與原理》
http://tec.5lulu.com/detail/107mwn4e6aaa684c1.html
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=7934175&id=5679365
1.balloon技術簡介:
通常來說,要改變客戶機的記憶體大小,我們需要關閉客戶機,用qemu-system-x86_64重新配置設定。這個是很不友善的,于是balloon技術出現了。
ballooning(氣球)技術可以在客戶機運作時動态地調整記憶體大小,而不需要關閉客戶機。它是客戶機的balloon driver通過virtio虛拟隊列接口和主控端協同工作來完成的。
balloonDriver的作用在于它既可以膨脹自己使用記憶體大小也可以縮減記憶體使用量(可以縮減至幾近于無),而且被balloon裡面的記憶體客戶機是不可以使用,balloonDriver本身并不直接管理balloon,它的擴容與縮減都是通過virtio隊列由主控端發送信号管理。主控端可以把balloon的記憶體取消映射,拿來給其他客戶機使用,也可以映射回去,并讓balloon縮減,用來增加客戶機記憶體。因為不能使用balloon裡面的記憶體,是以當客戶機的記憶體不足以滿足自身應用時,它要麼使用swap,要麼開啟OOM-killer選擇性殺死一些程序。
簡單地說,類似于,你(客戶機)會裝貨和卸貨,但是至于要裝還是卸,取決于你的老闆(主控端)。而這些貨是幹嘛的怎麼用,那也是老闆的事。你隻有這麼多貨,不夠用怎麼辦?要麼造假(swap)要麼不賣..
ballooning工作過程主要有以下幾步:
(1)hypervisor發送請求到客戶機作業系統讓其縮減一定數量記憶體
(2)客戶機作業系統收到請求
(3)客戶機作業系統利用balloon驅動,縮減記憶體氣球,并發送結果給hypervisor
(4)vmm收到後,取消對balloon記憶體的映射,進而回收記憶體
(5)vmm把這些記憶體自由配置設定到任何需要的地方
(6)vmm也可以按相反的動作,擴充客戶機記憶體
事實上,kvm balloon技術并不完全是你想的那種動态配置設定,它是有記憶體上限的,它是這樣子的:
kvm hypervisor給客戶機指定一個最大記憶體(MAXmemory),這個就是客戶機最多能使用的記憶體大小
客戶機利用balloon驅動生成記憶體氣球
客戶機目前能使用的真實記憶體(currentMemory)的值就是最大記憶體減去氣球記憶體的結果
currentMemory=MaxMemory-ballooning
2.ballooning的使用
balloon需要客戶機virtio驅動的支援,關于怎麼安裝驅動,上篇kvm virtio已有說明,這裡不重複
kvm 下balloon的啟動,是利用-balloon virtio參數來指定,也可以使用-device來配置設定,如:
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
我們可以用類似以下指令來啟動客戶機:
qemu-system-x86_64 -m 4096 -smp 6 -balloon virtio -net nic -net tap,script=/etc/qemu-ifup redhat6.qcow2
其中 -m 指明了MAXmemory的值,我們可以ctrl+alt+2切換到qemu monitor 模式利用info balloon 檢視目前客戶機可用的記憶體大小。利用balloon num設定balloon 可用記憶體大小,比如:
(qemu) info balloon
balloon: actual=4096
(qemu):balloon 2048 #這裡雖然使用的是balloon指令,但是設定的值是currentMemory,而不是記憶體氣球的值
在linux下,可以利用free -m 等指令檢視到記憶體明顯變化。
在windows下,可以利用任務管理器檢視記憶體變化,與linux不同的是,windows下,改變currentMemory的值,任務管理器顯示的記憶體總量并不會減少,而是把已使用量變高。比如:
我們window的記憶體是4G,目前已經用掉213MB,如果此時我們balloon 2048,那麼看到的記憶體總數依然是4G,但是已使用量會從213MB-->2303MB
值得一提的是balloon設定的值不能超過-m指定的MAXMemory的值,一旦超過,則預設設定為MAXMemory的值
3.所謂的balloon記憶體過載使用:
kvm下記憶體過載(能使用超過真實記憶體數量)使用有三種方式:
swapping:就是把硬碟做成虛拟記憶體,這樣能使用的記憶體就額外多了虛拟記憶體部分,大于真實記憶體
page sharing:把各個程序通路到的相同資料塊共享,這樣記憶體隻需要一份資料,進而各個程序所需要的記憶體數量加起來大于真實記憶體
ballooning:利用每個主機不同時段負載不同這個特點實作,具體如下:
我們知道,很多不同功能的主機不同時段負載不一樣,比如提供OA高的主機白天負載比較高,提供娛樂的主機晚上負載比較高,是以一般平均負載不會太高。假設我們有A、B、C、D、E 5台客戶機,工作在8G記憶體的主控端上,他們的高峰期都需要2G的記憶體,而低峰期隻需要512M不到的記憶體,假設A、B、C白天很忙,晚上很閑,而E、F白天很閑,晚上很忙,那麼我們可以利用balloon技術,每台設定MAXMemory 2G,然後:
白天:A、B、C的balloon設定為2G,EF 512M
總共:2Gx3+512Mx2=7G
晚上:A、B、C 各512M EF 1G
總共:512Mx3+2Gx2=5632M
這樣,我們使用8G記憶體完成了看起來要10G才能運作的客戶機,而且還有富餘記憶體,很好地實作了記憶體過載使用
4.virtio_net的使用
1.檢視kvm是否支援virtio
[root@localhost kvm_vhost]# qemu-system-x86_64 -net nic,model=?
qemu: Supported NIC models: ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio
2.啟動客戶機,(客戶機沒驅動的參考上一篇,kvm virtio功能配置)
qemu-system-x86_64 -m 4096 -smp 6 -balloon virtio -net nic,model=virtio -net tap,script=/etc/qemu-ifup xp.qcow2 -usb -usbdevice tablet
3.主控端中TSO和GSO的設定
根據Redhat文檔的接受,關閉GSO和TSO可以使半虛拟化網絡驅動的性能更加優化,操作如下:
(1)利用brctl show找出供客戶機使用的真實網絡接口,這裡是em1
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
br08 000.02046d 871562 yes em1
tap0
(2)ethtool -k eth0檢視GSO和TSO狀态
[root@localhost ~]# ethtool -k em1
...
tcp-segmentation-offload: on#這個是TSO狀态
generic-segmentation-offload: on#這個是GSO狀态
(3)關閉gso和tso
[root@localhost ~]# ethtool -K em1 gso off
[root@localhost ~]# ethtool -K em1 tso off
[root@localhost ~]# ethtool -k em1
tcp-segmentation-offload: off#這個是TSO狀态
generic-segmentation-offload: off#這個是GSO狀态
5.使用vhost_net後端驅動
前面所提到virtio在主控端中的後端處理程式(backend)一般是由使用者空間的qemu提供的,如果能把對網絡i/o請求的後端處理能夠在核心空間完成,那麼效率會提高很多。在比較新的核心中有一個叫做“vhost-net”的驅動子產品,它工作在核心中,利用它可以讓virtio的後端處理程式的内容在核心中完成,進而提高效率。
與vhost_net相關的選項是-net tap ,它的幾個參數說明如下
-net tap,[vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostforce=on|off]
vnet_hdr=on|off :是否打開tap裝置的iff_vnet_hdr辨別。這個辨別表示允許發送或接受大資料包僅做部分的檢查和校驗,開啟的話可以提高virtio_net驅動的吞吐量
vhost=on|off :是否開啟vhost-net這個核心空間的後端驅動,隻對MIS-X中斷的virtio客戶機有效
vhostforce=on|off :是否強制vhost作為非MIS-X中斷的客戶機後端處理程式
vhostfs=h:設定去連結已經打開vhost的網絡裝置
vhost_net需要主控端的支援,是以可以lsmod |grep vhost_net檢視有沒有加載這個子產品,沒有的話modprobe vhost_net,如果核心不這個子產品,那麼需要重新編譯核心
使用vhost_net驅動的客戶機啟動指令如下:
qemu-system-x86_64 /home/kvm_vhost/xp.qcow2 -net nic,model=virtio -net tap,vhost=on -usb -usbdevice tablet
需要額外說明的是,如果使用libvirt時,xml配置指定的後端驅動名為qemu而不是vhost(這個我還沒用過,存疑..沒特殊聲明的都是自己測試過的,請放心使用)
6.使用virtio_blk
virtio_blk啟動沒什麼好說的,利用-drive file=xx.img,if=virtio即可,指令如下:
qemu-system-x86_64 -drive file=/home/kvm_vhost/redhat6.qcow2,if=virtio -net nic,model=virtio -net tap,vhost=on -curses
有一點需要注意的是:使用virtio_blk後,裝置會被識别為vda的形式,這可能會使原來fstab上的交換分區失效,比如:
原來的fstab 交換分區配置:
/dev/hda2 swap swap defaults 0 0
解決方法:
改為: /dev/vda2 swap swap defaults 0 0
7.kvm_clock配置
之是以有這個配置是因為客戶機的中斷并非真正的中斷,而是通過主控端向客戶機注入的虛拟中斷,是以中斷有可能不能立即傳遞給一個客戶機的所有vcpu,這就可能導緻中斷需要的時間精确性得不到保證,這對一些應用來說是不行的。
kvm通過kvm_clock向客戶機提供精确的system time和wall time來解決這個問題,這個需要較新的硬體平台支援,預設是啟動的。可以通過檢視主控端中的CPU資訊的contabt_tsc辨別來檢視硬體是否支援,通過檢視核心編譯配置檔案來了解是否支援kvm_clock
grep constant_tsc /proc/cpuinfo
grep -i paravirt_guest /boot/config-2.6.32-431.el6.x86_64
grep -i kvm_clock /boot/config-2.6.32-431.el6.x86_64
如果結果為y的話,就代表支援,預設qemu-system會讓客戶機使用kvm_clock作為時鐘來源,可以在客戶機中使用: dmesg |grep -i kvm_clock 檢視是否有對應結果
本文轉自biao007h51CTO部落格,原文連結: http://blog.51cto.com/linzb/1878953,如需轉載請自行聯系原作者