libvirt 庫是一種實作 linux 虛拟化功能的 linux® api,它支援各種虛拟機監控程式,包括 xen 和 kvm,以及 qemu 和用于其他作業系統的一些虛拟産品。本文主要探讨 libvirt 及其用途和架構。
講到向外擴充計算(比如雲計算),libvirt 可能是您從未聽說過的最重要的庫之一。libvirt 提供一種虛拟機監控程式不可知的 api 來安全管理運作于主機上的來賓作業系統。libvirt 本身不是一種工具, 它是一種可以建立工具來管理來賓作業系統的 api。libvirt 本身建構于一種抽象的概念之上。它為受支援的虛拟機監控程式實作的常用功能提供通用的 api。libvirt 起初是專門為 xen 設計的一種管理 api,後來被擴充為可支援多個虛拟機監控程式。
<a target="_blank"></a>
首先讓我們從用例模型視角來展開對 libvirt 的讨論,然後深入探究其架構和用途。libvirt 以一組 api 的形式存在,旨在供管理應用程式使用(見圖 1 )。libvirt 通過一種特定于虛拟機監控程式的機制與每個有效虛拟機監控程式進行通信,以完成 api 請求。文章後面我将探讨如何通過 qemu 來實作該功能。
libvirt 比較和用例模型
圖中還顯示了 libvirt 所用術語對照。這些術語很重要,因為在對 api 命名時會用到它們。兩個根本差別在于,libvirt 将實體主機稱作節點,将來賓作業系統稱作域。這裡需要注意的是,libvirt(及其應用程式)在宿主 linux 作業系統(域 0)中運作。
使用 libvirt,我們有兩種不同的控制方式。第一種如 圖 1 所示,其中管理應用程式和域位于同一節點上。 在本例中,管理應用程式通過 libvirt 工作,以控制本地域。當管理應用程式和域位于不同節點上時,便産生了另一種控制方式。在本例中需要進行遠端通信(參見 圖 2)。該模式使用一種運作于遠端節點上、名為 libvirtd 的特殊守護程序。當在新節點上安裝 libvirt 時該程式會自動啟動,且可自動确定本地虛拟機監控程式并為其安裝驅動程式(稍後讨論)。該管理應用程式通過一種通用協定從本地 libvirt 連接配接到遠端 libvirtd。對于 qemu,協定在 qemu 螢幕處結束。qemu 包含一個監測控制台,它允許檢查運作中的來賓作業系統并控制虛拟機(vm)各部分。
使用 libvirtd 控制遠端虛拟機監控程式
為支援各種虛拟機監控程式的可擴充性,libvirt 實施一種基于驅動程式的架構,該架構允許一種通用的 api 以通用方式為大量潛在的虛拟機監控程式提供服務。這意味着,一些虛拟機監控程式的某些專業功能在 api 中不可見。另外,有些虛拟機監控程式可能不能實施所有 api 功能,因而在特定驅動程式内被定義為不受支援。圖 3 展示了 libvirt api 與相關驅動程式的層次結構。這裡也需要注意,libvirtd 提供從遠端應用程式通路本地域的方式。
基于驅動程式的 libvirt 架構
在撰寫此文時,libvirt 為表 1 所列的虛拟機監控程式實作了驅動程式。随着新的虛拟機監控程式在開源社群出現,其他驅動程式無疑也将可用。
虛拟機監控程式
描述
xen
面向 ia-32,ia-64 和 powerpc 970 架構的虛拟機監控程式
qemu
面向各種架構的平台仿真器
kernel-based virtual machine (kvm)
linux 平台仿真器
linux containers(lxc)
用于作業系統虛拟化的 linux(輕量級)容器
openvz
基于 linux 核心的作業系統級虛拟化
virtualbox
x86 虛拟化虛拟機監控程式
user mode linux
面向各種架構的 linux 平台仿真器
test
面向僞虛拟機監控程式的測試驅動器
storage
存儲池驅動器(本地磁盤,網絡磁盤,iscsi 卷)
上面已經介紹了 libvirt 的一些架構,接下來看一下如何使用 libvirt 虛拟化 api 的一些示例。首先介紹一種名為 virsh(虛拟 shell)的應用程式,它建構于 libvirt 之上。該 shell 允許以互動(基于 shell)方式使用多個 libvirt 功能。在本節中,我使用 virsh 示範了一些 vm 操作。
第一步是要定義域配置檔案(如下面的 清單 1 所示)。該代碼指定了定義域所需的所有選項 — 從虛拟機監控程式(仿真器)到域使用的資源以及外圍配置(比如網絡)。注意,這隻是個簡單的配置,libvirt 真正支援的屬性更加多樣化。例如,您可以指定 bios 和主機引導程式,域要使用的資源,以及要用到的裝置 — 從軟碟和 cd-rom 到 usb 和 pci 裝置。
域配置檔案定義該 qemu 域要使用的一些基本中繼資料,包括域名、最大記憶體、初始可用記憶體(目前)以及該域可用的虛拟處理器數量。您不需要自己配置設定 universally unique idenifier (uuid),而是讓 libvirt 配置設定。您需要為該平台定義要仿真的機器類型 — 在本例中是被完全虛拟化(hvm)的 686 處理器。您需要為域定義仿真器的位置(以備需要支援多個同類型仿真器時使用)和虛拟磁盤。這裡注意要指明 vm,它是以 virtual machine disk(vmdk)格式存在的 reactos 作業系統。最後,要指定預設網絡設定,并使用面向圖形的 virtual network computing (vnc)。
<xml version="1.0"?>
<domain type='qemu'>
<name>reactos-on-qemu<name>
<uuid><uuid>
<memory>131072<memory>
<currentmemory>131072<currentmemory>
<vcpu>1<vcpu>
<os>
<type arch='i686' machine='pc'>hvm<type>
<devices>
<emulator>usr/bin/qemu<emulator>
<disk type='file' device='disk'>
<source file='/home/mtj/libvtest/reactos.vmdk'/>
<target dev='hda'/>
<disk>
<interface type='network'>
<source network='default'/>
<interface>
<graphics type='vnc' port='-1'/>
<domain>
完成了域配置檔案之後,現在開始使用 virsh 工具啟動域。virsh 工具為要執行的特定動作采用指令參數。在啟動新域時,使用 create 指令和域配置檔案:
mtj@mtj-desktop:~/libvtest$ virsh create react-qemu.xml
connecting to uri: qemu:///system
domain reactos-on-qemu created from react-qemu.xml
mtj@mtj-desktop:~/libvtest$
這裡要注意用于連接配接到域(qemu:///system)的 universal resource indicator (uri)。該本地 uri 連接配接到本地 qemu 驅動程式的系統模式守護程序上。要通過主機 shinchan 上的 secure shell (ssh) 協定連接配接到遠端 qemu 虛拟機監控程式,可以使用 url qemu+ssh://shinchan/。
下一步,您可以使用 virsh 内的 list 指令列出給定主機上的活動域。這樣做可以列出活動域,域 id,以及它們的狀态,如下所示:
mtj@mtj-desktop:~/libvtest$ virsh list
id name state
----------------------------------
1 reactos-on-qemu running
注意,這裡定義的名稱是在域配置檔案中繼資料中定義過的名稱。可以看到,該域的域名是 1 且正在運作中。
您也可以使用 suspend 指令中止域。該指令可停止處于排程中的域,不過該域仍存在于記憶體中,可快速恢複運作。下面的例子展示了如何中止域,執行清單檢視狀态,然後重新啟動域:
mtj@mtj-desktop:~/libvtest$ virsh suspend 1
domain 1 suspended
1 reactos-on-qemu paused
mtj@mtj-desktop:~/libvtest$ virsh resume 1
domain 1 resumed
virsh 工具也支援許多其他指令,比如儲存域的指令(save),恢複已存域的指令(restore),重新啟動域的指令(reboot),以及其他指令。您還可以從運作中的域(dumpxml)建立域配置檔案。
到目前為止,我們已經啟動并操作了域,但是如何連接配接域來檢視目前活動域呢?這可以通過 vnc 實作。要建立表示特定域圖形桌面的視窗,可以使用 vnc:
mtj@mtj-desktop:~/libvtest$ xvnc4viewer 127.0.0.1 0
上一個例子說明了如何使用指令行工具 virsh 實作對域的控制。現在我們看一個使用 python 來控制域的例子。python 是受 libvirt 支援的腳本語言,它向 libvirt api 提供完全面向對象的接口。
在本例中,我研究了一些基本操作,與之前用 virsh 工具(list、suspend、resume 等)展示的操作類似。python 示例腳本見 清單 6。在本例中,我們從導入 libvirt 子產品開始。然後連接配接到本地 qemu 虛拟機監控程式。從這裡開始,重複可用的域 id;對每個 id 建立一個域對象,然後中止,繼續,最後删除該域。
import libvirt
conn = libvirt.open('qemu:///system')
for id in conn.listdomainsid():
dom = conn.lookupbyid(id)
print "dom %s state %s" % ( dom.name(), dom.info()[0] )
dom.suspend()
print "dom %s state %s (after suspend)" % ( dom.name(), dom.info()[0] )
dom.resume()
print "dom %s state %s (after resume)" % ( dom.name(), dom.info()[0] )
dom.destroy()
雖然這隻是個簡單示例,我們仍然可以看到 libvirt 通過 python 提供的強大功能。通過一個簡單的腳本就能夠重複所有本地 qemu 域,發行有關域的資訊,然後控制域。該腳本的結果如 清單 7 所示。
mtj@mtj-desktop:~/libvtest$ python libvtest.py
dom reactos-on-qemu state 1
dom reactos-on-qemu state 3 (after suspend)
dom reactos-on-qemu state 1 (after resume)
進階 libvirt api 可劃分為 5 個 api 部分:虛拟機監控程式連接配接 api、域 api、網絡 api、存儲卷 api 以及存儲池 api。
為給定虛拟機監控程式建立連接配接後會産生所有 libvirt 通信(例如,清單 6 中所示的 open 調用)。該連接配接為所有其他要使用的 api 提供路徑。在 c api 中,該行為通過 virconnectopen 調用(以及其他進行認證的調用)提供。這些函數的傳回值是一個 virconnectptr 對象,它代表到虛拟機監控程式的一個連接配接。該對象作為所有其他管理功能的基礎,是對給定虛拟機監控程式進行并發 api 調用所必需的語句。重要的并發調用是 virconnectgetcapabilities 和 virnodegetinfo,前者傳回虛拟機監控程式和驅動程式的功能,後者擷取有關節點的資訊。該資訊以 xml 文檔的形式傳回,這樣通過解析便可了解可能發生的行為。
進入虛拟機監控程式後,便可以使用一組 api 調用函數重複使用該虛拟機監控程式上的各種資源。virconnectlistdomains api 調用函數傳回一列域辨別符,它們代表該虛拟機監控程式上的活動域。
api 實作大量針對域的函數。要探究或管理域,首先需要一個 virdomainptr 對象。您可通過多種方式獲得該句柄(使用 id、uuid 或域名)。繼續來看重複域的例子,您可以使用該函數傳回的索引表并調用 virdomainlookupbyid 來擷取域句柄。有了該域句柄,就可以執行很多操作,從探究域(virdomaingetuuid、virdomaingetinfo、virdomaingetxmldesc、virdomainmemorypeek)到控制域(virdomaincreate、virdomainsuspend、virdomainresume、virdomaindestroy 和 virdomainmigrate)。
您還可使用 api 管理并檢查虛拟網絡和存儲資源。建立了 api 模型之後,需要一個 virnetworkptr 對象來管理并檢查虛拟網絡,且需要一個virstoragepoolptr(存儲池)或 virstoragevolptr(卷)對象來管理這些資源。
api 還支援一種事件機制,您可使用該機制注冊為在特定事件(比如域的啟動、中止、恢複或停止)發生時獲得通知。
libvirt 庫用 c (支援 c++)實作,且包含對 python 的直接支援。不過它還支援大量語言綁定。目前已經對 ruby、java™ 語言,perl 和 ocaml 實施了綁定。在從 c# 調用 libvirt 方面我們已做了大量工作。libvirt 支援最流行的系統程式設計語言(c 和 c++)、多種腳本語言、甚至一種統一的函數型語言(objective caml)。是以,不管您側重何種語言,libvirt 都會提供一種路徑來幫助您控制域。
僅從本文已經展示的一小部分功能上便可看出 libvirt 提供的強大功能。且如您所願,有大量應用程式正成功建構于 libvirt 之上。其中一個有趣的應用程式就是 virsh(這裡所示),它是一種虛拟 shell。還有一種名為 virt-install 的應用程式,它可用于從多個作業系統發行版供應新域。virt-clone 可用于從另一個 vm 複制 vm(既包括作業系統複制也包括磁盤複制)。一些進階應用程式包括多用途桌面管理工具 virt-manager 和安全連接配接到 vm 圖形控制台的輕量級工具 virt-viewer。
建構于 libvirt 之上的一種最重要的工具名為 ovirt。ovirt vm 管理應用程式旨在管理單個節點上的單個 vm 或多個主機上的大量 vm。除了可以簡化大量主機和 vm 的管理之外,它還可用于跨平台和架構自動化叢集,負載平衡和工作。
從這篇簡短的文章可以看出,libvirt 是一種用來建構應用程式的強大庫,能夠跨系統的大型網絡在不同的虛拟機監控程式環境中管理域。鑒于雲計算的日漸流行,libvirt 無疑也會随之發展,不斷獲得新的應用程式和使用者。撰寫本文時,libvirt 也僅有四年的發展史,是以在大規模可伸縮計算領域中相對較新。libvirt 将來肯定會有很大發展。
原文釋出時間:2014-11-19
本文來自雲栖合作夥伴“linux中國”