[ kvm ] 學習筆記 4:KVM 高級功能詳解

1. 半虛擬化驅動

1.1 virtio 概述

KVM 是必須使用硬件虛擬化輔助技術(如 Intel VT-x 、AMD-V)的 Hypervisor,在CPU 運行效率方面有硬件支持,其效率是比較高的;在有 Intel EPT 特性支持的平臺上,內存虛擬化的效率也較高。 QEMU/KVM 提供了全虛擬化環境,可讓客戶機不通過任何修改就能運行在 KVM 環境中。不過 KVM 在 I/O虛擬化方面,傳統的方式是使用 QEMU 純軟件的方式來模擬 I/O 設備(如網卡、磁盤、顯卡等),其效率並不很是高。前端

  CPU 和 內存的虛擬化由KVM內核模塊提供,I/O設備虛擬化由QEMU負責實現。node

在KVM中,能夠在客戶機中使用半虛擬化驅動的方式是採用 Virtio 這個 Linux 上的設備驅動標準框架。mongodb

 

徹底虛擬化:GuestOS 運行在物理機上的 Hypervisor 之上,GuestOS 並不知道它已經被虛擬化,並不須要任何修改就能工做;windows

半虛擬化:GuestOS 不只知道它運行在 Hypervisor 之上,還包括讓 GuestOS 更高效的過分到 Hypervisor 的代碼。後端

 

在徹底虛擬化模式中,hypervisor 必須模擬設備硬件,它是在會話的最低級別進行模擬的,儘管在該抽象中模擬很乾淨,但它同時也是最低效的,最複雜的。緩存

在半虛擬化中,GuestOS 和 hypervisor 可以共同合做,讓模擬更加高效,缺點是操做系統知道它被虛擬化,而且須要修改才能工做。安全

 

左圖在傳統的徹底虛擬化環境中,hypervisor必須捕捉這些請求,而後模擬物理硬件的行爲。儘管這也作提供很大的靈活性(即運行未更改的操做系統),但它的效率比較低.bash

右圖,半虛擬化,來賓操做系統知道它運行在hypervisor之上,幷包含了充當當前的驅動程序.hypervisor爲特定的設備模擬實現後端驅動程序.經過在這些前端和後端驅動程序中的virtio,爲開發模擬設備提供標準化接口,從而增長代碼的跨平臺重用率並提升效率.服務器

 

QEMU模擬 I/O 設備基本原理和優缺點網絡

 

使用QEMU模擬 I/O 的狀況下:

  (1)當客戶機中的設備驅動程序(device driver)發起 I/O 操做請求時,KVM模塊中的 I/O 操做捕獲代碼會攔截此次 I/O 請求;

  (2)通過處理後將本次 I/O 請求的信息存放到 I/O 共享頁,並通知用戶控件中的 QEMU 程序;

  (3)QEMU 模擬程序得到 I/O 操做的具體信息以後,交由硬件模擬代碼來模擬出本次的 I/O 操做;

  (4)完成以後,將結果放回到 I/O 共享頁,並通知KVM 模塊中的 I/O 操做捕獲代碼;

  (5)由 KVM 模塊中的捕獲代碼讀取 I/O 共享頁中的操做結果,並把結果返回到客戶機中。

在這個過程當中,QEMU進程在等待I/O時被阻塞,當客戶機經過 DMA 訪問大塊 I/O時,QEMU模擬程序將不會把操做結果放到I/O共享頁中,而是經過內存映射的方式將結果直接寫到客戶機的內存中去,而後經過KVM模塊告訴客戶機DMA操做已經完成。

QEMU 模擬 I/O 設備的方式,其優勢是能夠經過軟件模擬出各類各樣的硬件設備,包括一些不經常使用的或者很老很經典的設備,並且它不用修改客戶機操做系統,就能夠實現模擬設備在客戶機中正常工做。 在KVM客戶機中使用這種方式,對於解決手上沒有足夠設備的軟件開發及調試有很是大的好處。而它的缺點是,每次 I/O 操做的路徑比較長,有較多的 VMEntry、VMExit發生,須要屢次上下文切換(context switch),也須要屢次數據複製,因此它的性能較差。

 

半虛擬化 virtio 的基本原理和優缺點

其中前端驅動(frondend,如 virtio-blk、virtio-net等)是在客戶機中存在的驅動程序模塊,然後端處理程序(backend)是在 QEMU中實現的。

在這先後端驅動之間,還定義了兩層來支持客戶機與 QEMU 之間的通訊:

  virtio:虛擬隊列接口,在概念上將前端驅動程序附加到後端處理程序,一個前端驅動程序可使用 0 個或 多個隊列,具體數據取決於需求;

  例如:virtio-net 網絡驅動程序使用兩個虛擬隊列(一個用於接收、另外一個用於發送),而virtio-blk塊驅動程序僅使用一個虛擬隊列。虛擬隊列實際上被實現爲跨越客戶機操做系統和hypervisor的銜接點,但它能夠經過任意方式實現,前提是客戶機操做系統和virtio後端程序都遵循必定的標準,以相互匹配的方式實現它。

  virtio-ring:實現了環形緩衝區(ring buffer),用於保存前端驅動和後端處理程序執行的信息,而且它們能夠一次性保存前端驅動的屢次I/O請求,而且交由後端去批量處理,最後實際調用宿主機中設備驅動實現物理上的I/O操做,這樣作就能夠根據約定實現批量處理而不是客戶機中每次I/O請求都須要處理一次,從而提升客戶機與hypervisor信息交換的效率。

