Kubernetes: 微內核的分佈式操做系統

現在,Kubernetes 已經成爲分佈式集羣管理系統和公有云/私有云的事實標準。實際上,Kubernetes 是一個分佈式操做系統,它是 Google 在分佈式操做系統領域十餘年工程經驗和智慧的結晶,而 Google 一直以來都管理着世界上最大的分佈式集羣,在分佈式操做系統領域的研究和認識領先於全世界。所以,2014年發佈的 Kubernetes 能在短短几年時間內就超越了諸多前輩,大獲成功。git

做爲分佈式操做系統,Kubernetes(包括其前代產品 Google Borg)的出現遠遠晚於 UNIX、Linux、Windows 等著名的單機操做系統,Kubernetes 架構設計天然地繼承了不少單機操做系統的珍貴遺產,微內核架構就是這些遺產中最重要的一份。在本文接下來的部分,咱們將專一於微內核(microkernel)這個概念及其對 Kubernetes 架構的影響。github

什麼是微內核?

在介紹微內核的時候,咱們有必要同時回顧一下單機操做系統的歷史,以理解其價值所在。本章中以「操做系統」指代「單機操做系統」。算法

UNIX 的興起

電子計算機誕生以後,在上個世紀70年代之前,出現過許許多多的操做系統,DOS、OS/360、Multics 是其中的知名錶明,這是操做系統領域的拓荒時代。20年來的拓荒孕育出了偉大的成果:隨着 CPU 技術的發展,UNIX 於1969年誕生了,這是一個真正意義上的分時操做系統。sql

UNIX

圖片來源:維基百科shell

藉助新的 CPU 技術的支持,UNIX 將軟件系統劃分爲內核(kernel)用戶態程序(userland programs)兩部分。內核是一組中斷處理程序的集合,把硬件的能力封裝爲操做系統功能調用(system calls),用戶態程序經過系統調用使用硬件功能,用戶態程序運行於各自的進程中,全部用戶態進程都共享同一個內核,每當系統調用或中斷髮生,UNIX 便陷入(trap)內核,內核執行系統調用,與此同時,內核中的分時調度算法將決定把 CPU 交給哪一個進程,並管理進程的上下文切換。另外,UNIX 把(幾乎)全部硬件都封裝爲文件。UNIX 還提供了一個特殊的用戶態程序 shell,供用戶直接使用系統,經過內核提供的進程間通訊能力,shell讓 用戶能夠把一系列應用程序組合起來,處理複雜的需求,做者稱這個設計思想爲「KISS」(Keep It Simple and Stupld)。UNIX 的全部設計思想在當時是都是很是了不得的創舉。編程

UNIX 不但自身對業界產生了巨大的直接貢獻,還成爲全部現代操做系統的藍本,兩位做者 Ken Tompson 和 Dennis Ritchie 所以榮獲1983年度的圖靈獎。安全

UNIX 誕生於貝爾實驗室,該實驗室屬於美國國家電信電報公司(AT&T),見識到 UNIX 的強大威力以後,AT&T 作出了一個看似無私的決定:將 UNIX 開源(初期只對大學開源),這使得全部現代操做系統得以誕生。雖然 AT&T 最終被分拆,輝煌再也不,但這個決定對人們的貢獻綿延至今。在21世紀20年代的今天,不管是 MacOS、Windows、Linux,都直接受到 UNIX 的影響,而 iOS 來自 MacOS,Android 來自 Linux,所以 UNIX 的靈魂仍然活在每一個人的手機中、活在每一個手機 App 後臺的服務中。網絡

此外,UNIX 誕生之時,還附送了一項比操做系統自己價值更大的副產品:Dennis Ritchie 爲開發 UNIX 設計了C語言,C語言成爲了全部流行的現代編程語言的主要設計來源,不只如此,C語言在其誕生近40年後的今天,仍然是最重要的編程語言之一。架構

值得一提的是,當時 UNIX 的主要開放對象是伯克利、卡內基梅隆等研究型大學,文理學院規模較小,沒有研究生項目,不屬於 AT&T 的主要開放目標,所以 Olivet College 畢業的一位小哥未受到 UNIX 思潮的影響。這位名叫 David Cutler 的軟件天才於1975年在 DEC 設計了 VMS 操做系統,VMS 和最初的 UNIX 同樣,運行在 PDP-11 上,但並非基於 UNIX,而是獨立設計的。VMS 在業界沒有掀起大浪,以兼容 UNIX 了結。後來 David Cutler 離開 DEC,加入微軟,在那裏譜寫了屬於他本身的傳奇。有趣的是,喬布斯也曾在文理學院就讀,看來美國文理學院的學生是不走尋常路的。框架

