以下命令行親自執行有效,執行環境:
Compiled against library: libvirt 4.5.0
Using library: libvirt 4.5.0
Using API: QEMU 4.5.0
Running hypervisor: QEMU 1.5.3
QEMU存儲虛擬化結構棧
QEMU可以處理幾種不同的磁盤映像格式。首選格式為raw或qcow2。Raw是一種非常簡單的格式,它將文件系統中的字節逐字節存儲在文件中。大多數其他仿真器都支持此格式。Qcow2是QEMU自己的圖像格式,對小圖像很有用。並且支持磁盤映像壓縮以及捕獲磁盤映像狀態的快照。
從QEMU的存儲協議棧來說,應用程序和虛擬機內核的工作類似於裸機。虛擬機通過硬件仿真(Hardware emulation)與QEMU交互,並將IO執行情況的控制流和數據流交互給QEMU,QEMU代表虛擬機對磁盤鏡像文件執行I/O操作。而從主機內核層面上,主機內核會將虛擬機I/O視為一種用戶空間的應用程序IO請求進行正常的執行處理。
硬件仿真(Hardware emulation)主要有3種:
- Virtio 是准虛擬化存儲接口,提供較好的性能,virtio_blk 是准虛擬化塊設備接口。
- IDE 是 QEMU 全虛擬化接口,提供最好的兼容性,但是性能最差。
- SCSI 是新的給特定設備的接口。
全虛擬化 I/O
- 客戶機的設備驅動程序發起 I/O 請求操作請求
- KVM 模塊中的 I/O 操作捕獲代碼攔截這次 I/O 請求
- 經過處理后將本次 I/O 請求的信息放到 I/O 共享頁 (sharing page),並通知用戶空間的 QEMU 程序。
- QEMU 程序獲得 I/O 操作的具體信息之后,交由硬件模擬代碼來模擬出本次 I/O 操作。
- 完成之后,QEMU 將結果放回 I/O 共享頁,並通知 KMV 模塊中的 I/O 操作捕獲代碼。
- KVM 模塊的捕獲代碼讀取 I/O 共享頁中的操作結果,並把結果放回客戶機。
qemu-kvm 關於磁盤設備和網絡的主要選項
-drive option[,option[,option[,...]]]:定義一個硬盤設備;可用子選項有很多。 file=/path/to/somefile:硬件映像文件路徑; if=interface:指定硬盤設備所連接的接口類型,即控制器類型,如ide、scsi、sd、mtd、floppy、pflash及virtio等; index=index:設定同一種控制器類型中不同設備的索引號,即標識號; media=media:定義介質類型為硬盤(disk)還是光盤(cdrom); format=format:指定映像文件的格式,具體格式可參見qemu-img命令; -boot [order=drives][,once=drives][,menu=on|off]:定義啟動設備的引導次序,每種設備使用一個字符表示;不同的架構所支持的設備及其表示字符不盡相同,在x86 PC架構上,a、b表示軟驅、c表示第一塊硬盤,d表示第一個光驅設備,n-p表示網絡適配器;默認為硬盤設備(-boot order=dc,once=d)
詳情:libvirt 虛機的生命周期 (Libvirt Virtual Machine Lifecycle)
I/O 全虛擬化和准虛擬化 [KVM I/O QEMU Full-Virtualizaiton Para-virtualization] https://www.cnblogs.com/sammyliu/p/4543657.html libvirt 介紹 [ Libvrit for KVM/QEMU ] https://www.cnblogs.com/sammyliu/p/4558638.html Nova 通過 libvirt 管理 QEMU/KVM 虛機 [Nova Libvirt QEMU/KVM Domain] https://www.cnblogs.com/sammyliu/p/4568188.html 使用 libvirt 做 QEMU/KVM 快照和 Nova 實例的快照 (Nova Instances Snapshot Libvirt) https://www.cnblogs.com/sammyliu/p/4468757.html 使用 libvirt 遷移 QEMU/KVM 虛機和 Nova 虛機 [Nova Libvirt QEMU/KVM Live Migration] https://www.cnblogs.com/sammyliu/p/4572287.html
KVM/QEMU 的 vitio 實現采用在 Guest OS 內核中安裝前端驅動 (Front-end driver)和在 QEMU 中實現后端驅動(Back-end)的方式。前后端驅動通過 vring 直接通信,這就繞過了經過 KVM 內核模塊的過程,達到提高 I/O 性能的目的。
純軟件模擬的設備和 Virtio 設備的區別:virtio 省去了純模擬模式下的異常捕獲環節,Guest OS 可以和 QEMU 的 I/O 模塊直接通信。
Libvirt
為什么需要Libvirt?
- Hypervisor 比如 qemu-kvm 的命令行虛擬機管理工具參數眾多,難於使用。
- Hypervisor 種類眾多,沒有統一的編程接口來管理它們,這對雲環境來說非常重要。
- 沒有統一的方式來方便地定義虛擬機相關的各種可管理對象。
Libvirt提供了什么?
- 它提供統一、穩定、開放的源代碼的應用程序接口(API)、守護進程 (libvirtd)和和一個默認命令行管理工具(virsh)。
- 它提供了對虛擬化客戶機和它的虛擬化設備、網絡和存儲的管理。
- 它提供了一套較為穩定的C語言應用程序接口。目前,在其他一些流行的編程語言中也提供了對libvirt的綁定,在Python、Perl、Java、Ruby、PHP、OCaml等高級編程語言中已經有libvirt的程序庫可以直接使用。
- 它對多種不同的 Hypervisor 的支持是通過一種基於驅動程序的架構來實現的。libvirt 對不同的 Hypervisor 提供了不同的驅動,包括 Xen 的驅動,對QEMU/KVM 有 QEMU 驅動,VMware 驅動等。在 libvirt 源代碼中,可以很容易找到 qemu_driver.c、xen_driver.c、xenapi_driver.c、vmware_driver.c、vbox_driver.c 這樣的驅動程序源代碼文件。
- 它作為中間適配層,讓底層 Hypervisor 對上層用戶空間的管理工具是可以做到完全透明的,因為 libvirt 屏蔽了底層各種 Hypervisor 的細節,為上層管理工具提供了一個統一的、較穩定的接口(API)。
- 它使用 XML 來定義各種虛擬機相關的受管理對象。
目前,libvirt 已經成為使用最為廣泛的對各種虛擬機進行管理的工具和應用程序接口(API),而且一些常用的虛擬機管理工具(如virsh、virt-install、virt-manager等)和雲計算框架平台(如OpenStack、OpenNebula、Eucalyptus等)都在底層使用libvirt的應用程序接口。
Libvirt API 的實現
libvirt API 的實現是在各個 Hypervisor driver 和 Storage dirver 內。Hypervisor 驅動包括:
- LXC - Linux Containers
- OpenVZ
- QEMU
- Test - Used for testing
- UML - User Mode Linux
- VirtualBox
- VMware ESX
- VMware Workstation/Player
- Xen
- Microsoft Hyper-V
- IBM PowerVM (phyp)
- Parallels
- Bhyve - The BSD Hypervisor
Libvirti API 所管理的主要對象
對象 | 解釋 |
Domain (域) | 指運行在由Hypervisor提供的虛擬機器上的一個操作系統實例(常常是指一個虛擬機)或者用來啟動虛機的配置。 |
Hypervisor | 一個虛擬化主機的軟件層 |
Node (主機) | 一台物理服務器。 |
Storage pool (存儲池) | 一組存儲媒介的集合,比如物理硬盤驅動器。一個存儲池被划分為小的容器稱作卷。卷會被分給一個或者多個虛機。 |
Volume (卷) | 一個從存儲池分配的存儲空間。一個卷會被分給一個或者多個域,常常成為域里的虛擬硬盤。 |
對象的管理模型
對象名稱 | 對象 | Python 類 | 描述 |
Connect | 與 Hypervisor的連接 |
virConnectPtr
|
在調用任何 API 去管理一個本地或者遠端的Hypervisor前,必須建立和這個Hypervisor的連接。 |
Domain | Guest domain |
virDomainPtr
|
用於列舉和管理已有的虛機,或者創建新的虛機。唯一標識:ID,Name,UUID。一個域可能是暫時性的或者持久性的。暫時性的域只能在它運行期間被管理。持久性的域在主機上保存了它的配置。 |
Virtual Network | 虛擬網絡 |
virNetworkPtr
|
用於管理虛機的網絡設備。唯一標識:Name,UUID。一個虛擬網絡可能是暫時性的或者持久性的。每個主機上安裝libvirt后,它都有一個默認的網絡設備“default”。它向該主機上運行的虛機提供DHCP服務,以及通過NAT連接到主機上。 |
Storage Pool | 存儲池 |
virStoragePoolPtr
|
用於管理虛擬機內的所有存儲,包括 local disk, logical volume group, iSCSI target, FibreChannel HBA and local/network file system。唯一標識:Name,UUID。一個存儲池可能是暫時性的或者持久性的。Pool 的 type 可以是 dir , fs , netfs , disk , iscsi , logical , scsi ,mpath , rbd , sheepdog , gluster 或者 zfs。 |
Storage Volume | 存儲卷 |
virStorageVolPtr
|
用於管理一個存儲池內的存儲塊,包括一個池內分配的塊、磁盤分區、邏輯卷、SCSI/iSCSI Lun,或者一個本地或者網絡文件系統內的文件等。唯一標識:Name,Key,Path。 |
Host device | 主機設備 |
virNodeDevPtr
|
用於管理主機上的物理硬件設備,包括 the physical USB or PCI devices and logical devices these provide, such as a NIC, disk, disk
controller, sound card, etc。唯一標識:Name。
|
Libvirt XML 定義
Libvirt 使用 XML 來定義各種對象,例如
<devices> <emulator>/usr/libexec/qemu-kvm</emulator> <disk type='file' device='disk'> <driver name='qemu' type='raw'/> <source file='/data/centos7.raw'/> <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </disk> <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <target dev='hda' bus='ide'/> <readonly/> <address type='drive' controller='0' bus='0' target='0' unit='0'/> </disk>
其中,與 OpenStack Nova 關系比較密切的有:
disk (磁盤) | 任何磁盤設備,包括軟盤(floppy)、硬盤(hard disk)、光驅(cdrom)或者半虛擬化驅動都使用 <disk> 元素來定義。 方式: <disk type='**' device='**'>。其中:
(1)”volume“ 類型的 disk <disk type='volume' device='disk'> <driver name='qemu' type='raw'/> <source pool='blk-pool0' volume='blk-pool0-vol0'/> <target dev='hdk' bus='ide'/> </disk> <disk type='file' snapshot='external'> <driver name="tap" type="aio" cache="default"/> <source file='/var/lib/xen/images/fv0' startupPolicy='optional' /> <target dev='hda' bus='ide'/> </disk> <disk type='block' device='cdrom'> <driver name='qemu' type='raw'/> <target dev='hdd' bus='ide' tray='open'/> <readonly/> </disk> <disk type='network' device='cdrom'> <driver name='qemu' type='raw'/> <source protocol="http" name="url_path"> <host name="hostname" port="80"/> </source> <target dev='hde' bus='ide' tray='open'/> <readonly/> </disk> |
|
Host device assignment (主機設備分配) |
<hostdev mode='subsystem' type='usb'> #USB 設備直接分配 <source startupPolicy='optional'> <vendor id='0x1234'/> <product id='0xbeef'/> </source> <boot order='2'/> </hostdev> <hostdev mode='subsystem' type='pci' managed='yes'> #PCI 設備直接分配 <source> <address domain='0x0000' bus='0x06' slot='0x02' function='0x0'/> </source> <boot order='1'/> <rom bar='on' file='/etc/fake/boot.bin'/> </hostdev> |
|
Network interface (網卡) | 有幾種 interface 類型: (1)type = ‘network’ 定義一個連接 Virtual network 的 interface <devices> <interface type='network'> <source network='default'/> #虛擬網絡的名稱為 ‘default’ </interface> ... <interface type='network'> <source network='default' portgroup='engineering'/> <target dev='vnet7'/> <mac address="00:11:22:33:44:55"/> <virtualport> <parameters instanceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/> </virtualport> </interface> </devices> #virsh:attach-interface --domain d-2 --type network --source isolatednet1 --mac 52:53:00:4b:75:6f --config ![]() (2)type=‘birdge’ 定義一個 Bridge to LAN(橋接到物理網絡)的interface:前提是主機上存在一個 bridge,該 bridge 已經連到物理LAN。 <interface type='bridge'> #連接到 br0 <source bridge='br0'/> </interface> <interface type='bridge'> #連接到br1 <source bridge='br1'/> <target dev='vnet7'/> <mac address="00:11:22:33:44:55"/> </interface> <interface type='bridge'> #連接到 Open vSwithc bridge ovsbr <source bridge='ovsbr'/> <virtualport type='openvswitch'> <parameters profileid='menial' interfaceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/> </virtualport> </interface> #virsh:attach-interface --domain d-2 --type bridge --source virbr0 --mac 52:22:33:44:55:66 --config (3)type=‘ethernet’ 定義一個使用指定腳本連接到 LAN 的 interface <devices> <interface type='ethernet'> <target dev='vnet7'/> <script path='/etc/qemu-ifup-mynet'/> </interface> </devices> (4)type=‘direct’ 定義一個直接連到物理網卡(Direct attachment to physical interface)的 interface:需要 Linux macvtap 驅動支持 <interface type='direct' trustGuestRxFilters='no'> <source dev='eth0' mode='vepa'/> </interface> (5)type=‘hostdev’ 定義一個由主機PCI 網卡直接分配(PCI Passthrough)的 interface: 分配主機上的網卡給虛機 <devices> <interface type='hostdev' managed='yes'> <driver name='vfio'/> <source> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </source> <mac address='52:54:00:6d:90:02'/> <virtualport type='802.1Qbh'> <parameters profileid='finance'/> </virtualport> </interface> </devices> |
|
network (網絡) | <bridge name="virbr0" stp="on" delay="5" macTableManager="libvirt"/> <domain name="example.com" localOnly="no"/> <forward mode="nat" dev="eth0"/> 1. bridge:定義一個用於構造該虛擬網絡的網橋。 2. domain:定義 DHCP server 的 DNS domain。 3. forward: 定義虛擬網絡直接連到物理 LAN 的方式. ”mode“指轉發模式。 (1) mode=‘nat’:所有連接到該虛擬網絡的虛擬的網絡都會經過物理機器的網卡,並轉換成物理網卡的地址。 <network> <name>default</name> <bridge name="virbr0" /> <forward mode="nat"/> <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> <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" /> </network> 也可以指定公共的IP地址和端口號。 <forward mode='nat'><nat><address start='1.2.3.4' end='1.2.3.10'/> </nat> </forward> <forward mode='nat'><nat><port start='500' end='1000'/></nat></forward> <network> <name>local</name> <bridge name="virbr1" /> <forward mode="route" dev="eth1"/> <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> <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" /> </network> <network> <name>host-bridge</name> <forward mode="bridge"/> <bridge name="br0"/> </network> <forward mode='passthrough'> <interface dev='eth10'/> <interface dev='eth11'/> <interface dev='eth12'/> <interface dev='eth13'/> <interface dev='eth14'/> </forward> <forward mode='hostdev' managed='yes'> <driver name='vfio'/> <address type='pci' domain='0' bus='4' slot='0' function='1'/> <address type='pci' domain='0' bus='4' slot='0' function='2'/> <address type='pci' domain='0' bus='4' slot='0' function='3'/> </forward> |
詳細的 XML 定義說明在 https://libvirt.org/format.html
鏡像文件管理工具qemu-img
可以通過qemu-img -h查看其支持的鏡像格式,支持20多中格式:blkdebug blkverify bochs cloop cow tftp ftps ftp https http dmg nbd parallels qcow qcow2 qed host_cdrom host_floppy host_device file raw sleepdog vdi vmdk vpc vvfat。這里主要介紹一下raw和qcow2格式
qemu-img有很多命令,包括下面常用的
info
查看鏡像的信息
create
創建鏡像
check
檢查鏡像
convert
轉化鏡像的格式,(raw,qcow ……)
snapshot
管理鏡像的快照
rebase
在已有的鏡像的基礎上創建新的鏡像
resize
增加或減小鏡像大小
create創建鏡像
qemu-img create [-f fmt] [-o options] filename [size] 對於qcow2,-o支持的參數包括compat\backing-file\backing-fmt\encryption\cluster_size\prellocation qemu-img create -f raw /data/centos7.raw 10G
convert 轉化鏡像文件格式
qemu-img convert [-c] [-f fmt] [-O output_fmt] [-o options] filename output_filename [-c]表示是否對文件進行壓縮 [-o options]可以指定后端鏡像文件(保證源和目標的后端一致)、文件大小、是否加密等 qemu-img convert -c -O qcow2 vm2.raw vm2.qcow2
snapshot管理鏡像文件終端 快照
qemu-img snapshot [-l| -a snapshot| -c snapshot| -d snapshot] filename
[-l]列出所有快照
[-a]使用某一個快照
[-c]創建一個快照
[-d]刪除一個快照
查看快照 qemu-img snapshot -l /images/vm2.qcow2 注意:只有qcow2才支持快照 打快照 qemu-img snapshot -c booting vm2.qcow2 從快照恢復: qemu-img snapshot -a 1 /images/vm2.qcow2 然后從kvm啟動這個虛擬機,會發現虛擬機又在打快照時的狀態了 刪除快照: qemu-img snapshot -d 2 /images/vm2.qcow
resize 改變鏡像文件大小
qemu-img rebase [-f fmt] [-t cache] [-p] [-u] -b backing-file [-F backing-fmt] filename 只有qcow2和qed格式支持 qemu-img resize filename [+/-]size size支持K M G T 單位 qemu-img resize vm2.raw +2GB
qemu-kvm存儲配置
qemu-kvm創建和開啟虛機的存儲配置
存儲配置主要涉及三部分
(1)指定存儲器
(2)設置啟動順序
(3)詳細配置存儲驅動器(設置存儲驅動器的詳細屬性,先略過)
指定存儲器,主要是指指定客戶機的IDE設備、軟盤設備、CD-ROM、Flash存儲器、SD卡具體使用哪個鏡像文件
配置客戶機的啟動順序,在指定了各個存儲器設備后,可以指定客戶機在啟動的時候選擇啟動設備的順序
qemu-kvm ... -boot [order=a|b|c|d|n][,once=drivces][,menu=on|off]
[,splash=filename][,splash-time=sp-time]
a|b分別表示第1、2軟驅,c表示第一個硬盤,d表示cd-rom;
once表示第一次啟動的啟動順序;
menu設置開機交互界面;
splash ,splash-time設置開機bios顯示的圖片和時間
詳細配置存儲驅動器
-drive option[,option[,option.....]]
為客戶機添加一個新的存儲驅動器,可以指定對應的鏡像文件、接口類型、
媒介類型、快照、緩存等
qemu-kvm創建虛擬機
qemu-kvm -name c1 -smp 2 -m 128 -cpu host -drive file=/data/VMs/c1/c1.img,if=virtio,media=disk,cache=writeback,format=qcow2 -net nic,macaddr=52:54:00:00:00:11,model=virtio -net tap,script=/etc/qemu-ifup -vnc :0
virt-install創建虛擬機
# 默認網絡 virt-install --virt-type kvm --name centos7 --ram 1024 --cdrom=/home/CentOS-7-x86_64-Minimal-2003.iso --disk path=/data/centos7.raw --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole # 橋接網絡: virt-install --virt-type kvm --name openstack-middleware1 --ram 4096 --vcpus 4 --cdrom=/usr/local/src/CentOS-7-x86_64-Minimal-1511.iso --disk path=/var/lib/libvirt/images/CentOS-7-x86_64-GenericCloud-1511-ok.qcow2 --network bridge=br0 --graphics vnc,listen=0.0.0.0 --noautoconsole