virtio 半虛擬化驅動的方式,能夠得到很好的I/O性能,其性能幾乎能夠達到和 native(非虛擬化環境中的原生系統)差很少的I/O性能。因此,在使用 kvm 時,若是宿主機內核和客戶機都支持 virtio的狀況下,通常推薦使用 virtio 達到更好的性能。

 

virtio 缺點:

  必需要安裝特定的virtio驅動使其知道是運行在虛擬化環境中,且按照 virtio 的規定格式進行數據傳輸,不過客戶機中可能有一些老的Linux系統不支持virtio 和主流windows系統須要安裝特定的驅動才支持 virtio,不過,較新的一些Linux發行版(如RHEL 6.三、Fedora 17等)默認都將virtio相關驅動編譯爲模塊,可直接做爲客戶機使用virtio,並且對於主流Windows系統都有對應的virtio驅動程序可供下載使用。

virtio是對半虛擬化hypervisor中的一組通用模擬設備的抽象.該設置還容許hypervisor導出一組通用的模擬設備,並經過一個通用的應用程序接口(API)讓它們變得可用.有了半虛擬化hypervisor以後,來賓操做系統可以實現一組通用的接口,在一組後端驅動程序以後採用特定的設備模擬.後端驅動程序不須要是通用的,由於它們只實現前端所需的行爲.

注意,在現實中(儘管不須要),設備模擬發生在使用 QEMU 的空間,所以後端驅動程序與 hypervisor 的用戶空間交互,以經過 QEMU 爲 I/O 提供便利。QEMU 是一個系統模擬器,它不只提供來賓操做系統虛擬化平臺,還提供整個系統(PCI 主機控制器、磁盤、網絡、視頻硬件、USB 控制器和其餘硬件元素)的模擬。   

 

1.2 安裝 virtio 驅動

Linux 2.6 及以上版本內核都是支持 virtio 的。因爲 virtio 的後端處理程序是在位於用戶空間的 QEMU 中實現的,因此,在宿主機中只須要比較新的內核便可,不須要特別的編譯與 virtio 相關的驅動。

 

1.2.1 Linux 中的 virtio 驅動

[root@192.168.118.14 ~]#lsmod | egrep virt
virtio_balloon         13664  0 
virtio_blk             18156  3 
virtio_console         28114  0 
virtio_net             28024  0 
virtio_pci             22913  0 
virtio_ring            21524  5 virtio_blk,virtio_net,virtio_pci,virtio_balloon,virtio_console
virtio                 15008  5 virtio_blk,virtio_net,virtio_pci,virtio_balloon,virtio_console

其中,virtio,virtio_ring、virtio_pci 等驅動程序提供了對 virtio API 的基本支持,是使用任何 virtio 前端驅動都必須使用的,並且它們的加載還有必定的順序,應該按照 virtio、virtio_ring、virtio_pci 的順序加載,而 virtio_net、virtio_blk 這樣的驅動能夠根據實際須要進行選擇性的編譯和加載。

 

1.3 使用 virtio_balloon

 

(1)ballooning 簡介

一般來講,要改變客戶機佔用的宿主機內存,要先關閉客戶機,修改啓動的內存配置,而後重啓客戶機才能實現。而內存的 ballooning (氣球)技術能夠在客戶機運行時動態的調整它所佔用的宿主機內存資源,而不須要關閉客戶機。

ballooning 技術形象的在客戶機佔用的內存中引入氣球(balloon)的概念。氣球中的內存是能夠供宿主機使用的,因此,當宿主機內存緊張,空餘內存很少時,能夠請求客戶機回收利用已分配給客戶機的部份內存,客戶機就會釋放其空閒的內存,此時若客戶機空閒內存不足,可能還會回收部分使用中的內存,可能會將部份內存換出到客戶機的交換分區(swap)中,從而使內存氣球充氣膨脹,進而使宿主機回收氣球中的內存用於其餘進程。反之,當客戶機中內存不足時,也可讓宿主機的內存氣球壓縮,釋放出內存氣球中的部份內存,讓客戶機使用更多的內存。

目前不少虛擬機,如KVM 、Xen、VMware 等,都對 ballooning 技術提供了支持。

 

(2)KVM 中 ballooning 的原理及優劣勢

KVM 中 ballooning 的工做過程主要有以下幾步:

  1. Hypervisor 發送請求到客戶機操做系統讓其歸還必定數量的內存給 Hypervisor;

  2. 客戶機操做系統中 virtio_balloon 驅動接收到 Hypervisor;

  3. virtio_balloon 驅動使客戶機的內存氣球膨脹,氣球中的內存就不能被客戶機訪問。若是此時客戶機中內存剩餘量很少,而且不能讓內存氣球膨脹到足夠大的以知足 Hypervisor 的請求,那麼 virtio_balloon 驅動也會盡量多的提供內存使氣球膨脹,儘可能去知足 Hypervisor 的請求中的內存數量;

  4. 客戶機操做系統歸還氣球中的內存給 Hypervisor;

  5. Hypervisor 能夠將從氣球中得來的內存分配到任何須要的地方;

  6. 即便從氣球中獲得的內存沒有處於使用中,Hypervisor 也能夠將內存返還給客戶機中,這個過程爲:Hypervisor 發請求到客戶機的 virtio_balloon 驅動;這個請求使客戶機操做系統壓縮內存氣球;在氣球中的內存被釋放出來,從新由客戶機訪問和使用。

 

