第1章 初识Kubernetes
本章内容分为以下两个部分。
Kubernetes的背景介绍,比如它的来源等。Kubernetes如何成为云上的操作系统。
1.1 Kubernetes的背景
Kubernetes是一个应用编排器(orchestrator),主要用于对容器化的云原生微服务应用进行编排。对于这一定义读者可能会感觉技术术语太多了!
随着对Kubernetes的了解和使用,这些术语都会遇到,下面就花少量的篇幅进行简要的介绍。
1.1.1 编排器
编排器是一套部署和管理应用程序的系统。它能够部署应用,并动态地响应变化。例如,Kubernetes包括但不仅限于以下功能。
- 部署应用程序。
- 根据需要动态扩缩容。
- 当出现故障时自愈。
- 进行不停机的滚动升级和回滚。
Kubernetes最突出的优点是,它可以在无须人工干预决策的情况下自动完成以上所有任务。显然,这需要用户在最初进行一些配置,一旦完成配置,就可以一劳永逸地放心交给Kubernetes了。
1.1.2 容器化应用
所谓容器化应用就是运行在容器中的应用。
在容器技术出现之前,应用程序可以运行在物理机或虚拟机中。容器是关于应用打包和运行方式的新的迭代,它更加快速、轻量,也比服务器或虚拟机更加适合现代的业务需求。
可以这样想。
- 在开放系统(open-system)时代(大约20世纪80年代和20世纪90年代),应用运行在物理机上。
- 在虚拟机时代(大约2000—2010年),应用运行在虚拟机中。
- 在云原生(cloud-native)时代(如今),应用运行在容器中。
同时,Kubernetes也可以编排其他负载类型,包括虚拟机和serverless功能(serverless function),不过最普遍的情况是用于容器的编排。
1.1.3 云原生应用
所谓云原生应用,是指被设计用来满足现代业务需求(自动扩缩容、故障自愈、滚动升级等)并且运行在Kubernetes之上的应用。
我认为有必要澄清一点,那就是云原生应用并非只能运行在公有云上。当然,它们可以运行在公有云上,不过也可以运行在其他任何Kubernetes平台之上,甚至包括自建数据中心。
1.1.4 微服务应用
一个微服务应用,是指由许多小而专的服务组件,通过互相通信而组成的一套完整的业务系统。以一个电子商务系统为例,它可能由以下功能独立的微服务组成。
- Web前端。
- 分类服务。
- 购物车。
- 授权服务。
- 日志服务。
- 持久化存储。
每一个单独的服务都可被称为一个微服务。通常,每个微服务都可以由不同的团队负责研发和运维,可以拥有自己的发布节奏,并且独自进行扩缩容。例如,可以在不影响其他组件的情况下,为日志服务打补丁或扩容。
这种构建方式正是云原生应用的一个很重要的特点。
通过以上的介绍,我们再来回顾一下前面那个由各种晦涩难懂的术语组成的定义。
Kubernetes可用于部署和管理(编排)那些能够以容器的形式打包和运行(容器化)的应用,这些应用的构建方式(云原生微服务)使它们能够根据业务需求实现扩缩容、故障自愈和在线升级。
以上这些以上这些概念将会贯穿本书,相信通过目前的介绍,读者可以对相关的术语具备一定的了解。
1.2 Kubernetes的诞生
让我们从故事的开头讲起……
Amazon Web服务(Amazon Web Services, AWS)通过其现代云计算产品改变了世界。自那时起,大家都在尝试追赶AWS的步伐。
其中一个公司就是Google。Google内部也有非常出色的云技术,并且希望通过某种方式吸取AWS的经验,使其潜在用户能够更加容易地使用Google云。
Google在将容器用于扩缩容方面有丰富的管理经验。例如,类似搜索和邮箱这种大型的Google应用,已经在极大规模的容器云上运行多年了——远早于Docker这种易于使用的容器产品。为了编排和管理这些容器化的应用,Google内部有一套专门的系统。他们利用来自这些内部系统的经验,创建了一套新的平台,名为Kubernetes,并将其作为开源项目于2014年捐赠给了当时刚刚成立的云原生计算基金会(Cloud Native Computing Foundation,CNCF),Logo如图1.1所示。

