Ubuntu Server + Linux KVM 虛擬主機最小安裝設定與管理

如果覺得文長這裡有精簡版

以下過程都在 root 權限下操作,如果有找不到指令或出現 Premission Denied 權限不足提示,自行視情況加 sudo 或進 root 權限模式操作。

提示符號 $ 並不是指在一般權限下執行,單純只是 root 提示符號 # 容易與註解 # 混淆。

準備工作

  • 一台主機
  • 2G 以上 USB 隨身碟
  • 路環境有 DHCP Server,且取得的 IP 可以連上網路
  • Ubuntu Server 安裝 ISO 檔

安裝 Ubuntu server

製作 Live USB 開機安裝碟

Windows 可以用 Rufus 製作。

macOS 環境則可以直接製作:

  1. 磁碟工具程式清除(格式化) USB 隨身碟,格式選 FAT + GUID
  2. 在終端機執行 diskutil list 確認 USB 隨身碟掛載的裝置代號 (假設 /dev/disk2)
  3. 卸載 USB 隨身碟
    diskutil unmountDisk /dev/disk2
  4. 把 ISO 轉換成 DMG 檔
    hdiutil convert -format UDRW -o converted-ubuntu-filename ubuntu-live-server-amd64.iso
  5. 把 DMG 檔寫入 USB 隨身碟
    dd if=converted-ubuntu-filename.dmg of=/dev/disk2 bs=1m
  6. 完成後插上要安裝 Ubuntu Server 的主機開機,記得進 BIOS 變更 USB 開機優先。

安裝 Ubuntu server

依提示自行照需求安裝,過程沒幾個步驟,我自己選最小安裝及啟用 OpenSSH Server,其餘都是預值安裝下去。

  • Ubuntu Server 安裝過程畫面

Ubuntu Server 最小安裝有許多常用基本指令(ping, ifconfig…)及套件(nano…)都沒有,操作環境境略不方便,是否要用最小安裝自行斟酌,亦或先選最小安裝,有需求待安裝完後再另外加裝。

安裝完成後,會需要先修改網路設定檔,可先安裝 nano
$ apt install nano

如果螢幕有轉 90° 使用習慣的需求,可以參考這裡
如果真想要挑戰最小安裝連 nano 都不裝,這裡有 sed 指令參考,祝好運。

網路設定(netplan)

這裡先設定好網路環境,後續建 VM 就可以直接套用在參數上,避免再修改設定檔除錯的麻煩。

修改網路設定
$ nano /etc/netplan/00-installer-config.yaml

以下是設定完成後的範本:

network:
  ethernets:
    enp1s0:
      dhcp4: no # 停用 DHCP,否則開機會多等二分鐘
    enp2s0:
      dhcp4: no
  bridges:
    br1:
      interfaces: [enp1s0]
    br2:
      interfaces: [enp2s0]
      addresses: [192.168.1.253/24]
      routes: # 這部份是 gateway 的替代內容
        - to: default
          via: 192.168.1.1
      nameservers: # 指定 DNS
        addresses: [168.95.1.1, 8.8.8.8]

  version: 2

重點是 bridge 的部分,把 bridges: 到 version: 2 之間的內容貼到現有內容之下,再自行依需求修改,如果網路接口只有一埠,就刪掉 enp2s0 及 br2 縮排內的設定;如果超過二埠,就複製同一介面內容再新增 enp3s0 及 br3,依此類推。

至於 IP 為何會設在 bridge 而不是 ethernet?是因為橋接界面己指派連到網卡,雖然兩個介面都能指派 IP,但 gateway 只能設在其中一個,而 bridge 無法設定 gateway,只能用指定 default route 的方式來代替。簡單的說,兩邊都能設 IP,但如果 gateway 設在 ethernet,bridge 的裝置就會連不上外網。

另外,YAML 檔對格式非常敏感,大小寫、tab、縮排、版本格式…稍有不對就拒絕套用,建議用上面的內容直接複製貼上,再依自身環境需求修改。