ballooning 在節約內存和靈活分配內存方面有明顯的優點:

  1. 由於ballooning 可以被控制和監控,因此可以潛在的節約大量的內存;

  2. ballooning 對內存的調節很靈活,便可以精細的請求少許內存,又能夠粗曠的請求大量的內存;

  3. Hypervisor 使用 ballooning 讓客戶機歸還部份內存,從而緩解其內存壓力。並且從氣球中回收的內存也不要求必定要被分配給另外某個進程。

 

從另外一方面來講,KVM 中 ballooning的使用不方便、不完善的地方也是存在的,其缺點以下:
  1. ballooning 須要客戶機操做系統加載 virt_balloon 驅動,然而並不是每一個客戶機系統都有該驅動;

  2. 若是有大量內存須要從客戶機系統中回收,那麼 ballooning 可能會下降客戶機操做系統運行的性能。一方面,內存的減小可能會讓客戶機中做爲磁盤數據緩存的內存被放到氣球中,從而使客戶機中的磁盤I/O訪問增長;另外一方面,若是處理機制不夠好,也可能讓客戶機中正在運行的進程因爲內存不足而執行失敗;

  3. 目前沒有比較方便的、自動化的機制來管理 ballooning,通常採用在 QEMU monitor 中執行 balloon 命令來實現 ballooning。沒有對客戶機的有效監控,沒有自動化的ballooning 機制,這可能會使在生產環境中實現大規模自動化部署不是很方便。

  4. 內存的動態增長或減小,可能會使內存被過分碎片化,從而下降內存使用時的性能。

 

(3)KVM 中 ballooning 使用示例

1. 建立虛擬機
[root@192.168.118.14 ~]#qemu-kvm -smp 1 -m 1024 -balloon virtio /images/cirros-0.3.5-i386-disk.img --nographic

2. 查看 PCI 設備是否加載
# lspci -k
00:00.0 Class 0600: 8086:1237
00:01.0 Class 0601: 8086:7000
00:01.1 Class 0101: 8086:7010 ata_piix
00:01.3 Class 0680: 8086:7113
00:02.0 Class 0300: 1013:00b8
00:03.0 Class 0200: 8086:100e e1000
00:04.0 Class 00ff: 1af4:1002 virtio-pci

能夠發現,00:04.0 Class 00ff: 1af4:1002 virtio-pci 就是 virtio-pci 設備


3. 經過 balloon 調整內存大小

原內存
# free -m 
             total         used         free       shared      buffers
Mem:          1001           12          988            0            0
-/+ buffers:                 12          989
Swap:            0            0            0


使用 qemu-monitor 減小內存大小
(qemu) info balloon
balloon: actual=1024
(qemu) balloon 512
(qemu) info balloon
balloon: actual=512

4. 查看調整後的內存大小
# free -m 
             total         used         free       shared      buffers
Mem:          489           12          477            0            0
-/+ buffers:                 12          234
Swap:            0            0            0

 

總的來講,對於 ballooning 技術,目前尚未徹底成熟的管理控制工具,大規模部署很是不方便,並且性能沒有很大的提高,建議慎用。

 

1.4 使用 virtio_net

在選擇KVM中的網絡設備時,通常來講優先選擇半虛擬化的網絡設備而不是模擬純軟件模擬的設備使用 virtio_net 半虛擬化驅動,能夠提升網絡吞吐量和下降網絡延遲,從而讓客戶機中網絡達到幾乎和非虛擬化系統中使用原生網卡的網絡差很少的性能。

(1)檢查 QEMU 是否支持 virtio 類型的網卡

# qemu-kvm -smp 2 -m 512m -net nic,model=?
qemu: Supported NIC models: ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio

(2)啓動客戶機時,指定分配 virtio 網卡設備

# qemu-kvm -smp 2 -m 512m \
-drive file=/root/cirros-0.3.5-i386-disk.img,if=virtio -net nic,model=virtio -net tap,name=tap0,script=no -daemonize 

 使用 virtio_net 依然是較低的性能,能夠檢查宿主機系統中對 GSO 和 TSO 特性的設置。關閉 GSO 和 TSO 可使用半虛擬化網絡驅動的性能更加優化。

ethtool -K eno1 gso off
ethtool -K eno1 tso off

 

用 vhost_net 後端驅動

前面提到 virtio 在宿主機中的後端處理程序(backend)通常是由用戶空間的 QEMU 提供的,然而,若是對於網絡 IO 請求的後端處理可以在內核空間來完成,則效率更高,會提升網絡吞吐量和減小網絡延遲。在比較新的內核中有一個叫作 「vhost_net」的驅動模塊,它做爲一個內核級別的後端處理程序,將 virtio-net的後端處理任務放到內核空間執行,從而提升效率。

qemu-kvm -smp 2 -m 512m \
-drive file=/root/cirros-0.3.5-i386-disk.img,if=virtio \
-net nic,model=virtio,macaddr=52:54:00:ac:0f:11 \
-net tap,name=tap0,vnet_hdr=on,vhost=on,script=no \
-daemonize

