一、KVM簡介
KVM的全稱是Kernel Virtual Machine,翻譯過來就是內核虛擬機。它是一個 Linux 的一個內核模塊,該內核模塊使得
Linux 變成了一個 Hypervisor:
- 它由 Quramnet 開發,該公司于 2008年被 Red Hat 收購。
- 它支持 x86 (32 and 64 位), s390, Powerpc 等 CPU。
- 它從 Linux 2.6.20 起就作為一模塊被包含在 Linux 內核中。
- 它需要支持虛擬化擴展的 CPU。
- 它是完全開源的。官網
1.1 KVM的功能列表
- 支持CPU 和 memory 超分(Overcommit)
- 支持半虛擬化I/O (virtio)
- 支持熱插拔 (cpu,塊設備、網絡設備等)
- 支持對稱多處理(Symmetric Multi-Processing,縮寫為 SMP )
- 支持實時遷移(Live Migration)
- 支持 PCI 設備直接分配和 單根I/O 虛擬化 (SR-IOV)
- 支持 內核同頁合并 (KSM )
- 支持 NUMA (Non-Uniform Memory Access,非一致存儲訪問結構 )
1.2 KVM原理
KVM 本身不執行任何模擬,需要用戶空間應用程序 QEMU 通過 /dev/kvm 接口設置一個客戶機虛擬服務器的地址空間,向它提供模擬的 I/O,KVM 模塊主要功能是初始化CPU硬件,打開虛擬化模式,然后將虛客戶機運行在虛擬機模式下,并對虛擬客戶機的運行提供一定的支持。在硬件虛擬化技術的支持下,內核的 KVM 模塊與 QEMU 的設備模擬協同工作,構成一套和物理計算機系統完全一致的虛擬化計算機軟硬件系統。
二、KVM基礎功能
2.1 CPU
在 QEMU/KVM 中,QEMU 提供對 CPU 的模擬,展現給客戶機一定的 CPU 數目和 CPU 的特性。在 KVM 打開的情況下,客戶機中 CPU 指令的執行由硬件處理器的虛擬化功能「如 Intel VT-x 和 AMD AMD-V」輔助執行,具有非常高的執行效率。
在 KVM 環境中,每個客戶機都是一個標準的 Linux 進程(QEMU 進程),而每一個 vCPU 在宿主機中是 QEMU 進程派生的一個普通線程。
在 Linux 中,一般進程有兩種執行模式:
- 內核模式
- 用戶模式
而在 KVM 環境中,增加了第三條模式:客戶模式。vCPU 在三種執行模式下的分工如下:
- 用戶模式
- 主要處理 I/O 的模擬和管理,由 QEMU 的代碼實現
- 內核模式
- 主要處理特別需要高性能和安全相關的指令,如處理客戶模式到內核模式的轉換,處理客戶模式下的 I/O 指令或其它特權指令引起的 VM-Exit,處理影子內存管理 (shadow MMU)
- 客戶模式
- 主要執行 Guest 中的大部分指令,I/O 和一些特權指令除外「它們會引起 VM-Exit,被 hypervisor 截獲并模擬」
2.2 內存
內存是一個非常重要的部件,它是與 CPU 溝通的一個橋梁。
在通過 QEMU 命令行啟動客戶機時設置內存的參數是 -m:
- -m megs # 設置客戶機的內存為 megs MB 大小
EPT 和 VPID
EPT(Extended Page Tables,擴展頁表),屬于 Intel 的第二代硬件虛擬化技術,它是針對內存管理單元(MMU)的虛擬化擴展。如果只是一臺物理服務器,這個物理地址就只為一個操作系統服務,但如果進行了虛擬化部署,有多個虛擬機時,就存在著穩定性的隱患。因為在進行 VM Entry(虛擬機進入)與 VM Exit(虛擬機退出)時(尤其是后者),都要對內存頁進行修改。但物理內存是多個虛擬機共享的,因此不能讓虛擬機直接訪問物理地址,否則一個虛擬機出現內存錯誤,就會殃及整個物理服務器的運行。所以必須要采取虛擬地址,而 EPT 的作用就在于加速從虛擬機地址至主機物理地址的轉換過程,節省傳統軟件處理方式的系統開銷。
VPID(Virtual-Processor Identifiers,虛擬處理器標識)。是對現在的 CPUID 功能的一個強化,因為在每個 CPU 中都有一個 TLB,用來緩存邏輯地址到物理地址的轉換表,而每個虛擬機都有自己的虛擬 CPU 來對應。所以,在進行遷移時要進行 TLB 的轉存和清除。而 VPID 則會跟蹤每個虛擬 CPU 的 TLB,當進行虛擬機遷移或 VM Entry 與 VM Exit 時,VMM可以動態的分配非零虛擬處理器的 ID 來迅速匹配(0 ID 給 VMM 自己使用),從而避免了 TLB 的轉存與清除的操作,節省了系統開銷,并提高了遷移速度,同時也降低對系統性能的影響。
# grep -E 'ept|vpid' /proc/cpuinfo # 查看 cpu 是否支持相應特性
# cat /sys/module/kvm_intel/parameters/{ept,vpid} # 確認是否開啟 ept 和 vpid
三、CentOS上安裝Kvm步驟
3.1 KVM
需要有 CPU 的支持(Intel VT 或 AMD SVM),在安裝 KVM 之前檢查一下 CPU 是否提供了虛擬技術的支持。
- 基于 Intel 處理器的系統,運行grep vmx /proc/cpuinfo查找 CPU flags 是否包括 vmx 關鍵詞
- 基于 AMD 處理器的系統,運行grep svm /proc/cpuinfo查找 CPU flags 是否包括 svm 關鍵詞
- 檢查BIOS,確保BIOS里開啟VT選項
3.2 安裝KVM所需組件
除了3.1的KVM內核模塊外,在用戶空間需要QEMU來模擬CPU和設備模型以及用于啟動客戶機進程,這樣才有一個完整的KVM運行環境。而qemu-kvm是為了針對KVM專門做了修改和優化的QEMU分支。
yum install seabios qemu-kvm virt-manager libvirt -y
啟動libvirt服務:
systemctl start libvirtd
3.3 創建并啟動bridge設備
安裝需要的RPM包
yum install -y bridge-utils tuned
查看tun模塊是否加載:
[root@server-31 ~]# lsmod | grep tun
tun 27141 12 vhost_net
檢查/dev/net/tun的權限,需要讓當前用戶擁有可讀寫的權限
[root@server-31 ~]# ll /dev/net/tun
crw-rw-rw- 1 root root 10, 200 Mar 10 08:33 /dev/net/tun
創建/etc/sysconfig/network-scripts/ifcfg-br0
DEVICE=br0
TYPE=Bridge
ONBOOT=yes
NM_CONTROLLED=no
BOOTPROTO=static
PEERDNS=no
DELAY=0
STP=yes
BRIDGING_OPTS=""
NM_CONTROLLED=no
IPADDR=x.x.x.x
NETMASK=255.255.255.0
GATEWAY=x.x.x.x
修改/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
HWADDR=24:6e:96:27:65:5c
TYPE=Ethernet
ONBOOT=yes
NM_CONTROLLED=no
BOOTPROTO=static
HOTPLUG=yes
PEERDNS=no
BRIDGE=br0
NM_CONTROLLED=no
重啟eth0:
ifdown eth0
ifup eth0
啟動br0:
ifup br0
3.4 創建虛擬機:
基于iso文件創建
劃分磁盤:
qemu-img create -f qcow2 /data/centos-6.4.qcow2 10G
創建虛擬機(本命令的虛擬機的網絡模式基于網橋)
virt-install --virt-type kvm --name centos-6.4 --ram 1024 \
--cdrom=/data/CentOS-6.4-x86_64-netinstall.iso \
--disk path=/data/centos-6.4.qcow2,size=10,format=qcow2 \
--network network=default \
--graphics vnc,listen=0.0.0.0 --noautoconsole \
--os-type=linux --os-variant=rhel6
基于現在的虛擬機創建
拷貝已有虛擬機的disk文件:
cp old_centos7.2.qcow2 new_centos7.2.qcow2
創建new_centos7.2.xml文件如下:
<domain type='kvm'>
<name>new_centos7.2</name>
<memory>16097152</memory>
<currentMemory>16097152</currentMemory>
<vcpu>2</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='localtime'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/new_centos7.2.qcow2'/>
<target dev='vda' bus='virtio'/>
</disk>
<interface type="bridge">
<model type="virtio"/>
<source bridge="br0"/>
</interface>
<input type='tablet' bus='usb'/>
<graphics type='vnc' port='-1' listen = '0.0.0.0' keymap='en-us'/>
</devices>
</domain>
啟動虛擬機
virsh define new_centos7.2.xml
virsh start new_centos7.2
查看創建的虛擬機:
[root@server-31 var]# virsh list --all
Id Name State
----------------------------------------------------
11 centos.7.2 running
/etc/libvirt/qemu目錄下會發現centos.7.2.xml,內容如下:
<domain type='kvm'>
<name>centos.7.2</name>
<uuid>727ade52-43ba-46a0-8865-1198498af22f</uuid>
<memory unit='KiB'>4194304</memory>
<currentMemory unit='KiB'>4194304</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
<boot dev='hd'/>
</os>
...
<devices>
<emulator>/usr/libexec/qemu-kvm</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/Centos-7.2.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</disk>
...
<interface type='bridge'>
<mac address='52:54:00:76:c4:91'/>
<source bridge='br0'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
...
</devices>
</domain>
查看網橋信息
root@server-31 qemu]# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.246e9627655c yes eth0
vnet0
后期可能會因為需求對KVM重新配置,這個時候我們只需要修改對應的xml文件即可
修改配置的時候需要關閉KVM: virsh destroy centos.7.2
使用virsh define centos.7.2.xml使配置生效
使用virsh start centos.7.2啟動虛擬機
四、虛擬機的上網方式
4.1 nat
1.nat模式配置
KVM默認采用nat模式,用戶網絡(User Networking):讓虛擬機訪問主機、互聯網或本地網絡上的資源的簡單方法,但是不能從網絡或其他的客戶機訪問客戶機。在公網IP不夠使用KVM還需要上網的時候可以使用,大大節省了公網IP!同時這種模式也使得KVM不用暴露在公網之中,也增加了安全性。
下圖是虛擬機管理模塊產生的接口關系:
其中virbr0是由宿主機虛擬機支持模塊安裝時產生的虛擬網絡接口,也是一個switch和bridge,負責把內容分發到各虛擬機。
從圖上可以看出,虛擬接口和物理接口之間沒有連接關系,所以虛擬機只能在通過虛擬的網絡訪問外部世界,無法從網絡上定位和訪問虛擬主機。
下面是nat的default配置,可以自定義地址池
[root@server-31 networks]# cat /etc/libvirt/qemu/networks/default.xml
<network>
<name>default</name>
<uuid>71c7ed8d-08aa-44d0-8f76-cc4fd2dd4380</uuid>
<forward mode='nat'/>
<bridge name='virbr0' stp='on' delay='0'/>
<mac address='52:54:00:91:d4:95'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
確認路由轉發開啟:
[root@server-31 networks]# cat /proc/sys/net/ipv4/ip_forward
1
使用virsh net-start default來啟動nat網絡
4.2 bridge
網橋(bridge)模式可以讓客戶機和宿主機共享一個物理網絡設備連接網絡,客戶機有自己的獨立IP地址,可以直接連接與宿主機一模一樣的網絡,客戶機可以訪問外部網絡,外部網絡也可以直接訪問客戶機。
Bridge方式即虛擬網橋的網絡連接方式,是客戶機和子網里面的機器能夠互相通信。可以使虛擬機成為網絡中具有獨立IP的主機。
橋接網絡(也叫物理設備共享)被用作把一個物理設備復制到一臺虛擬機。網橋多用作高級設置,特別是主機多個網絡接口的情況。
配置步驟見3.3小節
網絡配置可以同時存在nat和Bridge.
五、QEMU
Qemu本身并不是KVM的一部分,其自身就是一個著名的開源虛擬機軟件。與KVM不同,QEMU虛擬機是一個純軟件的實現,所以性能低下。但是,其優點是在支持QEMU本身編譯運行的平臺上就可以實現虛擬機的功能。
5.1 qemu-img
qemu-img 是 QEMU 的磁盤管理工具,支持多種虛擬鏡像格式
[root@server-31 ~]# qemu-img -h | grep Support
Supported formats: vvfat vpc vmdk vhdx vdi ssh sheepdog rbd raw host_cdrom host_floppy host_device file qed qcow2 qcow parallels nbd iscsi gluster dmg tftp ftps ftp https http cloop bochs blkverify blkdebug
簡單介紹一下qcow2和raw格式鏡像:
qcow2 是 qcow 的一種改進,是 QEMU 實現的一種虛擬機鏡像格式。更小的虛擬硬盤空間(尤其是宿主分區不支持 hole 的情況下),支持壓縮、加密、快照功能,磁盤讀寫性能較 raw 差。
raw是原始的磁盤鏡像格式,它的優勢在于它非常簡單而且非常容易移植到其他模擬器(emulator,QEMU 也是一個 emulator)上去使用。如果客戶機文件系統(如 Linux 上的 ext2/ext3/ext4、Windows 的 NTFS)支持“空洞” (hole),那么鏡像文件只有在被寫有數據的扇區才會真正占用磁盤空間,從而有節省磁盤空間的作用。qemu-img 默認的 raw 格式的文件其實是稀疏文件(sparse file)「稀疏文件就是在文件中留有很多空余空間,留備將來插入數據使用。如果這些空余空間被 ASCII 碼的 NULL 字符占據,并且這些空間相當大,那么這個文件就被稱為稀疏文件,而且,并不分配相應的磁盤塊」,dd 命令創建的也是 raw 格式,不過 dd 一開始就讓鏡像實際占用了分配的空間,而沒有使用稀疏文件的方式對待空洞而節省磁盤空間。盡管一開始就實際占用磁盤空間的方式沒有節省磁盤的效果,不過它在寫入新的數據時不需要宿主機從現有磁盤空間中分配,從而在第一次寫入數據時性能會比稀疏文件的方式更好一點。簡單來說,raw 有以下幾個特點:
- 尋址簡單,訪問效率高
- 可以通過格式轉換工具方便地轉換為其它格式
- 格式實現簡單,不支持壓縮、快照和加密
- 能夠直接被宿主機掛載,不用開虛擬機即可在宿主和虛擬機間進行數據傳輸
格式轉換
以raw轉換為qcow2為例
qemu-img convert -f raw -O qcow2 test.raw test.qcow2
# -f fmt
# -O output_fmt
六、KVM管理工具
6.1 libvirt
libvirt 是為了更方便地管理平臺虛擬化技術而設計的開放源代碼的應用程序接口、守護進程和管理工具,他不僅提供了對虛擬化客戶機的管理,也提供了對虛擬化網絡和存儲的管理。
libvirt中涉及幾個重要的概念,解釋如下:
節點(Node):一個物理機器,上面可能運行著多個虛擬客戶機。Hypervisor和Domain都運行在Node之上。
Hypervisor:也稱虛擬機監控器(VMM),如KVM、Xen、VMware、Hyper-V等,是虛擬化中的一個底層軟件層,它可以虛擬化一個節點讓其運行多個虛擬客戶機(不同客戶機可能有不同的配置和操作系統)。
域(Domain):是在Hypervisor上運行的一個客戶機操作系統實例。域也被稱為實例(instance,如亞馬遜的AWS云計算服務中客戶機就被稱為實例)、客戶機操作系統(guest OS)、虛擬機(virtual machine),它們都是指同一個概念。
libvirt安裝
yum install -y libvirt
systemctl start libvirtd
libvirt使用
在使用libvirt對虛擬化系統進行管理師,很多地方都是XML文件作為配置文件。
前面的new_centos7.2.xml配置文件中,關于CPU的配置為:
<vcpu>2</vcpu>
關于內存的配置為:
<memory>16097152</memory>
<currentMemory>16097152</currentMemory>
memory標簽中的值表示客戶機最大可使用的內存,為:16097152KB(即16GB)
currentMemory標簽中的值表示啟動時及分配給客戶機使用的內存
關于啟動順序的配置
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
這樣的配置表示客戶機的類型是HVM類型(硬件虛擬機),它表示在硬件輔助虛擬化技術的支持下不需要修改客戶機操作系統就可以啟動客戶機。
boot選項用于設置客戶機啟動時的設備,hd表示硬盤,cdrom表示光盤
網橋的配置
<devices>
···
<interface type="bridge">
<model type="virtio"/>
<source bridge="br0"/>
</interface>
</devices>
type='bridge'表示使用橋接方式使客戶機獲得網絡,可以用address來配置客戶機中網卡的MAC地址,<model type="virtio"/>表示在客戶機中使用virtio-net驅動的網卡設備,<source bridge='br0'> 表示使用宿主機的br0網絡接口來建立網橋
如果選用NAT方式的虛擬機網絡配置(需要保證宿主機中運行著dhcp和DNS服務器,一般默認使用dnsmasq),那么在域的XML配置中,配置實例如下:
<devices>
···
<interface type="network">
<source netwokr="default"/>
</interface>
</devices>
存儲的配置
<devices>
···
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/new_centos7.2.qcow2'/>
<target dev='vda' bus='virtio'/>
</disk>
</devices>
上面的配置表示,使用qcow2格式的centos7.2鏡像文件作為客戶機的磁盤,其在客戶機中使用virtio總線,設備名稱為/dev/vda