自此以后,Kubernetes就成为了世界上最重要的云原生技术。
与许多现代云原生项目一样,Kubernetes通过Go语言编写而成,开源在GitHub上(项目名为kubernetes/Kubernetes),开发人员在IRC频道上进行沟通,人们也可以在Twitter上关注它,slack.k8s.io是一个不错的用于沟通的Slack频道。除此之外,还有一些定期举行的见面会或大型会议。
1.2.1 Kubernetes和Docker
Kubernetes和Docker是两个互补的技术。比如,通常人们会使用Docker进行应用的开发,然后用Kubernetes在生产环境中对应用进行编排。
在这样的模式中,开发者使用自己喜欢的语言编写代码,然后用Docker进行打包、测试和交付。但是最终在测试环境或生产环境中运行的过程是由Kubernetes来完成的。
从运行架构上来说,假设在某生产环境中的Kubernetes集群是由10个节点构成的。那么其中的每个节点都是以Docker作为其容器运行时(Container Runtime)。也就是说,Docker是一种更加偏向底层的技术,它负责诸如启停容器的操作;而Kubernetes是一种更加偏向上层的技术,它注重集群范畴的管理,比如决定在哪个节点上运行容器、决定什么适合进行扩缩容或升级。
图1.2阐释了由多个以Docker为容器运行时的节点构成的Kubernetes集群。

如图1.2所示,Docker并非Kubernetes唯一支持的容器运行时。事实上,Kubernetes基于一系列特性实现了对容器运行时的抽象(从而可以兼容不同的底层容器运行时)。
- 容器运行时接口(
Container Runtime Interface, CRI)是Kubernetes用来与第三方容器运行时进行对接的标准化的抽象层。这样容器运行时与Kubernetes是解耦的,同时又能够以一种标准化的方式予以支持。 - 运行时类(
Runtime Class)是Kubernetes 1.12引入的新特性,并在1.14版中升级为beta。它对不同的运行时进行了归类。例如,gVisor或Kata容器运行时或许比Docker和Containerd能提供更优的隔离性。
至本书撰写时,Containerd已经赶超Docker成为Kubernetes中最普遍使用的容器运行时。它实际上是Docker的精简版本,只保留了Kubernetes需要的部分。
虽有提及,不过这些底层技术不会影响到Kubernetes的学习体验。无论使用哪种容器运行时,Kubernetes层面的操作(命令等)都是一样的。
1.2.2 Kubernetes与Docker Swarm对比
2016—2017年间,在Docker Swarm、Mesosphere DCOS以及Kubernetes之间展开了一场容器编排平台之战。总之,Kubernetes赢得了胜利。
虽然Docker Swarm和其他容器编排平台依然存活,但是它们的发展势头和市场份额都小于Kubernetes。
1.2.3 Kubernetes和Borg:抵抗是徒劳的
读者很可能听到过有关Kubernetes与Google的Borg和Omega系统的关系。
如前所述,很久以前Google就已经大规模地运行容器了——每周都可能运行数十亿个容器。所以,多年以来,Google的搜索、Gmail和GFS等就已经在许多的容器中运行了。
对这些容器化应用的编排工作,是由Google内部被称为Borg和Omega的技术来完成的。所以Kubernetes的出现也是水到渠成的事——毕竟它们都是大规模容器编排平台,而且同出Google之门。
然而需要明确的是,Kubernetes并非Borg或Omega的开源版本。更恰当地说是Kubernetes与Borg和Omega有着相同的基因和家族史。就像是Borg最先出生,然后孕育了Omega。而Omega又与开源社区“比较熟”,并孵化了Kubernetes,如图1.3所示。

问题在于,它们是不同的,但又是相关的。事实上,许多Borg和Omega的研发者也对Kubernetes有所贡献。所以,尽管Kubernetes是从头开始研发的,但是也吸收了来自Borg和Omega的经验。
目前,Kubernetes是于2014年捐赠给CNCF的开源项目,基于Apache 2.0协议。其1.0版本早在2015年7月就已发布,至本书编写时,已经到达1.16版。
1.2.4 Kubernetes——名字从何而来
Kubernetes(读作koo-ber-net-eez)一词来源于希腊语“舵手”——轮船的掌舵之人。这一主题也在图标(见图1.4)中得以体现。