通常來講,使用 vhost-net 做爲後端處理驅動能夠提升網絡的性能。不過,對於一些使用 vhost-net 做爲後端的網絡負載類型,可能使其性能不升反降。特別是從宿主機到其客戶機之間的 UDP 流量,若是客戶機處理接受數據的速度比宿主機發送的速度要慢,這時就容易出現性能降低。在這種狀況下,使用 vhost-net 將會使 UDP socket 的接受緩衝區更快的溢出,從而致使更多的數據包丟失。所以在這種狀況下不使用vhost-net,讓傳輸速度稍慢一點,反而會提升總體的性能。

 

1.5 使用 virtio_blk

virtio_blk 驅動使用 virtio API 爲客戶機提供了一個高效訪問塊設備 I/O 方法。在 QEMU/KVM 中對塊設備使用 virtio,須要在兩方面進行配置:客戶機中的前端驅動模塊 virtio_blk 編譯爲內核模塊,能夠做爲客戶機直接使用 virtio_blk。

啓動一個使用 virtio_blk 做爲磁盤驅動的客戶機,其 qemu-kvm 命令行以下:

[root@192.168.118.14 ~]#qemu-kvm -smp 2 -m 512m -drive file=/images/cirros-0.3.5-i386-disk.img,if=virtio
未使用 virtio 模塊的虛擬機
# lsblk 
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0  39.2M  0 disk 
`-sda1   8:1    0  31.4M  0 part /


使用 virtio 模塊的虛擬機
# lsblk 
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
vda    253:0    0  39.2M  0 disk 
`-vda1 253:1    0  31.4M  0 part /

 

2. 動態遷移

 

2.1 動態遷移概念

遷移(migration)包括系統總體的遷移和某個工做負載的遷移。系統總體遷移,是將系統上的全部軟件徹底複製到另外一臺物理硬件機器上。而工做負載的遷移,是將系統上的某個工做負載轉移到另外一臺物理機上繼續運行。服務器系統遷移的做用在於簡化了系統維護管理,提升了系統負載均衡,加強了系統容錯性並優化了系統電源管理。

在虛擬化環境中的遷移,又分爲 靜態遷移(static migration)和動態遷移(live migration) 靜態遷移和動態遷移最大的區別:靜態遷移有明顯一段時間客戶機中的服務不可用,而動態遷移則沒有明顯的服務暫停時間。

虛擬化中的靜態遷移,也能夠分爲兩種,一種是關閉客戶機後,將其硬盤鏡像複製到另外一臺宿主機上而後恢復啓動起來,這種遷移不能保留客戶機中運行的工做負載;另外一種是兩臺宿主機共享存儲系統,只須要暫停客戶機後,複製其內存鏡像到另外一臺宿主機中恢復啓動,這種遷移能夠保持客戶機遷移前的內存狀態和系統運行的工做負載。

動態遷移,是指在保證客戶機上應用服務正常運行的同時,讓客戶機在不一樣的宿主機之間進行遷移,其邏輯步驟與前面靜態遷移幾乎一致,有硬盤存儲和內存都複製的動態遷移,也有僅複製內存鏡像的動態遷移。不一樣的是,爲了保證遷移過程當中客戶機服務的可用性,遷移過程僅有很是短暫的停機時間。動態遷移容許系統管理員將客戶機在不一樣物理機上遷移,同時不會斷開訪問客戶機中服務的客戶端或應用程序的鏈接。一個成功的動態遷移,須要保證客戶機的內存、硬盤存儲、網絡鏈接在遷移到目的的主機後依然保持不變,並且遷移過程的服務暫停時間較短。

 

2.2 動態遷移的效率和應用場景

虛擬機遷移主要加強了系統的可維護性,其主要目標是在客戶沒有感受的狀況下,將客戶機遷移到了另外一臺物理機上,並保證其各個服務都正常使用。能夠從以下幾個方面來衡量虛擬機的遷移的效率:

(1)總體遷移時間:從源主機中遷移操做開始到客戶機被遷移到目的主機並恢復其服務所花費的時間;

(2)服務器停機時間:在遷移過程當中,源主機和目的主機上客戶機的服務都處於不可用狀態的時間,此時源主機上客戶機已暫停服務,目的主機上客戶機還未恢復服務;

(3)對服務的性能影響:不只包括遷移後的客戶機中應用程序的性能與遷移前相比是否有所降低,還包括遷移後對目的主機上的其餘服務的性能影響。

 

動態遷移的好處很是明顯,動態遷移的幾個場景:

(1)負載均衡:當一臺物理服務器的負載較高時,能夠將其上運行的客戶機動態遷移到負載較低的宿主機服務器中,以保證客戶機的服務質量(QoS)。

(2)解除硬件依賴:升級主機,添加某些硬件設備時,能夠將宿主機上運行的客戶機很是安全高效的動態遷移到其餘宿主機上。

(3)節約能源:經過動態遷移將宿主機上的客戶機集中遷移到其中幾臺服務器上。

(4)實現客戶機地理位置上的遠程遷移:好比跨地域性的遷移。

 

2.3 KVM 動態遷移原理與實踐