修改好後執行 netplan apply 套用,剩下的部分就可以從 ssh 遠端完成設定。

如果是用 SSD,可以參考這裡優化。

替代指令

過程如果需要用到 ping、ifconfig 或編輯文件卻沒有 nano,以下是替代指令

ping 用 curl 替代
curl https://www.hinet.net

ifconfig 用 ip 替代
ip aip addr

下載檔案
wget <url>curl -O <url>

nano 可以用 sed 替代,祝好運!

安裝 KVM

$ apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst

以上這些都是必要核心套件,只能在命令列文字介面操作

如果 KVM 只打算在本機操作管理,且需要圖型操作環境,要再多加裝 virt-manager 及 virt-viewer

建立虛擬機

先建立 VM 磁碟
$ qemu-img create -f qcow2 kvm-disk01.qcow2 10g
-f: 指定格式,成長型格式,用多少佔多少。不加 -f 參數預設會用 raw 格式,檔案會直接佔用指定空間,好處是空間不足時不會被搶走。
qcow2:KVM/QEMU 主要使用格式。
10g:要建立給 VM 的磁碟空間。

查看磁碟檔格式
qemu-img -info filename.qcow2

範例一:光碟開機安裝建立 VM

適用於光碟開機安裝。

$ virt-install --name=testvm --os-variant=debian11 --vcpus=2 --memory 2048 --disk test-vm-console-disk.qcow2,size=5 --cdrom=/var/lib/libvirt/ubuntu-22.04.1-live-server-amd64.iso --graphics=vnc,listen=0.0.0.0,password=abcd1234 --network bridge=br1 --autostart --noautoconsole

建立名叫 testvm 的 VM,準備安裝 debian11 作業系統,雙核 cpu2G 記憶體5G 磁碟空間,用VNC 輸出畫面,VNC 登入密碼為 abcd1234光碟開機掛載 ISO,VM guest 跟 KVM 以橋接模式連在同一層網路,執行後立即啟動 VM

查看支援的的作業系統
virt-install --os-variant list

其中比較特別的是 –os-variant 參數,它會依據要安裝的作業系統版本提供適當的優化配置提供較好的性能表現,不加此參數也能建立虛擬機,但效能會差一些。

雖然建 VM 時可以在 –disk 參數加 spare 直接建成長型磁碟,但不知為何,無論 spare 參數怎麼餵,建出來的磁碟都會直接佔用設定的空間,到 stackover flow 爬文的結果似乎都指向 bug,只有 qemu-img 指令才能順利建成長型磁碟。

 

範例二:直接使用現成映象檔建立 VM

適用於已可運行,不需安裝的 VM 映象檔。

如果 VM 映象檔是從別的 VM host 平台建立的映象檔,不是 KVM 原生支援的格式,要先經過轉換才能使用。

以 VirtualBox OVA 映象檔為例:

tar -xvf virtualbox.ova #OVA 檔實際就是 tar 檔
bitnami-wordpress-6.1.1-41-r41-linux-vm-debian-11-x86_64-nami.ovf
bitnami-wordpress-6.1.1-41-r41-linux-vm-debian-11-x86_64-nami.mf
bitnami-wordpress-6.1.1-41-r41-linux-vm-debian-11-x86_64-nami-disk1.vmdk
ls -alh
total 2.9G
drwxr-xr-x  7 root         root 4.0K Feb 21 20:59 .
drwxr-xr-x 33 root         root 4.0K Feb 19 20:28 ..
-rw-r--r--  1           64   64 733M Feb 18 01:08 virtualbox-disk1.vmdk
-rw-r--r--  1           64   64  235 Feb 18 01:07 virtualbox.mf
-rw-r--r--  1 root         root 733M Feb 18 06:51 virtualbox.ova
-rw-r--r--  1           64   64 4.2K Feb 18 01:07 virtualbox.ovf
# 解包後的 vmdk 檔才是實際的映象檔
qemu-img convert -O qcow2 source.vmdk target.qcow2 # vmdk 轉換成 qcow2 格式

 