微內核的興起

UNIX「一切皆文件」的設計帶來了用戶程序設計的不少便利,但它要求全部對硬件的封裝都要在內核態,所以內核中模塊的 bug 會讓整個系統受到影響,好比說,若是某個設備驅動有內存泄漏,全部使用該設備的用戶態進程都會有內存泄漏,若是某個內核模塊有安全漏洞,整個系統的安全性將再也不可控。

爲了解決這類問題,上個世紀70年代,操做系統研究者們開始發展「微內核」的概念,微內核的本質是讓操做系統的內核態只保留內存地址管理、線程管理和進程間通信(IPC)這些基本功能,而把其它功能如文件系統、設備驅動、網絡協議棧、GUI 系統等都做爲單獨的服務,這類服務通常是單獨的用戶態 daemon 進程。

用戶態應用程序經過 IPC 訪問這些服務,從而訪問操做系統的所有功能,如此一來,須要陷入內核的系統調用數量將大大減小,系統的模塊化更加清晰。同時系統更加健壯,只有內核中的少許系統調用纔有權限訪問硬件的所有能力,如設備驅動的問題只會影響對應服務,而不是影響整個系統。和 micro kernel 相對,UNIX 的設計被稱爲 monolithic kernel。

UNIX 開放後,AT&T 繼續着版本迭代,而各大學基於 AT&T 的 UNIX 開發了不少新的操做系統內核,其中較爲知名的有:

  1. BSD,monolithic,由伯克利的傳奇人物 Bill Joy 於1974年發佈(聽說 Bill Joy 花三天便完成了 BSD 內核的第一個版本開發,Bill Joy 的做品還包含第一個 TCP/IP 協議棧、vi、Solaris、SPARK 芯片等等)。該內核對業界影響很是之大,後來發展爲 FreeBSD、OpenBSD、NetBSD 等分支。現代操做系統如 Solaris、MacOS X、Windows NT 對其多有借鑑。
  2. Mach,微內核,由卡內基梅隆大學於1984年發佈,主要做者是 CMU 的兩位研究生 Avie Tevanian 和 Rick Rashid。該內核對業界影響也很大,GNU Hurd、MacOS X 對其多有借鑑,但該項目自己以失敗了結。
  3. MINIX,微內核,由阿姆斯特丹自由大學(Vrije Universiteit Amsterdam)的 Andrew Tanenbaum 教授於1987年發佈。無數計算機系學生經過 MINIX 及其配套教材掌握了操做系統的設計原理,Linux 的初始版本就是基於 MINIX 復刻的。MINIX 雖然著名,但主要用於教學,從未在工業界得到一席之地。

微內核的沉寂

從上世紀90年代至本世紀10年代,UNIX 和 VMS 的後裔們展開了一場混戰,從結果來看,微內核的概念雖然美好,但現實很是殘酷:

  1. MINIX 僅限於教學,而基於 MINIX 設計的 Linux 是 monolithic 系統,反而大獲成功。Mach 對業界影響深遠,但自己並未獲得大規模應用,其繼承者 GNU Hurd 一直在開發中,從未能應用。
  2. Windows 的 NTOS 內核是 David Cutler 基於他原來在 DEC 獨立設計的系統 VMS 設計的(VMS 和 UNIX 無關)。NTOS 借鑑了微內核的思想和 BSD 的一些代碼,但最終 David Cutler 決定將全部服務(如 GUI)都放到內核態而非用戶態,所以 Windows NT 在軟件架構上和微內核一致,而實際運行和 monolithic 內核一致,被稱爲 hybrid kernel。
  3. MacOS X 基於 NextStep OS 設計,NextStep 是 Avie Tevanian 設計的,Avie Tevanian 是 Mach 的主要設計者,博士畢業後,蓋茨和喬布斯都邀請過他,他去了 Next,他在 CMU 的好友 Rick Rashid 則去微軟做爲 David Cutler 的首席助手,聽說 Avie Tevanian 在 Next 天天用計算器算本身沒去微軟而損失的股票增值。跟喬布斯回到蘋果後,Avie 基於 NextStep 和 BSD 的代碼設計了 OS X,巧的是,OS X 也採用了 hybrid kernel 的架構,最終大獲成功,還能在 PowerPC 和 x86 兩種指令架構間無縫切換。