在KVM 中,即支持離線的靜態遷移,又支持在線的動態遷移。對於靜態遷移,能夠在源宿主機上某客戶機的 QEMU monitor中,用 "savevm my_tag" 命令來保存一個完整的客戶機鏡像快照(標記爲 my_tag),而後在源宿主機中關閉或暫停該客戶機,而後將該客戶機的鏡像文件複製到另一臺宿主機中,用於源主機中啓動客戶機時以相同的命令啓動複製過來的鏡像,在其 QEMU monitor 中用 "loadvm my_tag" 命令來恢復剛纔保存的快照便可徹底加載保存快照時的客戶機狀態。這裏的 "savevm" 命令保存的完整客戶機狀態包括:CPU 狀態、內存、設備狀態、可寫磁盤中的內容。注意:這種保存快照的方法須要 qcow二、qed 等格式的磁盤鏡像文件,由於只有它們才支持快照這個特性。

若是源宿主機和目的宿主機共享存儲系統,則只須要經過網絡發送客戶機的vCPU 執行狀態、內存中的內容、虛擬設備的狀態到目的主機上。不然,還須要將客戶機的磁盤存儲發送到目的主機上去。

 

在不考慮磁盤存儲複製的狀況下(基於共享存儲系統),KVM 動態遷移的具體遷移過程爲:在客戶機動態遷移開始後,客戶機依然在原宿主機上運行,與此同時,客戶機的內存頁被傳輸到目的主機之上。QEMU/KVM 會監控並記錄下遷移過程當中全部已被傳輸的內存頁的任何修改,並在全部的內存頁都被傳輸完成後即開始傳輸在前面過程當中內存頁的更改內容。QEMU/KVM 也會估計遷移過程當中的傳輸速度,當剩餘的內存數據量可以在一個可設定的時間週期內傳輸完成之時,QEMU/KVM 將會關閉源宿主機上的客戶機,再將剩餘的數據量傳輸到目的主機上去,最後傳輸過來的內存內容在目的宿主機上恢復客戶機的運行狀態。至此,KVM的一個動態遷移操做就完成了。

當客戶機中內存使用量很是大且修改頻繁,內存中數據被不斷修改的速度大於 KVM 可以傳輸的內存速度之時,動態遷移過程是不會完成的,這時要進行遷移只能進行靜態遷移。

 

對於 KVM 動態遷移,有以下幾點建議和注意事項:

  (1)源宿主機和目的宿主機之間儘可能用網絡共享的存儲系統來保存客戶機鏡像,儘管KVM動態遷移也支持連通磁盤鏡像一塊兒複製。共享存儲(如NFS)在源宿主機和目的宿主機上的掛載位置必須一致;

  (2)爲了提升動態遷移的成功率,儘可能在同類型 CPU 的主機上面進行動態遷移;

  (3)64 位的客戶機只能在 64位宿主機之間遷移,而 32 位客戶機能夠在 32 位宿主機和 64 位宿主機之間遷移;

  (4)動態遷移的源宿主機和目的宿主機對 NX 位的設置是相同的,要麼關閉狀態,要麼打開狀態;

  (5)在進行動態遷移時,被遷移客戶機的名稱是惟一的,在目的宿主機上不能與源宿主機中被遷移客戶機同名的客戶機存在;

  (6)目的宿主機和源宿主機的軟件配置儘量是相同,例如,爲了保證動態遷移後客戶機中網絡依然正常工做,須要在目的宿主機上配置和源宿主機相同名稱網橋,並讓客戶機以橋接的方式使用網絡。

 

示例:使用 qemu-kvm 動態遷移

 

NFS 主機配置:

[root@192.168.118.16 ~]#mkdir /images
[root@192.168.118.16 ~]#mv cirros-0.3.5-i386-disk.img  /images/
[root@192.168.118.16 ~]#yum install nfs-utils -y
[root@192.168.118.16 ~]#cat /etc/exports
/images *(rw,async,no_root_squash)

[root@192.168.118.16 ~]#systemctl start rpcbind
[root@192.168.118.16 ~]#systemctl start nfs-server

 

源宿主機配置:

[root@192.168.118.14 ~]#yum install nfs-utils -y
[root@192.168.118.14 ~]#mount 192.168.118.16:/images /images/
[root@192.168.118.14 ~]#qemu-kvm -smp 2 -m 512m /images/cirros-0.3.5-i386-disk.img -monitor stdio

目的遷移主機操做以下:

[root@192.168.118.15 ~]#yum install nfs-utils -y
[root@192.168.118.15 ~]#mount 192.168.118.16:/images /images/
[root@192.168.118.15 ~]#qemu-kvm -smp 2 -m 512m /images/cirros-0.3.5-i386-disk.img -incoming tcp:0:6666

經過 tigervnc 鏈接:

 

到此,在源宿主機執行:

(qemu) migrate -d tcp:192.168.118.15:6666

 

再次查看,被遷移的主機:

被遷移主機完成後,也存在運行top命令,遷移完成。

 

QEMU/KVM 中也支持增量複製磁盤修改部分數據(使用相同的後端鏡像時)的動態遷移,以及直接複製整個客戶機磁盤鏡像的動態遷移。使用相同後端鏡像文件的動態遷移過程以下,與前面直接使用NFS共享存儲很是相似。

