How-To:Linux 建置 KVM 虛擬機器

操作環境:

  • Fedora 38

 

Linux 的 KVM(Kernel-based Virtual Machine)技術,旨在為 Linux 平台提供原生的虛擬化解決方案。KVM 從問世之初便引起了高度關注,如今已廣泛地應用在雲端主機服務或企業級的虛擬化設施上。然而有很長一段時間,DR 自己的試驗環境仍是習於使用 VirtualBox 來建置,畢竟它也是一套在安裝及使用上都相當簡易的虛擬化軟體。但直到最近開始覺得,既然 KVM 是 Linux 本身即提供的虛擬化方案,應該是直接使用 KVM 就好。因此本文會是一份在 Linux 工作站電腦上建立 KVM 虛擬機器的簡單說明。

 

準確來說,KVM 是指涉 Linux 內核中提供虛擬化支援的模組,它需要搭配 QEMU 這套模擬器暨虛擬化程式,以及 libvirt 工具及服務,才能構成完整可操作的虛擬化軟體。不過 KVM 自 Linux 2.6.20 起便是內建模組,以及 QEMU 及 libvirt 的安裝則也是相當簡易,在 Fedora 發行版上只需要一行指令即可安裝完畢。

 

1. 檢查硬體規格

關於 KVM 的基本硬體需求,即是 CPU 得支援虛擬化技術,也就是 Intel VT-x 或者是 AMD-V。並且在主機板的韌體(BIOS/UEFI)設定內,也需要檢查相應的項目是否有啟用。倘若為停用狀態,儘管 QEMU 也能夠在不依賴 KVM 的情況下啟動虛擬機器,但效能會差非常多。

 

2.安裝所需套件

執行以下 dnf 群組安裝指令:

  • sudo dnf group install virtualization

 

3. 執行 virt-manager

執行前一步驟的安裝指令後,應該會一併安裝 virt-manager(Virtual Machine Manager)這套圖形介面的虛擬機管理程式,可用於新增、執行及管理虛擬機器,在桌面環境下應比使用文字介面的 virsh 來得方便許多。執行指令如下:

  • sudo virt-manager

 

若未加上 sudo,則執行時依然會要求 root 權限,獲取權限後才能夠順利執行。或者替代方式是將當前使用者加入到 libvirt 群組內:

  • sudo usermod -a -G libvirt <username>

 

在執行 virt-manager 時也會一併啟動 libvirtd 服務(若先前未啟動的話),可使用以下指令檢查服務執行狀態:

  • sudo systemctl status libvirtd

 

倘若在中文環境下,覺得 virt-manager 的中文介面不太順眼,則可在執行時將環境變數調整為英文:

  • LANG=en_US.UTF-8 sudo virt-manager

 

 

virt-manager 的操作細節基本上無須贅述,應該很容易就能夠瞭解建立及管理虛擬機器的方式。或許唯一需要留意之處,是建立出來的客體(guest)機器,預設不會反映出主體(host)的真實 CPU 型號。而這在某些情境下,對於客體機的運作效能可能會有不一的影響。至於調整的方式,是前往【Edit】→【Preferences】→【New VM】,將【CPU default】從「Application default」變更為「host-passthrough」。或者是開啟已建立的虛擬機器,於【View】→【Details】→【CPUs】→【Configuration】,將【Model】變更為「host-passthrough」。

 

因著不同的使用情境及管理需求,其實也是有 virt-manager、virsh 以外的管理工具可使用,相關清單可參考 Management Tools 頁面。

 

4. VirtIO

QEMU/KVM 容許以半虛擬化(paravirtualization)的方式,來驅動客體機的網路及磁碟裝置,藉此得到更佳的效能表現。然而其前提是客體的作業系統得具備 VirtIO 驅動程式,並在虛擬機器的網路或磁碟設定中,指定使用 VirtIO 作為裝置類型。反之倘若客體系統不具備 VirtIO 驅動程式,則應留意在虛擬機器設定中不應使用 VirtIO,否則會無法順利執行。

 

5. 網路設定