在幾位操做系統技術巨擎中,除 Linus Torvalds 外,不管是 David Cutler 和 Andrew Tanenbaum,仍是 Avie Tevanian 和 Rick Rashid,都是微內核架構的領袖級人物,但最終他們都沒有將微內核完全落地,這是有緣由的。

微內核操做系統訪問系統服務的效率比 monolithic 操做系統要低得多,舉例而言,在 Linux 中,系統調用(好比 open)只要陷入內核一次,也就是先切換 CPU 到高權限模式,再切回低權限模式。若是在一個微內核操做系統中,用戶調用 open 就須要先拼裝一條 IPC 請求消息,發送給對應的文件系統服務進程,隨後從文件系統服務進程獲取IPC響應消息並解包,拿到調用結果,這樣一來,消息帶來的數據拷貝和進程上下文切換都會帶來不少開銷。消息須要拷貝是由於用戶態進程間不能相互訪問內存地址,而內核的代碼能夠訪問任何用戶態進程的任何內存地址。
正是由於性能緣由,OS X 和 Windows 都選擇了 hybrid kernel 的架構,NTOS 甚至在內核中集成了 GUI 子系統,以帶來更好的用戶體驗。

簡單來講,在電腦性能不佳的狀況下,咱們會發現 Windows 的鼠標箭頭更加「跟手」,即便系統接近死機,Windows 系統的鼠標箭頭仍然能夠活動。Windows XP 能在 Windows 98 這樣「珠玉在前」的上代產品後得到更大的成功,和 NTOS 對性能的密切關注是分不開的,相比之下,蘋果當然在1980年代中期就有初代 Machintosh 這樣的壯舉,但由於喬布斯沒法說服銷售團隊換一根更強的內存條,所以初代 Mac 的性能較差,運行程序很是之慢,未能得到應得的藍海成功。

Kubernetes 和微內核

性能問題對單機操做系統來講多是相當重要的,但對分佈式操做系統並不是如此,分佈式操做系統做爲「幕後功臣」,不須要直接面對用戶,而單機性能上的小小損失能夠用更多機器來彌補,在這個前提下,更好的架構每每更加劇要。

Borg 的誕生

在單機操做系統大戰快要分出勝負之時,Google 這家行業新寵正準備 IPO,用如今的話來講,Google 那時是一家「小巨頭」:已經初露鋒芒,不容小覷,但巨頭們彼時正陷入戰爭泥潭,無暇顧及之。2003年,爲了更好地支持新版本的搜索引擎(基於MapReduce),使其能服務好億萬用戶,Google 開始了大規模集羣管理系統的開發,這個系統叫作 Borg,它的目標是管理以萬臺爲單位的計算機集羣。雖然剛開始只有三、4我的的小團隊,但 Borg 仍是跟上了 Google 的飛速發展,證實了它的潛力,最終 Google 的所有機器都由 Borg 管理,MapReduce、Pregel 等著名系統都創建於 Borg 之上。從操做系統的角度來看,Borg 是一個 monolithic 系統,任何對系統的功能升級都須要深刻到 Borg 底層代碼來修改支持。在 Google 這樣成熟的技術型公司中,有不少優秀的工程師,所以這個問題在內部系統中並不算嚴重。但若是是公有云,必然要接入許多第三方應用的需求,一家公司的工程師團隊再強大,也沒法把業界全部其餘系統都接入 Borg,這時系統的可擴展性將很是重要。

在2010年左右,隨着 Google 中國部門的撤銷,不少優秀的 Google 工程師加入了 BAT 等中國公司,其中一部分加入了騰訊搜搜。這些前 Googler 加入騰訊後,復刻了 Google 的許多系統,技術上也很出色,其中 Borg 的複製品叫作 TBorg,後來更名爲 Torca。Torca 在搜搜的廣告業務中起到了很是重要的做用,後來因爲騰訊業務調整,搜搜與搜狗合併,Torca 在騰訊內部失去用戶,逐漸中止了維護。