(1)在源宿主機上,根據一個後端鏡像文件,建立一個 qcow2 格式的鏡像文件,並啓動客戶機,命令以下:

[root@192.168.118.14 /images]#qemu-img create -f qcow2 -o backing_file=/images/cirros-0.3.5-i386-disk.img,size=20G kvm1.qcow2
[root@192.168.118.14 ~]#qemu-kvm -smp 2 -m 512m /root/kvm1.qcow2 -monitor stdio

(2)在目的宿主機上,也創建相同的 qcow2 格式的客戶機鏡像,並帶有 "-incoming" 參數來啓動客戶機使其處於遷移監聽狀態:

[root@192.168.118.15 ~]#qemu-img create -f qcow2 -o backing_file=/images/cirros-0.3.5-i386-disk.img,size=20G kvm1.qcow2
[root@192.168.118.15 ~]#qemu-kvm -smp 2 -m 512m /root/kvm1.qcow2 -incoming tcp:0:6666

(3)在源宿主機上的客戶機的 QEMU monitor 中,運行 "migrate -i tcp:192.168.118.15:6666"

注意:有些 qemu-kvm 並不支持 -i 增量遷移,能夠直接使用:migrate tcp:192.168.118.15:6666
(qemu) migrate tcp:192.168.118.15:6666

 

至此,基於相同後端鏡像的磁盤動態遷移就完成,在目的宿主機上能夠看到遷移過來的客戶機已經處於和源客戶機同樣的狀態。

 

3. KSM 技術

在現代操做系統中,共享內存是一個很廣泛應用的概念。如在 Linux 系統中,當使用 fork 函數建立一個進程時,子進程與父進程共享所有的內存,而當子進程或父進程試圖修改它們的共享內存區域時,內核會分配一塊新的內存區域,並將試圖修改的共享內存區域複製到新的內存區域上,而後讓進程去修改複製的內存。這就是著名的「寫時複製」(copy-on-write)技術。而 KSM技術卻與這種內存共享概念有點相反。

KSM 是「Kernel SamePage Merging」縮寫,中文可稱爲「內核同頁合併」。KSM 容許內核在兩個或多個進程之間共享徹底相同的內存頁。KSM 讓內核掃描檢查正在運行中的程序並比較它們的內存,若是發現它們有內存區域或內存頁是徹底相同的,就將相同的內存合併爲一個單一的內存頁,並將其標識爲「寫時複製」。這樣能夠起到節省系統內存使用量的做用。以後,若是有進程試圖去修改被標識爲「寫時複製」的合併的內存頁時,就爲該進程複製出一個新的內存頁供其使用。

在 QEMU/KVM 中,一個虛擬客戶機就是一個 QEMU 進程,因此使用 KSM 也能夠實現多個客戶機之間的相同內存合併。並且,若是在同一宿主機上的多個客戶機運行的是相同的操做系統或應用程序,則客戶機之間的相同內存頁數量就可能還比較大,這種狀況下KSM的做用就更加顯著。在KVM環境下使用 KSM ,KSM還容許KVM 請求哪些相同的內存頁是能夠被共享合併的,因此KSM只會識別併合並哪些不會干擾客戶機運行,不會影響宿主機或客戶機的安全內存頁。可見,在KVM 虛擬化環境中,KSM 可以提升內存的速度和使用效率,具體能夠從如下兩個方面來理解:

(1)在 KSM 的幫助下,相同的內存頁被合併了,減小了客戶機的內存使用量,一方面,內存中的內存更容易被保存到CPU 的緩存中;另外一方面,有更多的內存可用於緩存一些磁盤中的數據。所以,無論是內存的緩存命中率,仍是磁盤數據的緩存命中率都會提升,從而提升了 KVM 客戶機中操做系統或應用的運行速度;
(2)KSM 是內存過載使用的一種較好的方式。KSM 經過減小每一個客戶機實際佔用的內存數,就可讓多個客戶機分配的內存數量之和大於物理內存數量。而對於使用相同的內存量的客戶機,在物理內存量不變的狀況下,能夠在一個宿主機中建立更多客戶機,提升了虛擬化客戶機部署的密度,提升了物理資源的利用效率。

 

KSM 是在 Linux 內核 2.6中被加入到內核主代碼中去的,目前多數流行的 Linux 發行版都已經將 KSM 的支持編譯到內核中了,其內核配置文件中有 「CONFIG_KSM=y」 項:

[root@192.168.118.14 ~]#egrep -i ksm /boot/config-3.10.0-327.el7.x86_64 
CONFIG_KSM=y

Linux 系統的內核進程 ksmd 負責掃描後合併進程的相同內存頁,從而實現 KSM 功能。root 用戶能夠經過 "/sys/kernel/mm/ksm/" 目錄下的文件來配置和監控 ksmd 這個守護進程。KSM 只會去掃描和試圖合併那些應用程序建議爲可合併的內存頁。

KSM 最初就是爲 KVM 虛擬化中的使用而開發的,不過它對非虛擬化的系統依然很是有用。KSM 能夠在KVM 虛擬化環境中很是有效的下降內存使用量,在KSM的幫助下,有人在物理內存爲 16GB 的機器上,用KVM 成功運行了多達 52 個 1GB 內存的windows xp 客戶機。