Kubernetes的部分创始人想将其称作九之七(Seven of Nine)。如果读者了解星际迷航,就会知道九之七是一个被联邦星舰企业号解救的女性博格(Borg),下令解救她的是凯瑟琳·珍妮薇舰长。然而,版权法不允许用这个名字。不过图标中的“七个把手”也有向“九之七”致敬的意味。
关于名称需要交代的最后一点是,Kubernetes经常被写作K8s。其中的数字8替代了K和s中的8个字母——这一点倒是方便了发推,也方便了像我这样懒惰的人。
1.3 云操作系统
Kubernetes已经成为部署和管理云原生应用的事实上的标准平台。从多种方面来看,它就类似于云上的操作系统(OS)。试想一下以下情况。
- 当在物理服务器上安装一套传统的操作系统(Linux或Windows)时,操作系统会对服务器的物理资源进行抽象,并对进程进行调动,等等。
- 当在云上安装
Kubernetes时,它会对云上的资源进行抽象,并对多种云原生微服务应用进行调度。
就像Linux能够对不同的服务器硬件进行统一的抽象一样,Kubernetes也能够对不同的私有云和共有云进行统一的抽象。最终,只要运行Kubernetes,就不需要关心底层是运行在自建数据中心,还是边缘计算集群,抑或是共有云中了。
这样来说,Kubernetes能够实现真正意义上的混合云,使用户跨越不同的公有云或私有云实现对负载的无缝迁移和均衡。当然,也可以在不同的云之间进行迁移,这意味着不会永远被绑定在最初确定的云上。
1.3.1 云的规模
总体来说,容器让人们能够轻松应对大规模系统的扩展性的挑战——前面刚刚提到,Google每周可以运行数十亿的容器!
这很不错,但是并非所有组织或公司都有Google这样的体量。其他的情况呢?
通常来说,如果原有的应用运行在数百个虚拟机上,那么很可能相应的容器化的云原生应用会运行到数千个容器上。这么说来,确实迫切需要一种管理它们的方法。
劝君尝试一下Kubernetes。
而且,我们生活在一个商业和科技日新月异且越来越专精的世界。有鉴于此,我们迫切需要一种无所不在的框架或平台能够屏蔽这些复杂性。
再次劝君尝试一下Kubernetes。
1.3.2 应用的调度
一台典型的计算机是由CPU、RAM、存储和网络构成的。不过现代操作系统已经能够对大多数的底层进行很好的抽象。举例来说,有多少开发者会去关心程序运行在哪个CPU核心上呢?并没有多少,OS已经为我们搞定了这些。这是一种很好的方式,这使应用程序的开发过程变得友好许多。
Kubernetes对云和数据中心的资源进行了类似的管理。总体来说,云或数据中心就是一个包含计算、存储与网络的资源池。Kubernetes对它进行了抽象。这意味着我们无须明确对应用运行在哪个节点或存储卷上进行硬编程,我们甚至无须关心应用运行在哪个云上——让Kubernetes操心这事即可。从此无须为服务器命名,无须将卷的使用情况记录在电子表格中,总之,无须像对待“宠物”(pet)一样管理数据中心的资产。Kubernetes这样的系统并不关心这些。对应用进行类似“把某应用模块运行在某个指定的节点上,配置它的IP,将其数据至于某个具体的卷上……”这样进行运维操作的日子,已经一去不复返了。
1.3.3 一个简单的模拟
思考一下快递货物的过程。
发件人将货物按照快递公司的标准打包,写明送货信息,然后交给快递小哥。仅此而已,其他的事情交给快递公司来操心就好了:物流过程是走航运还是陆运,跑哪条高速,由哪个司机来驾驶等。快递公司还提供类似于包裹追踪、调整目的地等服务。重点在于,快递公司所需要的仅仅是打包的货物以及送货信息。
Kubernetes中的应用也是类似的。将应用打包成容器,声明其运行方式,然后交给Kubernetes来启动它们并保持其运行状态。Kubernetes同样也提供了丰富的用来检查运行状态的工具和API。特别好用。
1.4 总结
Kubernetes的诞生融入了来自Google多年的大规模容器化运维经验。它被作为开源项目捐赠给社区,现在已经成为部署和管理云原生应用的行业标准API。它可以运行在任何云或自建数据中心上,并对底层基础设施进行了抽象。从而允许用户构建混合云,以及在云平台间轻松实现迁移。它是基于Apache 2.0协议的开源项目,托管于云原生计算基金会(Cloud Native Computing Foundation, CNCF)。
Kubernetes目前正处于积极的开发过程中,因此变化不断。但是不要因此而退缩——积极拥抱它吧!变化是一种新常态!
为了跟上Kubernetes更新的步伐,作者建议订阅其YouTube频道。
KubernetesMoment:按周发布的探讨Kubernetes的短视频。Kubernetes this Month:按月发布,讨论关于Kubernetes的最新要闻。
以及其他推荐资料。
- 我的主页
nigelpoulton.com。 - 我在
pluralsight.com和acloud.guru上的视频教程。 - 我在MSB上的手把手教学。
KubeCon和读者当地的Kubernetes和云原生交流会。