在 Borg 上線幾年後,Google 意識到 monolithic 架構的問題和瓶頸,因而又一支小團隊開始了 Omega 系統的研發。Omega 系統繼承的是微內核的思想,新的功能升級幾乎不需修改底層代碼就能完成,它比 Borg 更加靈活,有更好的伸縮性。但由於當時 Google 的所有系統已經搭建在 Borg 之上了,因爲 Borg 的 monolithic 特性,MapReduce 等系統都緊密綁定到 Borg 核心代碼,不但無縫遷移到 Omega 系統是不可能的,遷移還要花巨大的人力、時間和試錯成本,所以即便核心成員堅持不懈地推進,Omega 系統在 Google 仍未能取得成功。

有趣的是,Omega 項目的核心成員之一 Brendan Burns 的職業軌跡和操做系統領域的大前輩 David Cutler 有很多類似之處。

  1. 他們一樣畢業於文理學院:David Cutler 畢業於 Olivet College,Brendan Burns 畢業於 Williams College。
  2. 他們一樣在畢業後加入了一家傳統行業的巨頭:David Cutler 畢業後加入杜邦,Brendan Burns 畢業後加入湯姆森金融。
  3. 正如教父所說,一個男人只能有一種命運,Cutler 和 Burns 在這兩家傳統巨頭學會了寫代碼,也許就是在那時,他們發現了本身在軟件上的天分,發現了本身的命運是構建新一代操做系統。所以他們一樣在第二份工做中選擇了當時最煊赫一時的科技巨頭:David Cutler 加入 DEC,Brendan Burns 加入 Google。
  4. 他們一樣在微軟到達了職業生涯的頂峯:Brendan Burns 現現在已經是微軟的 Corporate VP,而 David Cutler 老爺子早已經是微軟惟一的 Senior Technical Fellow,據傳微軟甚至有條規定,Cutler 的技術職級必須是全公司最高的,任何人升到 Cutler 的 level,Cutler 就自動升一級。

Kubernetes 的誕生

在單機操做系統時代,hybrid kernel 盛行一時,這證實了微內核在軟件架構上的成功,但由於性能問題,又沒有任何一個成功的內核採用「純粹的」微內核架構,所以微內核從實用角度上來講是失敗的。

和單機操做系統時代中微內核架構的失敗緣由不一樣,Omega 在 Google 公司內部的失敗和性能問題無關,只是歷史遺留問題的影響。對開源社區和大部分公司來講,尚無能和 Borg 相媲美的系統,也沒有歷史負擔,所以幾年後,Google 決定開源 Omega 這一超越 Borg 的新一代分佈式操做系統,將其命名爲 Kubernetes。

爲了介紹清楚 Kubernetes 和微內核的關係,以及微內核架構爲 Kubernetes 帶來的優點,這裏有必要引入一些技術細節。

上文中提到,單機操做系統的系統調用須要「陷入」內核,所謂的陷入(trap)也叫作中斷(interrupt),不管內核是什麼類型,單機操做系統都須要在啓動時將系統調用註冊到內存中的一個區域裏,這個區域叫作中斷向量(Interrupt Vector)或中斷描述符表(IDT,Interrupt Descriptor Table)。固然,現代操做系統的中斷處理很是複雜,系統調用也不少,所以除了IDT以外,還須要一張系統調用表(SCV,System Call Vector),系統調用經過一個統一的中斷入口(如 INT 80)調用某個中斷處理程序,由這個中斷處理程序經過 SCV 把系統調用分發給內核中不一樣的函數代碼。所以 SCV 在操做系統中的位置和在星際爭霸中的位置一樣重要。對微內核架構來講,除了 SCV 中的系統調用以外,用戶態服務提供什麼樣的系統能力,一樣須要註冊到某個區域。

與此相似,Kubernetes 這樣的分佈式操做系統對外提供服務是經過 API 的形式,分佈式操做系統自己提供的 API 至關於單機操做系統的系統調用,每一個 API 也須要可以註冊到某個位置。對 Kubernetes 來講,API 會註冊到 ectd 裏。Kubernetes 自己提供的至關於系統調用的那些 API,經過名爲 Controller 的組件來支持,由開發者爲 Kubernetes 提供的新的 API,則經過 Operator 來支持,Operator 自己和 Controller 基於同一套機制開發。這和微內核架構的思想一脈相承:Controller 至關於內核態中運行的服務,提供線程、進程管理和調度算法等核心能力,Operator 則至關於微內核架構中 GUI、文件系統、打印機等服務,在用戶態運行。

