现在,Kubernetes 曾经成为分布式集群管理系统和私有云 / 公有云的事实标准。实际上,Kubernetes 是一个分布式操作系统,它是 Google 在分布式操作系统畛域十余年工程教训和智慧的结晶,而 Google 始终以来都治理着世界上最大的分布式集群,在分布式操作系统畛域的钻研和意识当先于全世界。因而,2014 年公布的 Kubernetes 能在短短几年工夫内就超过了诸多前辈,大获胜利。
作为分布式操作系统,Kubernetes(包含其前代产品 Google Borg)的呈现远远晚于 UNIX、Linux、Windows 等驰名的单机操作系统,Kubernetes 架构设计天然地继承了很多单机操作系统的宝贵遗产,微内核架构就是这些遗产中最重要的一份。在本文接下来的局部,咱们将专一于微内核(microkernel)这个概念及其对 Kubernetes 架构的影响。
什么是微内核?
在介绍微内核的时候,咱们有必要同时回顾一下单机操作系统的历史,以了解其价值所在。本章中以「操作系统」指代「单机操作系统」。
UNIX 的衰亡
电子计算机诞生之后,在上个世纪 70 年代以前,呈现过许许多多的操作系统,DOS、OS/360、Multics 是其中的出名代表,这是操作系统畛域的开荒时代。20 年来的开荒孕育出了平凡的成绩:随着 CPU 技术的倒退,UNIX 于 1969 年诞生了,这是一个真正意义上的分时操作系统。
图片起源:维基百科
借助新的 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 开发了很多新的操作系统内核,其中较为出名的有:
- BSD,monolithic,由伯克利的传奇人物 Bill Joy 于 1974 年公布(据说 Bill Joy 花三天便实现了 BSD 内核的第一个版本开发,Bill Joy 的作品还蕴含第一个 TCP/IP 协定栈、vi、Solaris、SPARK 芯片等等)。该内核对业界影响十分之大,起初倒退为 FreeBSD、OpenBSD、NetBSD 等分支。古代操作系统如 Solaris、MacOS X、Windows NT 对其多有借鉴。
- Mach,微内核,由卡内基梅隆大学于 1984 年公布,次要作者是 CMU 的两位研究生 Avie Tevanian 和 Rick Rashid。该内核对业界影响也很大,GNU Hurd、MacOS X 对其多有借鉴,但该我的项目自身以失败告终。
- MINIX,微内核,由阿姆斯特丹自在大学(Vrije Universiteit Amsterdam)的 Andrew Tanenbaum 传授于 1987 年公布。有数计算机系学生通过 MINIX 及其配套教材把握了操作系统的设计原理,Linux 的初始版本就是基于 MINIX 复刻的。MINIX 尽管驰名,但次要用于教学,从未在工业界取得一席之地。
微内核的寂静
从上世纪 90 年代至本世纪 10 年代,UNIX 和 VMS 的后嗣们开展了一场混战,从后果来看,微内核的概念尽管美妙,但事实十分残暴:
- MINIX 仅限于教学,而基于 MINIX 设计的 Linux 是 monolithic 零碎,反而大获胜利。Mach 对业界影响深远,但自身并未失去大规模利用,其继承者 GNU Hurd 始终在开发中,从未能利用。
- Windows 的 NTOS 内核是 David Cutler 基于他原来在 DEC 独立设计的零碎 VMS 设计的(VMS 和 UNIX 无关)。NTOS 借鉴了微内核的思维和 BSD 的一些代码,但最终 David Cutler 决定将所有服务(如 GUI)都放到内核态而非用户态,因而 Windows NT 在软件架构上和微内核统一,而理论运行和 monolithic 内核统一,被称为 hybrid kernel。
- 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,它的指标是治理以万台为单位的计算机集群。尽管刚开始只有 3、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 有不少相似之处。
- 他们同样毕业于文理学院:David Cutler 毕业于 Olivet College,Brendan Burns 毕业于 Williams College。
- 他们同样在毕业后退出了一家传统行业的巨头:David Cutler 毕业后退出杜邦,Brendan Burns 毕业后退出汤姆森金融。
- 正如教父所说,一个男人只能有一种命运,Cutler 和 Burns 在这两家传统巨头学会了写代码,兴许就是在那时,他们发现了本人在软件上的天性,发现了本人的命运是构建新一代操作系统。因而他们同样在第二份工作中抉择了过后最煊赫一时的科技巨头:David Cutler 退出 DEC,Brendan Burns 退出 Google。
- 他们同样在微软达到了职业生涯的高峰: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、文件系统、打印机等服务,在用户态运行。
图片起源: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.