因爲KSM 對 KVM 宿主機中的內存使用有較大的效率和性能的提升,因此通常建議打開 KSM 功能。,但是,因爲KSM必須有一個或多個進程去檢測和找出哪些內存頁是徹底相同能夠用於合併的。所以,KSM 讓內存使用量下降了,可是 CPU 使用率會有必定程度的升高,也可能會帶來隱蔽的性能問題,須要在實際使用環境中進行適當配置 KSM 的使用,以便達到較好的平衡。

KSM對內存合併而節省內存的數量與客戶機操做系統及其上運行的應用程序有關,若是宿主機上的客戶操做系統及其上的應用程序也相似,節省內存的效果就會很顯著,甚至節省超過 50%的內存都有可能的。反之,若是客戶機操做系統不一樣,且運行的應用程序也大不相同,KSM 節省內存效率很差,可能連 5%都不到。

另外,在使用 KSM 實現內存過載使用時,最好保證系統的交換空間(swap space)足夠大,由於 KSM 將不一樣客戶機的相同內存頁合併而減小了內存使用量,可是客戶機可能因爲須要修改被KSM合併的內存頁,從而使這些被修改的內存被從新複製出來佔用內存空間,所以可能會致使系統內存不足,這是須要足夠的交換空間來保證系統的正常運行。

 

3.1 KSM 操做實踐

內核 KSM 守護進程是 ksmd,配置和監控 ksmd 的文件在 "/sys/kernel/mm/ksm/" 目錄下:

[root@192.168.118.14 ~]#ll /sys/kernel/mm/ksm/
total 0
-r--r--r--. 1 root root 4096 Jul  9 08:21 full_scans
-rw-r--r--. 1 root root 4096 Jul  9 08:21 merge_across_nodes
-r--r--r--. 1 root root 4096 Jul  9 08:21 pages_shared
-r--r--r--. 1 root root 4096 Jul  9 08:21 pages_sharing
-rw-r--r--. 1 root root 4096 Jul  9 08:21 pages_to_scan
-r--r--r--. 1 root root 4096 Jul  9 08:21 pages_unshared
-r--r--r--. 1 root root 4096 Jul  9 08:21 pages_volatile
-rw-r--r--. 1 root root 4096 Jul  9 08:21 run
-rw-r--r--. 1 root root 4096 Jul  9 08:21 sleep_millisecs

說明:
full_scans:記錄已經對全部可合併的內存區域掃描過的次數;
pages_shared:記錄着正在使用中的共享內存頁的數量;
pages_sharing:記錄着有多少數量的內存頁正在使用被合併的共享頁,不包括合併的內存頁自己。這就是實際節省的內存頁數量;
pages_unshared:記錄了守護進程去檢查並試圖合併,卻發現了並無重複內容而不能被合併的內存頁數量;
pages_volatile:記錄了由於其內容很容易變化而不被合併的內存頁;
pages_to_scan:在KSM進程休眠以前會去掃描的內存數量;
sleep_millisecs:ksmd 進程休眠的時間(單位:毫秒),ksmd 的兩次運行之間的間隔;
run:控制 ksmd 進程是否運行的參數,默認值爲0,要激活 ksm 必需要設置其參數爲 1,設置爲0,表示中止運行 ksmd 但保持它已經合併的內存頁;設置爲1,
   表示立刻運行 ksmd進程;設置爲2 表示中止運行 ksmd,並分離已經合併的全部內存頁,可是保持已經註冊爲合併的內存區域給下一次運行使用.

 

經過權限能夠看出, 只有 pages_to_scan , sleep_millisecs, run 這 3 個文件對 root 用戶是可讀可寫的,其他 5 個文件都是 只讀的,能夠向 pages_to_scan 、 sleep_millisecs、 run 這三個文件中寫入自定義的值以便控制 ksmd的運行。

例如:

echo 1200 > /sys/kernel/mm/ksm/pages_to_scan  用來調整每次掃描的內存頁數量
echo 10 > /sys/kernel/mm/ksm/sleep_millisecs  用來設置ksmd兩次運行的時間間隔
echo 1 > /sys/kernel/mm/ksm/run  用來激活ksmd 的運行

 

pages_sharing 的值越大,說明 KSM 節省的內存越多,KSM 效果越好,以下命令計算了節省的內存數量:

[root@mongodb ~]# echo "KSM saved: $(($(cat /sys/kernel/mm/ksm/pages_sharing) * $(getconf PAGESIZE) / 1024 / 1024))MB"
KSM saved: 1159MB

 

在 CentOS 7 系統中,提供了兩個服務 ksm 和 ksmtuned 來動態調節 KSM 的運行狀況,這兩個服務都包含在 qemu-kvm-common 這個 RPM 安裝包中。

[root@192.168.118.14 ~]#systemctl status ksm
● ksm.service - Kernel Samepage Merging
   Loaded: loaded (/usr/lib/systemd/system/ksm.service; enabled; vendor preset: enabled)
   Active: active (exited) since Tue 2019-07-09 09:59:40 CST; 21s ago
  Process: 668 ExecStart=/usr/libexec/ksmctl start (code=exited, status=0/SUCCESS)
 Main PID: 668 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/ksm.service