Kubernetes

圖片來源:https://mapr.com/products/kubernetes/

所以,Kubernetes 的工做機制和單機操做系統也較爲類似,etcd 提供一個 watch 機制,Controller 和 Operator 須要指定本身 watch 哪些內容,並告訴 etcd,這至關因而微內核架構在 IDT 或 SCV 中註冊系統調用的過程。

以 Argo 爲例,Argo 是個 Operator,提供在 Kubernetes 中執行一個 DAG 工做流的能力。用戶在使用 kubectl 命令提交 Argo 任務時,實際是讓 kubectl 將 Argo 的 yaml 提交給 Kubernetes 的 API Server,API Server 將 yaml 中的 Key-Value 數據寫入 etcd,etcd 將會提醒那些正在 watch 指定 Key 的服務。在咱們的例子中,這個服務也就是 Argo。這正像是微內核架構裏用戶進程請求用戶態服務的過程。

Argo 獲得 etcd watch 的 http 請求,去 etcd 讀出 yaml 中的數據並解析, 而後知道要去啓動什麼容器,並經過 API 要求 Kubernetes 啓動相應的容器。Kubernetes scheduler 是一個 Controller,在收到啓動容器請求後,分配資源,啓動容器。這是微內核架構中用戶進程經過系統調用啓動另外一個進程的過程。

固然,Kubernetes 和單機操做系統也有不一樣之處:Kubernetes 沒有明確的「陷入」過程,而微內核架構的單機操做系統在訪問系統調用時須要陷入,在訪問用戶態服務時則不須要陷入。可是,Kubernetes 能夠爲不一樣的服務設置不一樣的權限,這一點在必定程度上相似於單機操做系統中內核態和用戶態的 CPU 權限的區別。

微內核在架構上的優點在 Kubernetes 中顯露無遺:在 Borg 中,開發者想要添加新的子系統是很是複雜的,每每須要修改 Borg 底層代碼,而新系統也所以會綁定到 Borg 上。而對 Kubernetes 來講,開發者只須要基於 Kubernetes 提供的 SDK 實現一個 Operator,就可以添加一組新的 API,而不須要關注 Kubernetes 的底層代碼。Argo、Kubeflow 都是 Operator 的應用。任何已有軟件均可以方便地經過 Operator 機制集成到 Kubernetes 中,於是 Kubernetes 很是適合做爲公有云的底層分佈式操做系統,正因如此,Kubernetes 在2014年年中發佈,通過2015年一年的成長,在2016年便成爲業界主流,對於沒有歷史負擔的公司,也將 Kubernetes 做爲內部雲的底層系統使用。

尾聲

在這篇文章中,咱們介紹了單機操做系統的發展簡史,介紹了微內核架構在這個歷史進程中從興起到衰落的過程,也介紹了微內核架構在 Kubernetes 中從新煥發生機的過程。總的來講,顯著超前於時代的技術雖然未必能在被提出的時代取得成功,但必定會在多年後,在時代跟上來以後,拿回屬於本身的榮耀。微內核架構在單機操做系統的時代和雲計算的時代的不一樣遭遇證實了這一點,深度學習在低算力時代和高算力時代的不一樣遭遇也證實了這一點。

值得一提的是,在 Kubernetes 以後,Google 推出了 Fuchsia 做爲 Android 可能的替代品。而 Fuchsia 基於 Zircon 內核開發,Zircon 基於 C++ 開發,正是微內核架構。在算力井噴的現代,除了在分佈式操做系統領域,微內核可否也在手機/物聯網操做系統領域復興,讓咱們拭目以待。

本文內容主要基於王益最近給SQLFlow 和ElasticDL 團隊的分享。沈凋墨和章海濤、武毅、閆旭、張科等一塊兒總結。這個總結解釋了 SQLFlow 做爲一個 Kubernetes-native 的分佈式編譯器的設計思路基礎,也解釋了 ElasticDL 只針對 Kubernetes 平臺作分佈式 AI 的緣由。本文做者中包括百度 Paddle EDL 的做者。Paddle EDL 是基於 PaddlePaddle 和 Kubernetes 的分佈式計算框架,於 2018 年貢獻給 Linux Foundation.

相關文章
相關標籤/搜索