Unikernel:從不入門到入門

Unikernel:從不入門到入門

 

Unikernels: Beyond Containers to the Next Generation of Cloud 是 Russ Pavlicek 的一本動物書(雖然是 O’Reilly 的,但是封面不是動物,是石榴),這本書對 Unikernel 有着比較全面的介紹,而且電子書是免費的,值得一讀。

啥是 Unikernel?

從 2014 年以來,容器以一種不可逆轉的態勢席捲了全球,Unikernel 是很多人眼中的下一個容器。如果要了解什麼是 Unikernel,首先需要了解什麼是 kernel,kernel 是操作系統中的一個概念。應用要運行起來,是肯定要跟硬件打交道的,但是如果讓應用都直接操作硬件,那一定是一場災難。那內核就是在應用與硬件中間的一層抽象,內核提供了對底層硬件的抽象,比如把硬盤抽象成了文件,通過文件系統進行管理。傳統的內核會將所有的硬件抽象都實現在其中,其中的代表就是 Linux,這樣的內核被稱爲宏內核(Monolithic Kernel)。在宏內核中,所有的模塊,諸如進程管理,內存管理,文件系統等等都是實現在內核中的。這樣雖然不存在通信問題,但是任何一個模塊的 bug 會使得整個內核崩潰。

於是學者們提出了微內核(Micro Kernel)的概念,在內核中只保留必要的模塊,比如IPC,內存管理,CPU調度等等。而其他,諸如文件系統,網絡IO等等,都放在用戶態來實現。這樣會使得內核不那麼容易崩潰,而且內核需要的內存小了。但是由於模塊間的通信需要以 IPC 的方式進行,因此有一定的 overhead,效率不如很莽的宏內核。

那後來又有了混合內核(Hybrid Kernel),把一部分不常使用的內核模塊,或者是原本需要的時間就很長,因此 IPC 的 overhead 看起來就不是那麼誇張的功能,移出內核,而其他的就會放在內核裏。

再後來還有 Exokernel,但是太長了就不講了,這部分內容在 CSP 課堂筆記之 UniKernel 一文中有更詳細的解釋。

直接說 Unikernel,Unikernel 的官方解釋

Unikernels are specialised, single-address-space machine images constructed by using library operating systems.

翻譯一下就是

Unikernel 是專用的,單地址空間的,使用 library OS 構建出來的鏡像

其最大的賣點就是在,沒有用戶空間與內核空間之分,只有一個連續的地址空間。這樣使得 Unikernel 中只能運行一個應用,而且對於運行的應用而言,沒有硬件抽象可言,所有的邏輯,包括應用邏輯和操作硬件的邏輯,都在一個地址空間中。

這樣有啥好?

哦,原來 Unikernel 就是一個單一內存空間的內核鏡像,其中只能有一個應用在運行,那這樣有啥好呢,爲啥值得我放棄 Linux 而用你這麼一個看上去像是閹割版的內核呢?好處就在,小,快,安♂全 /w\

Unikernel 鏡像都很小,由 MirageOS 實現的一個 DNS server 才 184KB,實現的一個 web server 674 KB,小到恐怖的程度。

然後就是快,啓動很快。因爲鏡像都很小,所以起停都在毫秒級別,比傳統的 kernel 要快多了。

最後是安全,一般來講,小的東西相對而言比較安全。Unikernel 中沒有 Shell 可用,沒有密碼文件,沒有多餘的設備驅動,這使得 Unikernel 更加安全。

開發測試與傳統有啥不同?

Unikernel 在真正實踐中,如何開發與測試是一個值得關注的問題。在開發過程中,開發者可以假定自己在傳統的操作系統上進行開發,而所有內核相關的功能,暫且由開發機的操作系統提供。

而在測試環境中,大部分 Unikernel 的實現會將應用代碼與需要的內核模塊構建成 Unikernel 後,再將其跑在一個傳統的操作系統上,利用傳統操作系統上的工具來測試 Unikernel。以 Rumprun 爲例,它可以通過 KVM/QEMU 來運行一個 Rumprun Unikernel VM,隨後用 Host OS 上的 GDB 來對其進行調試,具體細節可見此處。關於調試就介紹到此,如果你想了解更多,Hacker News 上的這個 post 可能會給你一些啓發。