轉換後直接套用

$ virt-install --name=vmfromvirtualbox --os-variant=debian11 --vcpus=2 --memory 2048 --disk virtualbox.qcow2 --graphics=vnc,listen=0.0.0.0,password=abcd1234 --network bridge=br1 --import --autostart --noautoconsole

 

無論是 VirtualBox 的 OVA 或 VMware 的 VMDK 映象檔,放在網站公開提供下載通常都是壓縮過的格式,轉檔解壓後檔案會大 2-3 倍,並非 qcow2 格式佔較大空間。如果想保持壓縮格式,可以在 qcow2 後面加 -c 參數。

直接使用壓縮過的映象檔未必不好,如果 CPU 處理能力大過 IO 頻寬的話,同時間讀取的資料量會比未壓縮的還多,讀取效能反而提升,缺點是不支援快照。而後續再寫入增加的資料則就未經壓縮的累加上去。

其它支援支援轉換的格式

範例三:雙磁碟開機 + GUI 輸出

適用於直接掛載原本需要製作成 USB 開機,圖型操作環境的 Live OS/Installer 映象檔。

virt-install --name=LiveOS --os-variant=generic --vcpu=2 --memory 8192 --disk liveOSimage.qcow2 --disk vmLocalDisk.qcow2,size=16 --video virtio --graphics=vnc,listen=0.0.0.0,password=abcd1234 --network bridge=br1 --import --autostart --noautoconsole

幾個地方要注意:

  • 除非是光碟映象檔,不然只要來源映象檔是可開機的磁碟格式(包含 USB boot Live OS image),記得先轉換成 qcow2 格式(參考範例二)。
  • 如果要安裝的作業系統核心或版本不在清單上或無法確認,–os-variant 參數可填 generic。
  • 如果 Live OS 是安裝程式,安裝完後記得先執行 virsh edit 把第一組 <disk> 到 </disk> 的設定刪掉,不然重開機又會重新進入 Live OS。(亦或把第一組 <disk> 內的 source file 直接改為第二組<disk> 的 source file 路徑,再刪除第二組 <disk> 的內容)(建議)。
  • 如果開機、安裝後的操作環境是文字介面,可以把 –video virtio 參數拿掉。

無論是直接套用現成映象檔還是從光碟開機安裝建立新的 VM ,執行後就可以立即用 VNC 從遠端登入 KVM 的 IP 操作,到這裡基本上 KVM 就建置完成,後面是建議補充設定。

設定 console 輸出

如果 VM 是 Linux 系統,即便是圖型操作環境,仍是強烈建議開啟 console 輸出,避免網路設定錯誤造成 VM 失去所有登入操作的入口而殘掉,最後只能砍掉,萬一 VM 己運行一段時間又存有重要資料將會很麻煩。

VM 端啟用 console 輸出

$ sudo systemctl enable serial-getty@ttyS0.service
$ sudo systemctl start serial-getty@ttyS0.service

從 KVM 進入 VM console


virsh list
Id    Name                           State
----------------------------------------------------
 1     ubuntu-vm1                     running
 2     ubuntu-vm2                     running
 3     ubuntu-vm3                     running
virsh console ubuntu-vm1 #輸入 name 或 ID 編號都可以
Connected to domain 'ubuntu-vm2'
Escape character is ^] (Ctrl + ])
# 剛進來不會有反應,按任意鍵讓 VM 回應
debian login: vmuser
Password:
Linux debian 5.10.0-21-amd64 #1 SMP Debian 5.10.162-1 (2023-01-21) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Mon Feb 20 20:22:09 UTC 2023 on ttyS0
vmuser@debian:~$

Ctrl + ] 可退出console