Jul 09 09:59:40 localhost.localdomain systemd[1]: Starting Kernel Samepage Merging...
Jul 09 09:59:40 localhost.localdomain systemd[1]: Started Kernel Samepage Merging.
[root@192.168.118.14 ~]#systemctl status ksmtuned
● ksmtuned.service - Kernel Samepage Merging (KSM) Tuning Daemon
   Loaded: loaded (/usr/lib/systemd/system/ksmtuned.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2019-07-09 09:59:40 CST; 25s ago
  Process: 680 ExecStart=/usr/sbin/ksmtuned (code=exited, status=0/SUCCESS)
 Main PID: 685 (ksmtuned)
   CGroup: /system.slice/ksmtuned.service
           ├─685 /bin/bash /usr/sbin/ksmtuned
           └─686 sleep 60

Jul 09 09:59:40 localhost.localdomain systemd[1]: Starting Kernel Samepage Merging (KSM) Tuning Daemon...
Jul 09 09:59:40 localhost.localdomain systemd[1]: Started Kernel Samepage Merging (KSM) Tuning Daemon.

當 ksm 服務啓動時: run 文件爲 1

[root@192.168.118.14 ~]#cat /sys/kernel/mm/ksm/run 
1

在 KSM 服務啓動後,KSM 可以共享最多達到系統物理內存一半的內存頁。而 ksmtuned 服務一直保持循環執行,以調用 ksm 服務的運行,其配置文件的 /etc/ksmtuned.conf ,默認配置以下:

[root@192.168.118.14 ~]#cat /etc/ksmtuned.conf 
# Configuration file for ksmtuned.

# How long ksmtuned should sleep between tuning adjustments
# KSM_MONITOR_INTERVAL=60

# Millisecond sleep between ksm scans for 16Gb server.
# Smaller servers sleep more, bigger sleep less.
# KSM_SLEEP_MSEC=10

# KSM_NPAGES_BOOST=300
# KSM_NPAGES_DECAY=-50
# KSM_NPAGES_MIN=64
# KSM_NPAGES_MAX=1250

# KSM_THRES_COEF=20
# KSM_THRES_CONST=2048

# uncomment the following if you want ksmtuned debug info

# LOGFILE=/var/log/ksmtuned
# DEBUG=1

 

在主機內存爲 8 GB 的系統上,使用 Linux 3.10 內核的 CentOS 7 系統做爲宿主機,開始將 ksm 和 ksmtuned 服務暫停,"/sys/kernel/mm/ksm/run" 的默認值爲 0 ,KSM 不生效,而後啓動每一個內存爲 1GB 的 4 個 cirros 客戶機,再次啓動 KSM 和 ksmtuned服務,5分鐘後檢查系統內存的使用狀況以肯定 KSM 效果。腳本及執行以下:

[root@192.168.118.14 ~]#cat test-ksm.sh 
#!/bin/bash
echo "stop ksm"
systemctl stop ksm
systemctl stop ksmtuned
echo "---free -m---"
free -m
for i in {1..3};do
  qemu-img create -f qcow2 -o backing_file="/images/cirros-0.3.5-i386-disk.img" /images/cirros-${i}.qcow2
  echo "starting the No. ${i} guest..."
  qemu-kvm -smp 1 -m 1024m /images/cirros-${i}.qcow2 -daemonize
  sleep 20
done
echo "---free -m---"
sleep 10
free -m
echo "---starting services: ksm and ksmtuned..."
systemctl start ksm
systemctl start ksmtuned

sleep 300

echo "---free -m command output with ksm and ksmtuned running."
free -m

echo "KSM saved: $(($(cat /sys/kernel/mm/ksm/pages_sharing) * $(getconf PAGESIZE) / 1024 / 1024))MB"


*****************執行以下*****************
[root@192.168.118.14 ~]#./test-ksm.sh 
stop ksm
---free -m---
              total        used        free      shared  buff/cache   available
Mem:           7823         115        7565           8         142        7537
Swap:          8063           0        8063
Formatting '/images/cirros-1.qcow2', fmt=qcow2 size=41126400 backing_file='/images/cirros-0.3.5-i386-disk.img' encryption=off cluster_size=65536 lazy_refcounts=off 
starting the No. 1 guest...
VNC server running on `::1:5900'
Formatting '/images/cirros-2.qcow2', fmt=qcow2 size=41126400 backing_file='/images/cirros-0.3.5-i386-disk.img' encryption=off cluster_size=65536 lazy_refcounts=off 
starting the No. 2 guest...
VNC server running on `::1:5901'
Formatting '/images/cirros-3.qcow2', fmt=qcow2 size=41126400 backing_file='/images/cirros-0.3.5-i386-disk.img' encryption=off cluster_size=65536 lazy_refcounts=off 
starting the No. 3 guest...
VNC server running on `::1:5902'
---free -m---
              total        used        free      shared  buff/cache   available
Mem:           7823         368        7266           8         188        7261
Swap:          8063           0        8063
---starting services: ksm and ksmtuned...
---free -m command output with ksm and ksmtuned running.
              total        used        free      shared  buff/cache   available
Mem:           7823         248        7382           8         191        7377
Swap:          8063           0        8063
KSM saved: 121MB

 

以上輸出中,從 KSM、ksmtuned 服務開始運行以前和以後的 "free -m" 命令看出 used 從 368 下降到 248,明顯節約了系統內存。

相關文章
相關標籤/搜索