在發佈階段,這是 Unikernel 最簡單的事情了。Unikernel 最後的產物就是一個 kernel image,可以在 Hypervisor,Bare Metal 等等各種環境上運行。

所以可以看到,其中 Unikernel 在軟件過程中與傳統方式最大的不同就在於調試與測試。而在發佈的階段,傳統的方式可能發佈的是一個應用,時髦一點那一個容器鏡像,而 Unikernel 則是一個高度定製化的 kernel。

目前的 Unikernel 項目

介紹完 Unikernel,接下來將介紹下目前比較成氣候的 Unikernel 項目,Unikernel 的實現大部分都是語言特定的。因爲涉及到具體語言的運行時,所以很難有一個項目可以適配所有的技術棧。

MirageOS 應該是名氣最大的一個 Unikernel 項目,它是使用 OCaml 進行開發的,也是要求開發者懂 OCaml 才行。與其他 Unikernel 相比,它非常成熟,而且有一些論文,對鍾愛論文的同學非常友好。

HaLVM 也是一個比較早的 Unikernel 項目,它可以幫助 Haskell 程序員們把自己的 Haskell 程序構建成 Unikernel。如果你不會 Haskell,那就算了 =。=

ClickOS 是一個比較獨特的項目,他也非常古老了,但是原本 Click 並不是以 ClickOS 的形式出現的,原本它只是一個支持定製的 router,後來就變成了 ClickOS,一個基於 Unikernel 的 router。它也有很多論文,大部分都是關於 Click 本身,而不是 Unikernel 實現的。

Rumprun 也是一個非常獨特的項目,其利用了 Rump Kernel,理論上 POSIX 兼容的程序,都可以用 Rumprun 來構建成 Unikernel。

如果這些還不能滿足你的好奇心,Open source work on unikernels 上列出了衆多的 Unikernel 項目,如有需要還請自行瀏覽。

Unikernel, Docker,Hyper 與 Linuxkit

對 Unikernel 的介紹就是這些了,最後再談談自己對目前很火的一些概念的看法,以及它們之間的聯繫。

Unikernel,在我看來,是另一種形式上的容器。在一個 Unikernel 中,只能運行一個應用,這與容器的哲學不謀而合。但現在容器最吸引人的特性並不是它的便捷,而是在它的分發。Docker 讓我們看到了,原來應用的分發可以這麼無痛。而 Unikernel 與容器相比,雖然可以做的更小更安全,而且也不需要有 Docker Daemon 這樣的後臺程序存在,甚至不需要 Host OS,或者 Hypervisor,但是它一是與傳統的軟件過程有較大的出入,二是在分發等等方面不能做到像容器那樣方便。所以它目前肯定不會成爲主流的應用分發方式,還需要進一步探索。

爲了能夠讓 Unikernel 儘快進入生產環境,有一項工作很值得關注。

Docker on UniKernel

 

Docker on Unikernel

在 Unikernel 裏運行一個 Docker Container,想法很美好,但是同樣也有很多問題。這樣其實並沒有利用到容器便於分發的優勢,也沒有完全發揮 Unikernel 的優勢,我覺得這不是未來。不過作爲一種折中方案值得一看,可惜從 DockerCon 15 之後就沒聽見什麼動靜了。

Hyper Container 的技術特別獨特,之前在 Docker 與 Hyper 一文中介紹過,這裏不再多說。他們的實現很完整,有對標 runc 的 runv,有擴展 Kubernetes 中 container runtime 的 frakti,雖然我沒有嘗試過,但是我覺得是比 Docker in Unikernel 更加可行的方案,講道理很有前途。

Linuxkit 是 Docker 改名 Moby 後隨之發佈的一個項目。Linuxkit 嚴格來說是一個構建操作系統的工具集,可以用來構建 Unikernel,但是也可以用來構建最小化的 Linux Kernel,目前還不知道要往什麼方向發展。

這些概念或多或少都有相互重疊的部分,也沒有誰一定勝過誰的說法,但都有一個特點:有趣。它們都有自己不同的應用場景,本來嘛,Docker 也不是銀彈。