從 console 進 VM 操作,除了可以做為設定錯誤的最後一道防線,另一方面也能增加安全性。從 console 進 VM 如同直接在主機面前接上 com port 進入主機,設定好後甚至連 ssh 都可以停掉,適合公開在網路上的網頁伺服器,只開 443 port。

VM console 是模擬 serial/com port 輸出訊號,它不是 IP base,只有拔掉 com port,而 Ctrl + ] 就是拔掉 com port 的意思。

同樣的,也因為它不是 IP base,離開前還是要 exit 退到登入畫面,如果直接 Ctrl + ] 離開,session 仍會停留在最後的操作狀態,重新進入 console 如同電腦操作到一半沒有登出就離開,跟別人坐下來就可以繼續操作電腦一樣。

console port 是單向輸出,只有操作端發送訊息被控端才會回應,被控端無論發送什麼訊息都沒有意義,這樣即便 VM 被攻破,最後也只會卡在 console。

要特別注意 console 同一時間只能有一個 session,無論是從 remote terminal 或從 local 進入 VM console,其中一個 session 要先 Ctrl + ] 退出,否則會出現 operation failed 錯誤訊息。

停用 VM VNC

如果己設定好 ssh 遠端登入且 console 也成功啟用,除非是圖形操作介面,否則 VNC 就沒有保留開啟的必要,少一個連線方式多少提升一些安全性,畢竟 VNC 密碼是以明碼的方式存在 VM xml 設定檔裡,。

$ virsh edit alp

把 <graphic> 到 </graphic> 這幾行全部刪掉,包含 <graphic> 及 </graphic>,刪掉後按 Ctrl + X 離開就會自動儲存。如果想用 <!– –> 的方式註觲掉也可以,退出後 virsh 還是會把無效的內容自動刪除,所以無論是刪除還是註解,儲存後的結果一樣都是刪掉。

用 VNC 登入雖然操作方便,但限制很多,不但無法複製貼上、終端文字畫面無法回捲、占用螢幕空間…除非 VM 是圖形操作環境或一定要看到最最開頭的 bootloder

如果 VM 是純文字操作環境,建議從 console 做初使設定直到啟用 SSH (或原本就沒打算啟用 SSH),除了安全性較高以外,設定錯誤導至失去網路環境(如 IP、防火牆設錯),console 仍可做為進入 VM guest 的最後一道防線。

讓 virsh shutdown 有作用的方法

現今電腦的電源鍵都不再是真的「電源」鍵,依作業系統或設定的不同,在 Windows 或 macOS,它可能是登出、待機或休眠,在 Linux 是執行 shutdown 程序,依靠的都是 ACPI 電源管理訊號。

執行 virsh shutdown 就等同於按電源鍵送出 ACPI 訊號,在某些情況下,執行 virsh shutdown 可能會沒反應,這時就要執行 virsh destroy 強迫關機,等同按住電源鍵強迫關機。

不同的 Linux 套件發行版本設定可能不一樣,如果碰到安裝的 VM 對virsh shutdown送出的 ACPI 訊號不會執行 shutdown 的狀況,照以下方式修改 VM 的設定檔

$ virsh edit <vmname>

找出 <channel type='unix'> 那一行,把裡面改成以下內容:

    <channel type='unix'>
      <target type='virtio' name='org.qemu.guest_agent.0'/>
      <address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>

KVM virsh 常用指令

VM 開機|關機|暫停|重開機
virsh start|shutdown|suspend|reboot vmname

強迫關機
virsh destroy vmname
destroy 聽起來很恐怖,實際上只是強迫關機

刪除 VM
virsh undefine vmname
僅刪掉 VM 設定檔,磁碟映象檔要自己手動刪除

顯示運作中的 VM
virsh list

顯示所有已建立的 VM
virsh list --all

編輯 VM 設定檔
virsh edit vmname

建立 Snapshot
virsh snapshot-create vmname

列出已儲存 Sanpshot
virsh snapshot-list vmname

回復 Snapshot
virsh snapshot-revert --snapshotname