出自 Arch Linux 中文维基

Libvirt 是一組軟體的匯集,提供了管理虛擬機和其它虛擬化功能(如:存儲和網絡接口等)的便利途徑。這些軟體包括:一個長期穩定的 C 語言 API、一個守護進程(libvirtd)和一個命令行工具(virsh)。Libvirt 的主要目標是提供一個單一途徑以管理多種不同虛擬化方案以及虛擬化主機,包括:KVM/QEMUXenLXCOpenVZVirtualBox 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):

  • 其他受支持的虛擬運行環境,包括 LXCVirtualBoxXen。請參見它們各自的安裝說明。
    • Libvirt 的 LXC 驅動 並不依賴 lxc 提供的用戶空間工具。因此,即便需要使用這個驅動也並不是必須安裝該工具。
    • Libvirt 能支持 Xen,但默認未內建支持。需要用 ABS 編輯 libvirtPKGBUILD ,去掉 --without-xen 選項後重新構建(built)libvirt。由於 VirtualBox 尚未正式支持 Xen,所以應當用 --without-vbox 選項替換前述選項。

對於網絡連接,安裝這些包:

客戶端

客戶端是用於管理和訪問虛擬機的用戶界面。

  • virshvirsh 是用於管理和配置域(虛擬機)的命令行程序。
https://libvirt.org/ || libvirt
  • GNOME Boxes — 簡單的 GNOME 3 程序,可以訪問遠程虛擬系統。
https://wiki.gnome.org/Apps/Boxes || gnome-boxes
  • Libvirt Sandbox — 應用程式沙箱工具包。
https://sandbox.libvirt.org/ || libvirt-sandboxAUR
  • Remote Viewer — 簡單的遠程訪問工具。
https://virt-manager.org/ || virt-viewer
  • Qt VirtManager — 管理虛擬機的Qt程序。
https://github.com/F1ash/qt-virt-manager || qt-virt-managerAUR
https://virt-manager.org/ || virt-manager

兼容 libvirt 的軟體列表見 這裡.

配置

對於系統 級別的管理任務(如:全局配置和鏡像 位置),libvirt 要求至少要設置授權啟動守護進程

注意: 對於用戶會話 級別的管理任務,守護進程的安裝和設置不是 必須的。授權總是僅限本地,前台程序將啟動一個 libvirtd 守護進程的本地實例。

設置授權

來自 libvirt:連接授權

Libvirt 守護進程允許管理員分別為客戶端連接的每個網絡 socket 選擇不同授權機制。這主要是通過 libvirt 守護進程的主配置文件 /etc/libvirt/libvirtd.conf 來實現的。每個 libvirt socket 可以有獨立的授權機制配置。目前的可選項有 nonepolkitsasl

由於 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)就會被提示輸入該用戶的口令。

注意: 要求口令的提示由系統中的認證代理給出(參閱:Polkit#身份認證組件)。文本控制台默認的認證代理是 pkttyagent 它可能因工作不正常而導致各種問題。
提示:如果要配置無口令認證,參閱 Polkit#跳過口令提示

從 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.servicevirtlogd.service這兩個服務單元都要啟動。可以把 libvirtd.service 設置為啟用,這時系統將同時啟用 virtlogd.servicevirtlockd.socket 兩個服務單元,因此後二者不必再設置為啟用

非加密的 TCP/IP sockets

警告: 這種方法常用於在可信網絡中快速連接遠程域做協助。這是最不安全 的連接方式,應當僅僅 用於測試或用於安全、私密和可信的網絡環境。這時 SASL 沒有啟用,所以所有的 TCP 通訊都是明文傳輸。在正式的應用場合應當始終 啟用 SASL。

編輯 /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
注意: pingssh 這類命令用於虛擬機主機名可以正常工作,但 hostnslookup 這類命令可能會失敗或產生非預期結果,因後者依賴 DNS 。應改用 getent hosts <vm-hostname> 命令。

測試

測試 libvirt 在系統級工作是否正常:

$ virsh -c qemu:///system

測試 libvirt 在用戶會話級工作是否正常:

$ virsh -c qemu:///session

管理

絕大部分的 libvirt 管理可以通過三個工具實現:virt-manager(圖形界面)、virshguestfish(它是 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 存儲池而言:
  • 最佳實踐是僅把一個卷組分配給一個存儲池。
  • 請為存儲池選擇一個與 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
注意: SELinux有內置策略使在/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.serviceSystemd服務,運行中的域可以在宿主機關閉時自動掛起/關閉。同時這個服務還可以讓掛起/休眠的域在宿主機啟動的時候自動恢復。查看/etc/conf.d/libvirt-guests並設置相關選項。

編輯一個域的XML配置:

$ virsh edit domain
注意: 直接被QEMU啟動的虛擬機不被libvirt管理。

網絡

這裡是有關 libvirt 網絡的一個正宗的概述。

默認情況下,當 libvirtd 服務啟動後,即創建了一個名為 default 的 NAT 網橋與外部網絡聯通(僅 IPv4)。對於其他的網絡連接需求,可創建下列四種類型的網絡以連接到虛擬機:

  • bridge — 這是一個虛擬設備,它通過一個物理接口直接共享數據。使用場景為:宿主機有 靜態 網絡、不需與其它域連接、要占用全部進出流量,並且域運行於 系統 層級。有關如何在現有默認網橋時增加另一個網橋的方法,請參閱 網橋。網橋創建後,需要將它指定到相應客戶機的 .xml 配置文件中。
  • network — 這是一個虛擬網絡,它可以與其它虛擬機共用。使用場景為:宿主機有 動態 網絡(例如:NetworkManager)或使用無線網絡。
  • macvtap — 直接連接到宿主機的一個物理網絡接口。
  • user — 本地網絡,僅用於用戶 會話

絕大多數用戶都可以通過 virsh 的各種可選項創建具有各種功能的網絡,一般來說比通過 GUI 程序(像 virt-manager 之類)更容易做到。也可以按 #用 virt-install 新建域 所述實現。

注意: libvirt 通過 dnsmasq 處理 DHCP 和 DNS 請求,以啟動每個虛擬網絡的不同實例。也會為特定的路由添加 iptables 規則並啟用 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格式。快照使用增量存儲,所以並不會占用很多空間。

創建快照

Tango-view-refresh-red.png本文內容或本節內容已經過期。Tango-view-refresh-red.png

原因: Some of this data appears to be dated. (在Talk:Libvirt討論)

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
注意: 如果你在連接RHEL伺服器(或其他不是Arch的伺服器)時出現問題,嘗試這兩個解決方案:FS#30748FS#22068.

連接到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-desktopopenssh的例子(非官方):

#! /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。

參閱