libvirt 預設提供給客體機的網路連線方式為 NAT 模式,此模式會形成一組虛擬網路,由主體機擔當路由器,並配發私有 IP 位址給客體機。在 NAT 模式下,客體會透過主體的網路來對外連線,並且客體與客體之間、以及主體與客體之間,也能夠透過各自的私有 IP 位址來進行連線。以下指令可用於檢視各個客體所分配到的 IP 位址:

  • virsh net-dhcp-leases default

 

倘若希望客體能夠與實體的區域網路接通,則有不只一種實現方式。一般來說,最常見的作法是改採橋接(bridge)模式。此模式需要修改主體機的網路設定,新增一個橋接介面,並改用橋接介面來進行連線。以下的操作範例是使用 NetworkManager 的 nmcli 工具,首先可以藉由下列指令來檢視 NetworkManager 內的連線清單,後續也可以多次利用此指令來檢查異動情形:

  • nmcli con show

 

假設實體網卡介面為 enp5s0,以及欲建立的橋接介面為 br0。那麼第一步驟就是建立名為 br0 的橋接介面,其中明確地停用 STP,則是為了避免在後續啟動橋接時出現不必要的延遲:

  • sudo nmcli con add type bridge autoconnect yes con-name br0 ifname br0 stp no

 

在預設情況下,新增的橋接介面會嘗試自動取得 IP 位址及相關設定(也就是 DHCP)。倘若希望手動設定,比方說指定 IPv4 位址、閘道、DNS,以及明確地停用 IPv6 等設定,則接著再執行以下修改指令:

  • sudo nmcli con modify br0 ipv4.method manual ipv4.addresses 192.168.1.112/24 gw4 192.168.1.1 ipv4.dns "8.8.8.8 8.8.4.4"
  • sudo nmcli con modify br0 ipv6.method disabled

 

然後再將實體網卡介面 enp5s0 分派給 br0:

  • sudo nmcli con add type bridge-slave autoconnect yes con-name br0p1 ifname enp5s0 master br0

 

由於在橋接的配置下,主體機取得網路連線的會是 br0 而非 enp5s0。因此應取消原本 enp5s0 的自動連線,並關閉現有的 enp5s0 連線:

  • sudo nmcli con modify enp5s0 connection.autoconnect no
  • sudo nmcli con down enp5s0

 

然而請注意前述兩段指令中的 enp5s0,指的是 NetworkManager 內所建立的連線名稱。在 Linux 桌面環境下,它很可能不必然等同於網卡介面的名稱,請以系統當前所看到的連線名稱為準。

 

最後的步驟便是啟動 br0 連線:

  • sudo nmcli con up br0

 

橋接設定若是有順利運作,br0 介面應會取得 IP 位址,反之 enp5s0 則是無 IP 位址的狀態,可使用「ip a」指令加以檢視。倘若有些非預期的狀況需要排查,則可以看看 dmesg 的輸出訊息是否有什麼線索。

 

前述步驟中所列的 nmcli 指令設定,其實也可以透過圖形化設定工具(例如 nm-connection-editor 或 nmtui)實作出來,不過在此不再特別多做說明。倘若已確認主體機在橋接設定下連線正常,那麼便能夠在 virt-manager 裡,於客體機器的【View】→【Details】內,編輯現有的客體網卡(或者也可以新增一張網卡),然後將【Network source】選項變更為「Bridge device」,並指定【Device name】為 br0 後套用變更。如此一來,客體機的網卡就會銜接到與主體機相同的區域網路中。

 

6. 匯入 OVA

若是有匯入 *.ova 虛擬設備封裝的需求,最基本的實作方式,是將 *.ova 解開來,例如:

  • tar xvf <OVA 檔案>

 

然後便建立新的虛擬機器,將解開的虛擬磁碟映像檔指定到磁碟設定中。倘若欲轉換磁碟映像的格式,則可以使用 qemu-img 工具,例如以下指令能夠將 *.vmdk 轉換為 *.qcow2:

  • qemu-img convert -O qcow2 <VMDK 檔案> <QCOW2 檔案>

 

7. 其它參考資料