Unikernels: Beyond Containers to the Next Generation of Cloud 是 Russ Pavlicek 的一本動物書(雖然是 O’Reilly 的,但是封面不是動物,是石榴),這本書對 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 的實現大部分都是語言特定的。因爲涉及到具體語言的運行時,所以很難有一個項目可以適配所有的技術棧。
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 的介紹就是這些了,最後再談談自己對目前很火的一些概念的看法,以及它們之間的聯繫。
Unikernel,在我看來,是另一種形式上的容器。在一個 Unikernel 中,只能運行一個應用,這與容器的哲學不謀而合。但現在容器最吸引人的特性並不是它的便捷,而是在它的分發。Docker 讓我們看到了,原來應用的分發可以這麼無痛。而 Unikernel 與容器相比,雖然可以做的更小更安全,而且也不需要有 Docker Daemon 這樣的後臺程序存在,甚至不需要 Host OS,或者 Hypervisor,但是它一是與傳統的軟件過程有較大的出入,二是在分發等等方面不能做到像容器那樣方便。所以它目前肯定不會成爲主流的應用分發方式,還需要進一步探索。
爲了能夠讓 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 也不是銀彈。