Use virtual machines as daily drivers. Virtualize a home PC and replace it with a thin client that connects to the VMs via remote desktop.
我終於成為「Yes I am Linux user」!How do you know that I am a Linux user?
實際使用場景就像下圖,差別在於我不是用Arch Linux,而是Ubuntu。
嘗試將現有的Linux電腦,轉換為一個兼具「工作 + 遊戲 + AIGC計算 + macOS XCode編譯 + 玩Android遊戲 + BT下載 + NAS」的多功能虛擬機主機,底層的系統得是跑在Linux上的。
並且,將虛擬機系統作為一種類似VDI(桌面虛擬化設施),隨時隨地的使用Thin Client遠端存取桌面。
1. 動機#
以前是一邊操作Linux宿主機,一邊使用虛擬機跑Windows。
因為我想跑的東西實在太雜,所以乾脆結合 過去幾年學到的虛擬機技術,將一切虛擬化,讓我能夠任意分配硬體資源給系統使用。
我知道的東西不是很多,所以這篇文章的內容可能會隨時修正。
這個想法在前幾個月的兩篇文章已然成形:
這次我重新把它polish了一遍,以求未來能以此繼續延展。我還是沒有用Proxmox,而是用Ubuntu搭配Libvirt KVM自行拼出一個虛擬機導向的作業系統。
下面會講選擇Ubuntu當底層作業系統的理由,這裡我要再講些動機方面的東西。第一個,那就是幾年前讀了「編程隨想的博客」補充了我許多虛擬機隔離的想法。第二個,透過Edward Snowden的書了解到Tails OS和Qubes OS的存在,讓我更想嘗試將一切都虛擬化,加強安全性的作法。
這兩個動機聽起來很詭異是吧,既沒有中共國安要抓我,也沒有CIA監控人民的風險,但是,台灣有可能在不遠的未來被那些"glowies glow in the dark"持續蠶食鯨吞人民的權利,所以防患於未然是重要的。
2. 伺服器硬體架構規劃#
開啟Joplin,用Apple Pencil畫了一上午得出來的構想。
設想
針對這幅靈魂繪圖的解釋。
首先是宿主機硬體規格。
- CPU:Intel i5-7400,含UHD 630 iGPU內顯
- RAM:16GB DDR4
- GPU:4GB VRAM的Nvidia GTX1050Ti
- 硬碟:總計6TB的空間,但不會全部使用。
將現有的兩個SSD硬碟組成一個LVM Group,取得最大的root空間,不用再額外掛載硬碟到其他路徑導致資料要搬來搬去的。也方便日後擴充硬碟。
宿主機的作業系統安裝標準的Ubuntu Desktop,並啟用LVM。為什麼不選Proxmox或者純伺服器的Linux發行版?因為我還想當普通人,要保有人性(humanity,即Ubuntu這個字的本義),我想當吸血鬼(戴上石鬼面,成為hacker admin)的時候就會拋棄它了。
…其實比較現實的理由是,Libvirt沒有好用的網頁界面,Cockpit還不成熟,所以在起初建置虛擬機胡敬的時候還是有圖形界面跑Virt Manager較好。等一切就緒後圖形界面就能關掉了。
宿主機應當儘量保持精簡,只要做好Hypervisor的調度工作就行了,除了SSH和Libvrit虛擬機等必要軟體以外一律不安裝,UFW防火牆全部封鎖。因為我不會用LXC(吐舌),就連Docker和Podman都是在虛擬機裡面跑的。
然後,手邊有幾個HDD,他們有各自的用途,所以不會成為LVM Group的一部分。
3. 虛擬機規劃#
計畫安裝三個虛擬機:
- 第一個是使用我慣用的KDE桌面的Linux虛擬機,做主力,直通Intel GPU,負擔基本3D加速。
- 專門跑self-hosted服務的headless Linux虛擬機,主要跑Docker和Podman,直通Nvidia GPU跑AI運算。
- Windows虛擬機,直通Nvidia GPU玩遊戲。
以上是最常用的三個,剩下的就按照需求臨時加開虛擬機。如果有必要,虛擬機應該啟用Secure Boot和FDE全硬碟加密。
既然虛擬機都是跑在區域網路,我有想過,或許虛擬機可以用PXE從網路硬碟開機的?但為了效能考量還是採用比較常見的作法,即一個系統一個qcow2硬碟。
因為Libvirt有超賣(overcommiting)機制,所以CPU和RAM可以有效利用。多個虛擬機同時執行的是可能的,閒置的虛擬機資源會被其他虛擬機拿去用。不過就實務來看上,同時跑Linux和Windows虛擬機就差不多吃乾i5-7400的所有資源了(該死的Windows Update)。倒是跑兩個Linux虛擬機比較滋潤,所以我不會讓Windows虛擬機一直在線上,會一直在線上的是Linux的虛擬機。
就算虛擬機全部下線,宿主機也不會關機。我已經做好長期不關機的準備,要買UPS了。
4. 遠端存取虛擬機的手段#
當你啟用VFIO隔離了電腦上所有的GPU,等同封鎖了它輸出螢幕的能力,故開機後會完全沒畫面,得用SSH登入。
將宿主機連上Tailscale網路,組成私人VPN通訊網,這樣就能用手機或者其他電腦遠端登入操作。另外雖然Cockpit界面很爛,我還是啟用了,聊勝於無。
要連線到虛擬機,一般的遠端桌面是滿足不了我的,所以不使用虛擬顯示卡,不用SPICE或VNC,而是將GPU直通給虛擬機,再於區域網路做高品質桌面串流。目前試下來最順的就是Moonlight + Sunshine的搭配了。Looking Glass不能在非本機以外的網路傳輸,所以淘汰。
除了Moonlight外我還準備了備用的遠端桌面連線手段,因為它們都是Libvirt建立的虛擬機,因此GPU串流出問題的話還可以在Virt Manager插SPICE,再用VNC或RDP遠端進入桌面除錯。最不濟還有SSH能登入。
而如果是那種不能裝遠端桌面,又需要圖形效能的特殊虛擬機系統(例如BlissOS)我還有一招,那就是使用USB擷取卡獲得螢幕畫面,於其他虛擬機裡面檢視那個虛擬機的畫面。
5. 硬體直通做法#
Libvirt可以將宿主機的任意USB裝置或PCI裝置直通給虛擬機使用。
首先是GPU,透過VFIO,將Nvidia GPU完全隔離,它就是一個讓各個虛擬機允取允求的資源,一次只能由一個虛擬機使用。不搞一對多的vGPU,因為太麻煩,且4GB VRAM也沒什麼好拆分的。
至於Intel iGPU,也是透過VFIO直通,而非選擇壓搾Intel iGPU到極限,用GVT-g功能分給兩個虛擬機使用。因為經過測過,iGPU直通原本是能負擔1080p60串流的,但啟用GVT-g後VRAM砍半就撐不了,位元率必須降得很低才行,而且虛擬機的解析度還會被限制住,這樣我不喜歡。
替代方案:用不怎麼吃GPU效能的RustDesk來存取桌面,即使iGPU VRam砍半也能負荷。但是,RustDesk延遲太高了。
以上兩個要直通的GPU都有插著一塊顯示器或者HDMi欺騙器,以確保能發揮顯示卡最大效能。
接著是其他硬體裝置。虛擬機的網路上網都是透過Libvirt的NAT虛擬網路,不過我特別做了橋接網路讓虛擬機能從外網存取。僅是為了區網傳輸方便,防火牆還是有開,且為了通訊安全大部分時候都是用SSH或VPN之類的加密通訊。
若是為了降低虛擬機輸入與輸出延遲,購買USB Hub,將滑鼠與鍵盤與喇叭插在Hub上,再將該Hub直通給單一虛擬機使用,就可達致最低延遲。
6. 將單個硬碟共享給多個虛擬機#
有個HDD資料碟得在多個虛擬機間共享,例如跑Podman服務的虛擬機需要存取照片,我又想在主力桌面環境虛擬機直接開照片。
所以我不直通硬碟給單一虛擬機,而是透過網路檔案系統傳輸。
為了安全性和維護容易,選擇SSHFS,備用方案NFS + Kerberos。所有的虛擬機皆得透過遠端連線到宿主機,間接讀取資料碟上的檔案。
然後還有虛擬機玩遊戲問題。利用Steam硬碟資料庫共享原理,將一個專門裝遊戲的實體硬碟給Linux和Windows虛擬機使用。
為了速度考量,不採用SSHFS,而是直通。在Linux和Windows虛擬機間共享遊戲,這樣能測試Proton的執行效果,也能夠順利的於Linux虛擬機玩遊戲。此外利用VFIO原理,Nvidia GPU可以在虛擬機關機之下任意分配給虛擬機,Sunshine會在開機後自動啟動,不問Nvidia還是iGPU都能開始串流。
7. 準備Thin Client遠端存取#
Thin Client是使用硬體較弱的裝置存取虛擬機桌面的電腦。
這就叫"Thin client",識得唔識得呀?
對VDI而言,這又稱之為VDI Client
沒有多餘的電腦,所以就地利用,將樹莓派拿出來,從伺服器轉做桌面用途。
雖然Android、iPad接上螢幕也可以當電腦用,但是這是次佳的選擇。樹莓派配上GNOME桌面才有真正多工,方便管理多視窗的虛擬機。
Thin Client的東西要盡量精簡,只裝遠端桌面軟體,負責透過區域網路連線到Ubuntu和管理虛擬機,除此之外Thin Client不可以登入任何帳號,所有正式的工作都應該在虛擬機內部完成。
8. 架設過程#
- 把重要資料備份到最大的HDD
- 抹除系統,重裝Ubuntu Desktop,啟用LVM
- 設定SSH與 Taiscale服務
- 安裝 Libvirt KVM,安裝Linux和Windows虛擬機
- 設定 橋接器網路
- 安裝 Cockpit網頁服務
- 確認虛擬機就緒後,切換到Thin Client,遠端登入操作
- 直通Nvidia GPU, 直通Intel GPU,測試VFIO功能是否正常。
- 設定遠端桌面功能,包括SSH、 RustDesk、 Moonlight + Sunshine等等。
- 正式拔除圖形環境,使用指令
sudo systemctl set-default multi-user.target
設定Ubuntu開機進入純文字模式。
9. 實際使用體驗&未解決的問題#
利用Moonlight遠端到Linux虛擬機日常上網、玩遊戲,因為是區域網路沒什麼問題,只是偶爾會延遲。因為每個虛擬機的資源分配不均,加上4核心的CPU根本吃不消,容易一個虛擬機開始做大量操作就影響到主力虛擬機的正常使用。例如,Linux主力機的喇叭爆音就知道整個系統的CPU過載了;在區域網路搬移許多檔案的時候會導致遠端桌面連線跟著塞車。使用下來體驗不佳,甚至比我以前一邊操作宿主機,一邊使用虛擬機的體驗還差勁。
正如我上面說的,硬體效能限制了我的想像。目前的硬體實在不能同時跑兩個以上的虛擬機,會引發宿主機的OOM Killer,亦不適合一邊正常使用一邊當伺服器。因此未來全面升級硬體是必須的,最好升級到10核心以上CPU、16GB VRAM的GPU,還有32GB以上的RAM。主機板最好可以插兩個GPU,一個AMD一個Nvidia(或者至少CPU要有強力內顯),供給多個虛擬機使用。
此外我沒有把備份納入考量,所以硬體方面未來要再搞個RAID。
因此在短暫試驗幾天之後,我又回到了以前的模式:宿主機恢復圖形界面,改GPU直通搭配Moonlight存取虛擬機。服務直接在宿主機用Docker跑就好。