Libvirt 是一組軟體的匯集,提供了管理虛擬機和其它虛擬化功能(如:存儲和網絡接口等)的便利途徑。這些軟體包括:一個長期穩定的 C 語言 API、一個守護進程(libvirtd)和一個命令行工具(virsh)。Libvirt 的主要目標是提供一個單一途徑以管理多種不同虛擬化方案以及虛擬化主機,包括:KVM/QEMU,Xen,LXC,OpenVZ 或 VirtualBox hypervisors (詳見這裡)。
Libvirt 的一些主要功能如下:
- VM management(虛擬機管理):各種虛擬機生命周期的操作,如:啟動、停止、暫停、保存、恢復和遷移等;多種不同類型設備的熱插拔操作,包括磁碟、網絡接口、內存、CPU等。
- Remote machine support(支持遠程連接):Libvirt 的所有功能都可以在運行著 libvirt 守護進程的機器上執行,包括遠程機器。通過最簡便且無需額外配置的 SSH 協議,遠程連接可支持多種網絡連接方式。
- Storage management(存儲管理):任何運行 libvirt 守護進程的主機都可以用於管理多種類型的存儲:創建多種類型的文件鏡像(qcow2,vmdk,raw,...),掛載 NFS 共享,枚舉現有 LVM 卷組,創建新的 LVM 卷組和邏輯卷,對裸磁碟設備分區,掛載 iSCSI 共享,以及更多......
- Network interface management(網絡接口管理):任何運行 libvirt 守護進程的主機都可以用於管理物理的和邏輯的網絡接口,枚舉現有接口,配置(和創建)接口、橋接、VLAN、埠綁定。
- Virtual NAT and Route based networking(虛擬 NAT 和基於路由的網絡):任何運行 libvirt 守護進程的主機都可以管理和創建虛擬網絡。Libvirt 虛擬網絡使用防火牆規則實現一個路由器,為虛擬機提供到主機網絡的透明訪問。
安裝
基於守護進程/客戶端的架構的 libvirt 只需要安裝在需要要實現虛擬化的機器上。注意,伺服器和客戶端可以是相同的物理機器。
服務端
安裝 libvirt包 以及至少一個虛擬運行環境(hypervisor):
- libvirt 的 KVM/QEMU 驅動 是 libvirt 的首選驅動,如果 KVM 功能已 啟用,則支持全虛擬化和硬體加速的客戶機。詳見 QEMU。
- 其他受支持的虛擬運行環境,包括 LXC、VirtualBox 和 Xen。請參見它們各自的安裝說明。
對於網絡連接,安裝這些包:
- iptables-nft包 和 dnsmasq包 用於 默認的 NAT/DHCP網絡
- bridge-utils包 用於橋接網絡
- openbsd-netcat包 通過 SSH 遠程管理
客戶端
客戶端是用於管理和訪問虛擬機的用戶界面。
- virsh — virsh 是用於管理和配置域(虛擬機)的命令行程序。
- GNOME Boxes — 簡單的 GNOME 3 程序,可以訪問遠程虛擬系統。
- Libvirt Sandbox — 應用程式沙箱工具包。
- Remote Viewer — 簡單的遠程訪問工具。
- Qt VirtManager — 管理虛擬機的Qt程序。
- Virtual Machine Manager — 使用libvirt對KVM,Xen,LXC進行管理的圖形化工具。
兼容 libvirt 的軟體列表見 這裡.
配置
對於系統 級別的管理任務(如:全局配置和鏡像卷 位置),libvirt 要求至少要設置授權和啟動守護進程。
設置授權
來自 libvirt:連接授權:
- Libvirt 守護進程允許管理員分別為客戶端連接的每個網絡 socket 選擇不同授權機制。這主要是通過 libvirt 守護進程的主配置文件
/etc/libvirt/libvirtd.conf
來實現的。每個 libvirt socket 可以有獨立的授權機制配置。目前的可選項有none
、polkit
和sasl
。
由於 libvirt包 在安裝時將把 polkit包 作為依賴一併安裝,所以 polkit 通常是 unix_sock_auth
參數的默認值(來源)。但基於文件的權限仍然可用。
使用 polkit
polkit
認證工作正常,應該重啟一次系統。libvirt 守護進程在 polkit 策略配置文件(/usr/share/polkit-1/actions/org.libvirt.unix.policy
)中提供了兩種策略(參閱:Polkit#操作):
-
org.libvirt.unix.manage
面向完全的管理訪問(讀寫模式後台 socket),以及 -
org.libvirt.unix.monitor
面向僅監視察看訪問(只讀 socket)。
默認的面向讀寫模式後台 socket 的策略將請求認證為管理員。這點類似於 sudo 認證,但它並不要求客戶應用最終以 root 身份運行。默認策略下也仍然允許任何應用連接到只讀 socket。
Arch Linux 默認 wheel
組的所有用戶都是管理員身份:定義於 /etc/polkit-1/rules.d/50-default.rules
(參閱:Polkit#管理員身份認證)。這樣就不必新建組和規則文件。 如果用戶是 wheel
組的成員:只要連接到了讀寫模式 socket(例如通過 virt-manager包)就會被提示輸入該用戶的口令。
pkttyagent
它可能因工作不正常而導致各種問題。從 libvirt 1.2.16 版開始(提案見:[1]),libvirt
組的成員用戶默認可以無口令訪問讀寫模式 socket。最簡單的判斷方法就是看 libvirt 組是否存在並且用戶是否該組成員。
你可能想要修改授權以讀寫模式訪問socket的組,例如,你想授權kvm
組,可創建下面的文件:
/etc/polkit-1/rules.d/50-libvirt.rules
/* Allow users in kvm group to manage the libvirt daemon without authentication(允许 kvm 组的用户管理 libvirt 而无需认证) */ polkit.addRule(function(action, subject) { if (action.id == "org.libvirt.unix.manage" && subject.isInGroup("kvm")) { return polkit.Result.YES; } });
然後添加用戶到 kvm
組並重新登錄。kvm 也可以是任何其它存在的組並且用戶是該組成員(詳閱用戶和用戶組)。
修改組之後不要忘記重新登錄才能生效。
基於文件的權限授權
為了給 libvirt 組用戶定義基於文件的權限以管理虛擬機,取消下列行的注釋:
/etc/libvirt/libvirtd.conf
#unix_sock_group = "libvirt" #unix_sock_ro_perms = "0777" # set to 0770 to deny non-group libvirt users #unix_sock_rw_perms = "0770" #auth_unix_ro = "none" #auth_unix_rw = "none"
有些資料提到可以通過改變某些特定 libvirt 目錄的權限以簡化管理。需要記住的是:包更新時,這些變更會丟失。如要修改這些系統目錄的權限,需要 root 用戶權限。
守護進程
libvirtd.service
和 virtlogd.service
這兩個服務單元都要啟動。可以把 libvirtd.service
設置為啟用,這時系統將同時啟用 virtlogd.service
和 virtlockd.socket
兩個服務單元,因此後二者不必再設置為啟用。
非加密的 TCP/IP sockets
編輯 /etc/libvirt/libvirtd.conf
:
/etc/libvirt/libvirtd.conf
listen_tls = 0 listen_tcp = 1 auth_tcp="none"
同時需要編輯/etc/conf.d/libvirtd
以在監聽模式下啟動服務:
/etc/conf.d/libvirtd
LIBVIRTD_ARGS="--listen"
用主機名訪問虛擬機
在非隔離的、橋接的網絡中從宿主機訪問客戶機,可以通過啟用 libvirt包 提供的 libvirt
NSS 模塊實現。
編輯 /etc/nsswitch.conf
:
/etc/nsswitch.conf
hosts: files libvirt dns myhostname
ping
和 ssh
這類命令用於虛擬機主機名可以正常工作,但 host
和 nslookup
這類命令可能會失敗或產生非預期結果,因後者依賴 DNS 。應改用 getent hosts <vm-hostname>
命令。測試
測試 libvirt 在系統級工作是否正常:
$ virsh -c qemu:///system
測試 libvirt 在用戶會話級工作是否正常:
$ virsh -c qemu:///session
管理
絕大部分的 libvirt 管理可以通過三個工具實現:virt-manager包(圖形界面)、virsh
和 guestfish
(它是 libguestfs包 的一部分)。
virsh
Visrsh 用於管理客戶域(虛擬機),在腳本式虛擬化管理環境中工作良好。由於需要通過通訊管道與虛擬運行環境通訊,絕大部分 virsh 命令需要管理員權限。儘管如此,一些典型的管理操作如域的創建、運行等也可以像VirtualBox 那樣以普通用戶身份執行。
Virsh 允許帶命令行選項執行。如果不帶則進入其內置的交互式終端:virsh
。交互式終端支持 tab 鍵命令補全。
從命令行執行:
$ virsh [可选项] <命令> [参数]...
在交互式終端裡運行:
virsh # <命令> [参数]...
幫助也是可用的:
$ virsh help [option*] or [group-keyword*]
存儲池
存儲池是指保存卷的位置。Libvirt 中卷的定義相當於其他系統中虛擬磁碟或虛擬機鏡像的概念。存儲池應該是一個目錄、一個網絡文件系統或一個分區(此處包括 LVM)。存儲池可以在活動與不活動之間切換,可以為其分配存儲空間。
在系統級別,默認被激活的存儲池是 /var/lib/libvirt/images/
;在用戶會話級別,virt-manager
將存儲池創建在 $HOME/VirtualMachines
目錄。
列出活動和不活動的存儲池的命令:
$ virsh pool-list --all
用 virsh 新建存儲池
以下示例為添加存儲池、目錄和 LVM 卷的方法:
$ virsh pool-define-as name type [source-host] [source-path] [source-dev] [source-name] [<target>] [--source-format format] $ virsh pool-define-as poolname dir - - - - /home/username/.local/libvirt/images $ virsh pool-define-as poolname fs - - /dev/vg0/images - mntpoint
上述示例僅僅定義了存儲池的信息,下面創建它:
$ virsh pool-build poolname $ virsh pool-start poolname $ virsh pool-autostart poolname
刪除它的命令:
$ virsh pool-undefine poolname
- 最佳實踐是僅把一個卷組分配給一個存儲池。
- 請為存儲池選擇一個與 LVM 卷組不同的名字。否則當存儲池被刪除時,該卷組也將被刪除。
用 virt-manager 新建存儲池
首先,連接到虛擬運行環境(例如QEMU/KVM的系統/用戶會話)。然後,右鍵點擊一個連接(例如QEMU/KVM)選擇詳情,切換到存儲選項卡,點擊左下角的+,按照嚮導操作。
存儲卷
存儲池被創建之後,就可以在存儲池中創建存儲卷。如果你想新建一個域(虛擬機),那麼這一步可以跳過,因為這一步可以在創建域的過程中完成。
用 virsh 新建卷
新建卷,列出卷,變更卷大小,刪除卷:
$ virsh vol-create-as poolname volumename 10GiB --format aw|bochs|raw|qcow|qcow2|vmdk $ virsh vol-upload --pool poolname volumename volumepath $ virsh vol-list poolname $ virsh vol-resize --pool poolname volumename 12GiB $ virsh vol-delete --pool poolname volumename $ virsh vol-dumpxml --pool poolname volumename # for details.
virt-manager 後備存儲類型的 bug
在較新版本的virt-manager
中,你可以在創建新磁碟的時候選擇一個後備存儲(backing store)。這個功能很實用,它可以在你創建新域的時候選擇基礎鏡像,從而節省你的時間和磁碟空間。目前的virt-manager
有一個bug(https://bugzilla.redhat.com/show_bug.cgi?id=1235406),导致qcow2
格式的後備存儲被錯誤的當做raw
格式。這會讓虛擬機無法讀取後備存儲,從而使這個功能完全失效。
這裡有一個臨時的解決辦法。qemu-img
長期以來都可以直接實現這個功能。如果你想在這個bug修復之前為新域創建一個後備存儲,你可以使用下面的命令。
$ qemu-img create -f qcow2 -o backing_file=<path to backing image>,backing_fmt=qcow2 <disk name> <disk size>
之後你就可以以此鏡像為基礎創建新域,後備存儲將被用作一個CoW(Copy on Write,寫時複製)卷,節省你的時間和磁碟空間。
域
虛擬機被稱作「域」。如果你想在命令行下操作,使用virsh
列出,創建,暫停,關閉……域。virt-viewer
可以用來查看使用virsh
啟動的域。域的創建通常以圖形化的virt-manager
或者命令行下的virt-install
(一個命令行工具,是virt-install包包的一部分)完成。
創建新域通常需要安裝媒介,例如存儲池中的iso
文件或是直接從光碟機安裝。
列出活動的和不活動的域:
# virsh list --all
/var/lib/libvirt/images/
中的卷可以被訪問。如果你使用SELinux並且在卷方面有問題,確保卷位於該目錄,其他存儲池標記正常。用 virt-install 新建域
對於很詳細的域(虛擬機)配置,可以#用 virt-manager 新建域更簡單地完成。但是,基礎配置同樣可以用virt-install
完成並且同樣運行順利。至少要配置--name
, --memory
, 存儲(--disk
, --filesystem
,或--nodisks
),和安裝方法(通常來說是.iso
文件或CD)。查看virt-install(1)得到未列出的選項和更多的詳情。
Arch Linux(兩個虛擬CPU,1 GiB內存,qcow2,用戶網絡):
$ virt-install \ --name arch-linux_testing \ --memory 1024 \ --vcpus=2,maxvcpus=4 \ --cpu host \ --cdrom $HOME/Downloads/arch-linux_install.iso \ --disk size=2,format=raw \ --network user \ --virt-type kvm
Fedora testing (Xen, 非默認池,無默認控制台):
$ virt-install \ --connect xen:/// \ --name fedora-testing \ --memory 2048 \ --vcpus=2 \ --cpu=host \ --cdrom /tmp/fedora20_x84-64.iso \ --os-type=linux --os-variant=fedora20 \ --disk pool=testing,size=4 \ --network bridge=br0 \ --graphics=vnc \ --noautoconsole $ virt-viewer --connect xen:/// fedora-testing
Windows:
$ virt-install \ --name=windows7 \ --memory 2048 \ --cdrom /dev/sr0 \ --os-variant=win7 \ --disk /mnt/storage/domains/windows7.qcow2,size=20GiB \ --network network=vm-net \ --graphics spice
osinfo-query --fields=name,short-id,version os
來獲得--os-variant
的參數,這可以幫助定製域的一些規格。然而--memory
和--disk
是必須被輸入的。如果需要查看這些規格,可以看看/usr/share/libosinfo/db/oses/os.xml
(譯註:此處可能已過時)。在安裝後,推薦安裝Spice Guest Tools,其中包括VirtIO驅動。Windows的VirtIO網絡驅動可以在virtio-winAUR得到。要使用VirtIO,需要在虛擬機.xml
配置中使用<model type='virtio' />
更多的信息可以參考QEMU頁面.導入現有的卷:
$ virt-install \ --name demo \ --memory 512 \ --disk /home/user/VMs/mydisk.img \ --import
用 virt-manager 新建域
首先,連接到虛擬運行環境(例如 QEMU/KVM system 或用戶 session,在連接上右擊並選擇 新建,然後跟隨嚮導完成。
- 在第四步中取消選中立即分配全部虛擬磁碟空間會加快創建過程並節省實際虛擬磁碟空間占用;然而,這將導致將來花費額外的磁碟整理時間。
- 在第五步中打開高級選項並確認虛擬化類型設為 kvm(這通常是首選模式)。如果要求附加的硬體配置,選中安裝前定製選項。
管理域
啟動域:
$ virsh start domain $ virt-viewer --connect qemu:///session domain
正常關閉域;強制關閉域:
$ virsh shutdown domain $ virsh destroy domain
在libvirtd啟動時自動啟動域:
$ virsh autostart domain $ virsh autostart domain --disable
在宿主機關閉時自動關閉域:
- 使用
libvirt-guests.service
Systemd服務,運行中的域可以在宿主機關閉時自動掛起/關閉。同時這個服務還可以讓掛起/休眠的域在宿主機啟動的時候自動恢復。查看/etc/conf.d/libvirt-guests
並設置相關選項。
編輯一個域的XML配置:
$ virsh edit domain
網絡
這裡是有關 libvirt 網絡的一個正宗的概述。
默認情況下,當 libvirtd
服務啟動後,即創建了一個名為 default 的 NAT 網橋與外部網絡聯通(僅 IPv4)。對於其他的網絡連接需求,可創建下列四種類型的網絡以連接到虛擬機:
- bridge — 這是一個虛擬設備,它通過一個物理接口直接共享數據。使用場景為:宿主機有 靜態 網絡、不需與其它域連接、要占用全部進出流量,並且域運行於 系統 層級。有關如何在現有默認網橋時增加另一個網橋的方法,請參閱 網橋。網橋創建後,需要將它指定到相應客戶機的
.xml
配置文件中。 - network — 這是一個虛擬網絡,它可以與其它虛擬機共用。使用場景為:宿主機有 動態 網絡(例如:NetworkManager)或使用無線網絡。
- macvtap — 直接連接到宿主機的一個物理網絡接口。
- user — 本地網絡,僅用於用戶 會話。
絕大多數用戶都可以通過 virsh
的各種可選項創建具有各種功能的網絡,一般來說比通過 GUI 程序(像 virt-manager
之類)更容易做到。也可以按 #用 virt-install 新建域 所述實現。
ip_forward
內核參數。這也意味著宿主機上已運行的dnsmasq並不是libvirt所必須的(並可能干擾到libvirt的dnsmasq實例)。IPv6
當通過任何配置工具試圖添加IPv6地址時,你可能會遇到這樣的錯誤:
Check the host setup: enabling IPv6 forwarding with RA routes without accept_ra set to 2 is likely to cause routes loss. Interfaces to look at: eth0
要修復這個問題,創建如下的文件(將eth0
改為你的物理接口的名稱),並且重新啟動系統。
/etc/sysctl.d/libvirt-bridge.conf
net.ipv6.conf.eth0.accept_ra = 2
快照
快照保存某一時刻域的磁碟、內存和設備狀態以供將來使用。快照有很多用處,例如在進行可能的破壞性操作時保存一份乾淨的域狀態。快照使用唯一名稱進行標識。
快照保存在卷之中,卷必須為qcow2或raw格式。快照使用增量存儲,所以並不會占用很多空間。
創建快照
Once a snapshot is taken it is saved as a new block device and the original snapshot is taken offline. Snapshots can be chosen from and also merged into another (even without shutting down the domain).
Print a running domain's volumes (running domains can be printed with virsh list
):
# virsh domblklist domain
Target Source ------------------------------------------------ vda /vms/domain.img
To see a volume's physical properties:
# qemu-img info /vms/domain.img
image: /vms/domain.img file format: qcow2 virtual size: 50G (53687091200 bytes) disk size: 2.1G cluster_size: 65536
Create a disk-only snapshot (the option --atomic
will prevent the volume from being modified if snapshot creation fails):
# virsh snapshot-create-as domain snapshot1 --disk-only --atomic
List snapshots:
# virsh snapshot-list domain
Name Creation Time State ------------------------------------------------------------ snapshot1 2012-10-21 17:12:57 -0700 disk-snapshot
One can they copy the original image with cp --sparse=true
or rsync -S
and then merge the the original back into snapshot:
# virsh blockpull --domain domain --path /vms/domain.snapshot1
domain.snapshot1
becomes a new volume. After this is done the original volume (domain.img
and snapshot metadata can be deleted. The virsh blockcommit
would work opposite to blockpull
but it seems to be currently under development (including snapshot-revert feature
, scheduled to be released sometime next year.
其他管理操作
連接到非默認的虛擬運行環境:
$ virsh --connect xen:/// virsh # uri xen:///
通過SSH連接到QEMU虛擬運行環境,並且以相同方式登錄:
$ virsh --connect qemu+ssh://username@host/system $ LIBVIRT_DEBUG=1 virsh --connect qemu+ssh://username@host/system
通過SSH連接到一個圖形控制台:
$ virt-viewer --connect qemu+ssh://username@host/system domain $ virt-manager --connect qemu+ssh://username@host/system domain
連接到VirtualBox(libvirt對VirtualBox的支持尚不穩定,可能會導致libvirtd崩潰):
$ virsh --connect vbox:///system
網絡配置:
$ virsh -c qemu:///system net-list --all $ virsh -c qemu:///system net-dumpxml default
Python 連接代碼
libvirt-python包軟體包提供了一個python2AURAPI,位於/usr/lib/python2.7/site-packages/libvirt.py
。
一般的例子在/usr/share/doc/libvirt-python-your_libvirt_version/examples/
給出。
一個qemu-desktop包和openssh包的例子(非官方):
#! /usr/bin/env python2 # -*- coding: utf-8 -*- import socket import sys import libvirt if (__name__ == "__main__"): conn = libvirt.open("qemu+ssh://xxx/system") print "Trying to find node on xxx" domains = conn.listDomainsID() for domainID in domains: domConnect = conn.lookupByID(domainID) if domConnect.name() == 'xxx-node': print "Found shared node on xxx with ID " + str(domainID) domServ = domConnect break
UEFI 支持
Libvirt 可以通過 qemu 和 OVMF 來支持 UEFI 虛擬機。
安裝 edk2-ovmf包 。
添加下面的內容到 /etc/libvirt/qemu.conf
。
/etc/libvirt/qemu.conf
nvram = [ "/usr/share/ovmf/x64/OVMF_CODE.fd:/usr/share/ovmf/x64/OVMF_VARS.fd" ]
- 重啟
libvirtd
現在你可以創建一個 UEFI 虛擬機了。 你可以通過 virt-manager包 來創建。當你進行到嚮導的最後一步時:
- 勾選在安裝前自定義配置,之後點擊完成。
- 在概況屏幕, 將固件改為'UEFI x86_64'。
- 點擊開始安裝
- 在啟動屏幕,你需要使用linuxefi命令來啟動安裝程序,並且你需要在系統中運行efibootmgr驗證確實運行在UEFI模式下。
參考fedora wiki獲得更多信息。
PulseAudio
PulseAudio守護進程通常在你的普通用戶下運行,並且只接受來自相同用戶的連接。然而libvirt默認使用root運行QEMU。為了讓QEMU在普通用戶下運行,編輯/etc/libvirt/qemu.conf
並將user
設置為你的用戶名。
user = "dave"
你同樣需要告訴QEMU使用PulseAudio後端並識別要連接的伺服器,首先將QEMU命名空間添加到你的域。
編輯域的.xml
文件(使用virsh edit domain
),將domain type
行改為:
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'[失效連結 2020-08-02 ⓘ]>
並且加入如下的配置(在最後一個</devices>
之後,</domain>
之前):
<qemu:commandline> <qemu:env name='QEMU_AUDIO_DRV' value='pa'/> <qemu:env name='QEMU_PA_SERVER' value='/run/user/1000/pulse/native'/> </qemu:commandline>
1000
是你的用戶ID,如果必要的話改為你的用戶ID。