Kubernetes修炼手册
人民邮电出版社
北京
图书在版编目(CIP)数据
Kubernetes修炼手册/(英)奈吉尔·波尔顿(Nigel Poulton)著;刘康,李瑞丰译.--北京:人民邮电出版社,2021.5
ISBN 978-7-115-56109-1
Ⅰ.①K… Ⅱ.①奈… ②刘… ③李… Ⅲ.①Linux操作系统—程序设计—手册 Ⅳ.①TP316.85-62
中国版本图书馆CIP数据核字(2021)第042691号
版权声明
Simplified Chinese translation copyright ©2021 by Posts and Telecommunications Press.
ALL RIGHTS RESERVED.
The Kubernetes Book, by Nigel Poulton, ISBN 9781521823637
Copyright © 2021by Nigel Poulton
本书中文简体版由作者授权人民邮电出版社有限公司出版。未经出版者书面许可,对本书的任何部分不得以任何方式或任何手段复制和传播。
版权所有,侵权必究。
◆ 著 [英]奈吉尔·波尔顿(Nigel Poulton)
译 刘康 李瑞丰
责任编辑 陈聪聪
责任印制 王郁 彭志环
◆ 人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
北京市艺辉印刷有限公司印刷
◆ 开本:800×1000 1/16
印张:13
字数:258千字 2021年5月第1版
印数:1–2000册 2021年5月北京第1次印刷
著作权合同登记号 图字:01-2019-4796号
定价:69.90元
读者服务热线:(010)81055410 印装质量热线:(010)81055316
反盗版热线:(010)81055315
广告经营许可证:京东市监广登字20170147号
本书是一本Kubernetes入门图书,共分为12章,涵盖了Kubernetes的基础知识,并附带了大量的配置案例。此外,还介绍了Kubernetes架构、构建Kubernetes集群、在Kubernetes上部署和管理应用程序、Kubernetes安全,以及云本地、微服务、容器化等术语的含义。本书在内容上不断进行充实和完善,可以帮助读者快速入门Kubernetes。
本书适合系统管理员、开发人员,以及对Kubernetes感兴趣的初学者阅读。
这一版本于2020年9月发布。
在编写此版本的内容时,我细致校审了每一页文字和每一个示例,以确保所有内容均可适用于新版本的Kubernetes,以及符合云原生生态的技术趋势。
为了保证对新技术的跟进,这一版增加了如下内容。
●StatefulSet的介绍。
●术语表。
希望读者能从此书中受益!
©️□2020奈吉尔·波尔顿
教育之意义在于启迪和创造机会。
我衷心地希望这本书,能够对您有所启迪,并带给您新的机会!
非常感谢我的妻子和孩子们对我的忍耐。我是一个极客——我认为自己是一套运行在生化硬件之上的软件。我知道与我相处并不容易!
非常感谢每一个观看我在Pluralsight、Udemy以及A Cloud Guru上的视频的朋友。我很乐意与你们交流,感谢这么多年来大家给我的反馈,这促使我写作这本书!我希望您能喜欢这本书,并有助于推动您的事业发展。
最后的感谢送给在魔术沙盒(Magic Sandbox)的训练营中,借助我的学习资料使自己的Kubernetes之旅步入新台阶的朋友。
@nigelpoulton
我要感谢普什卡(Pushkar)在有关安全章节中的贡献。在一次KubeCon大会上普什卡找到我,并询问是否可以加入一些关于安全运行环境的内容。我以前并未有过合作编写的经历,因此婉拒了他(我这个人比较散漫,较难共事)。然而,普什卡很是积极,于是我们进行了合作。需要指出的是,在安全相关的章节中,技术方面的内容全部出自普什卡之手。我仅仅进行了一些写作风格的调整,以便全书保持一致。
——奈吉尔·波尔顿
奈吉尔是一名致力于在云相关技术领域创作图书、培训教程和在线教育的技术极客。他是有关Docker和Kubernetes的畅销图书的作者,同时也是在该领域广受欢迎的在线培训视频的作者。他是一个Docker大牛,在此之前,奈吉尔曾在多家大型企业(多为银行)中担任与架构师相关的角色。
他一直在钻研技术,空闲时间可能阅读科幻小说或看科幻电影。他希望能够生活在未来,这样就可以探索时空、宇宙,以及其他脑洞大开的事物。他喜欢汽车、足球和美食。
普什卡目前是一名面向容器的防御安全工程师,这些容器涉及深度学习和分布式系统。最近几年,他为某财富百强公司研发构建了多个“设计即安全”的容器产品。
工作之余,他喜欢骑行游览附近街区,或是悠闲地吃着自制的马萨拉姜仔饼,用相机记录落日美景。
他同他美丽的妻子生活在一起,她也是一名工程师。
本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。
配套资源
本书配套资源请到异步社区本书购买页处下载。
要获得以上配套资源,请在异步社区本书页面中单击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。
提交勘误
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,单击“提交”按钮即可(见下图)。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
扫码关注本书
扫描下方二维码,您将会在异步社区微信服务号中看到本书信息及相关的服务提示。
与我们联系
我们的联系邮箱是chencongcong@ptpress.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们。
如果您所在的学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
关于异步社区和异步图书
“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。
“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。
这是一本新的关于Kubernetes的图书,虽然本书并不厚,却字字珠玑。
为了避免误导读者,特此说明:本书并非一本面面俱到、系统深入阐述Kubernetes的图书,而是一本易于阅读的令读者能够快速掌握Kubernetes的书。
纸质版
本书目前有几种不同的纸质版本。
●我在Amazon上自出版的英文版纸书。
●由Shroff出版的仅在印度次大陆出售的纸书。
●由人民邮电出版社出版的简体中文版纸书。
为什么会有一个面向印度次大陆的特别版本呢?
当我编写本书时,Amazon的自出版服务尚未在印度提供,这意味着我无法在印度发行纸质版。我调研了几种不同的方式,并最终决定与出版商Shroff合作。我非常感谢Shroff能够帮助将本书送到更多的读者手中。
音频版
我在2019年3月于Audible上推出了一版相当具有娱乐性的音频版本。为了便于理解,该版本对其中的部分例子和实验进行了微调。除此之外,读者可以获得完整的学习体验。
eBook和Kindle版
获取本书英文版电子版的最方便的地方是Leanpub。这是一个不错的平台,而且免费更新。
您也可以在美国Amazon网站上获取Kindle版本,同样也可以获取免费更新。然而众所周知的是,Kindle对更新的推送并不友好。如果您在获取更新的时候遇到问题,请联系Kindle客服来解决。
反馈
如果您喜欢本书并且觉得它有价值,那么请您推荐给您的朋友,或在Amazon的评论区留言(即使通过其他渠道购买,也是可以在Amazon上发表评价的)。
为什么阅读本书,以及为什么关注Kubernetes
当前Kubernetes异常火热,对该技能的需求也很多。因此,如果您希望在事业上有所提升,并且在工作中使用一种能够重塑未来的技术,那么您需要阅读本书。
如果已经看过视频教程,还需要买本书吗
由于都是围绕Kubernetes,那么可以肯定的是,我的书和视频教程的内容会有重复的部分。但是看书和看视频是完全不同的体验。我认为,视频更有意思,但是图书更容易做笔记以及翻阅查找。
如果我是您,我既会观看视频,也会阅读本书。二者是互补的,而且基于不同的途径进行学习是行之有效的。
我的一些视频教程如下。
●Kubernetes入门(Getting Started with Kubernetes, pluralsight.com)
●深入浅出Kubernetes(Kubernetes Deep Dive, acloud.guru)
●深入浅出Docker(Docker Deep Dive, pluralsight.com)
本书的免费更新
我将尽力确保您对本书的投资是保值的!
Kindle和Leanpub上的所有购买者都可免费获取更新。Leanpub上的更新很及时,但是在Kindle上可能会遇到些许问题。许多读者抱怨Kindle设备上的内容无法获得更新。这是一个普遍存在的问题,最简单的解决办法就是联系Kindle客服。
如果您在Amazon上购买了纸书,那么就可以使用折扣价格来购买Kindle版本。这来源于“Kindle Matchbook”服务。遗憾的是,Kindle Matchbook服务仅在美国地区实行,并且可能存在问题——有时候Kindle Matchbook的图标无法在Amazon图书销售页面显示。如果遇到此类问题,请联系Kindle客服来解决。
如果在其他渠道购买本书,我也爱莫能助了。我只是个搞技术的,不是出版商。
本书的GitHub库
本书有对应的GitHub库,其中的内容为书中的YAML代码和示例。
本书的版本
Kubernetes发展得很快!因此,此类图书的价值与其新旧程度是密切相关的。也就是说,图书越旧,那么其价值也就越低。鉴于此,我承诺将至少每年进行一次更新。我所说的“更新”,是指真正的更新——每个词语和概念都会重审,每个例子都会测试和更新。我会尽心尽责,争取让本书成为市面上最好的Kubernetes图书。
您也许会觉得至少每年更新一次太频繁了……然而这就是新常态。
如今,多数两年前的技术图书已经没有太多价值。事实上,对于像Kubernetes这样发展迅速的技术,一年前的相关图书的价值都有待商榷。作为作者,我当然希望写出的书能够耐得住5年时光的考验。但是现实并非如此。再次强调,欢迎来到新常态。
●版本7,2020年9月。所有的内容都针对Kubernetes 1.18进行了测试。新增关于StatefulSet的章节,增加了术语表。
●版本6,2020年2月。所有的内容都针对Kubernetes 1.16.6进行了测试。增加关于服务发现的新章节,由于附录会给人一种未完成的感觉,从而将其删除。
●版本5,2019年11月。针对Kubernetes 1.16.2进行了内容更新和示例测试。增加了有关ConfigMaps的章节。把第8章移至附录,并在附录中增加了有关服务网格(Service Mesh)技术的概述。
●版本4,2019年3月。所有内容进行了更新,所有示例都在最新版本的Kubernetes上进行了测试。添加了新的关于存储的章节。新增了两章关于实际运行环境中的安全问题的内容。
●版本3,2018年11月。调整了部分章节的顺序从而使内容更加顺畅。删除了ReplicaSets的章节,并将其中的内容挪到第5章。
●版本2.2,2018年1月。修改了一些文字错误,添加了一些解释性内容和图表。
●版本2.1,2017年12月。修改了一些文字错误,更新了缺少图例的图6.11和图6.12。
●版本2,2017年10月。新增ReplicaSets的章节。对Pod的相关内容进行了大量改动。修改了一些文字错误,并对现有章节进行了一些微调。
●版本1。初始版本。
本章内容分为以下两个部分。
●Kubernetes的背景介绍,比如它的来源等。
●Kubernetes如何成为云上的操作系统。
Kubernetes是一个应用编排器(orchestrator),主要用于对容器化的云原生微服务应用进行编排。对于这一定义读者可能会感觉技术术语太多了!
随着对Kubernetes的了解和使用,这些术语都会遇到,下面就花少量的篇幅进行简要的介绍。
编排器是一套部署和管理应用程序的系统。它能够部署应用,并动态地响应变化。例如,Kubernetes包括但不仅限于以下功能。
●部署应用程序。
●根据需要动态扩缩容。
●当出现故障时自愈。
●进行不停机的滚动升级和回滚。
Kubernetes最突出的优点是,它可以在无须人工干预决策的情况下自动完成以上所有任务。显然,这需要用户在最初进行一些配置,一旦完成配置,就可以一劳永逸地放心交给Kubernetes了。
所谓容器化应用就是运行在容器中的应用。
在容器技术出现之前,应用程序可以运行在物理机或虚拟机中。容器是关于应用打包和运行方式的新的迭代,它更加快速、轻量,也比服务器或虚拟机更加适合现代的业务需求。
可以这样想。
●在开放系统(open-system)时代(大约20世纪80年代和20世纪90年代),应用运行在物理机上。
●在虚拟机时代(大约2000—2010年),应用运行在虚拟机中。
●在云原生(cloud-native)时代(如今),应用运行在容器中。
同时,Kubernetes也可以编排其他负载类型,包括虚拟机和serverless功能(serverless function),不过最普遍的情况是用于容器的编排。
所谓云原生应用,是指被设计用来满足现代业务需求(自动扩缩容、故障自愈、滚动升级等)并且运行在Kubernetes之上的应用。
我认为有必要澄清一点,那就是云原生应用并非只能运行在公有云上。当然,它们可以运行在公有云上,不过也可以运行在其他任何Kubernetes平台之上,甚至包括自建数据中心。
一个微服务应用,是指由许多小而专的服务组件,通过互相通信而组成的一套完整的业务系统。以一个电子商务系统为例,它可能由以下功能独立的微服务组成。
●Web前端。
●分类服务。
●购物车。
●授权服务。
●日志服务。
●持久化存储。
每一个单独的服务都可被称为一个微服务。通常,每个微服务都可以由不同的团队负责研发和运维,可以拥有自己的发布节奏,并且独自进行扩缩容。例如,可以在不影响其他组件的情况下,为日志服务打补丁或扩容。
这种构建方式正是云原生应用的一个很重要的特点。
通过以上的介绍,我们再来回顾一下前面那个由各种晦涩难懂的术语组成的定义。
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频道。除此之外,还有一些定期举行的见面会或大型会议。
Kubernetes和Docker是两个互补的技术。比如,通常人们会使用Docker进行应用的开发,然后用Kubernetes在生产环境中对应用进行编排。
在这样的模式中,开发者使用自己喜欢的语言编写代码,然后用Docker进行打包、测试和交付。但是最终在测试环境或生产环境中运行的过程是由Kubernetes来完成的。
从运行架构上来说,假设在某生产环境中的Kubernetes集群是由10个节点构成的。那么其中的每个节点都是以Docker作为其容器运行时(Container Runtime)。也就是说,Docker是一种更加偏向底层的技术,它负责诸如启停容器的操作;而Kubernetes是一种更加偏向上层的技术,它注重集群范畴的管理,比如决定在哪个节点上运行容器、决定什么适合进行扩缩容或升级。
图1.2阐释了由多个以Docker为容器运行时的节点构成的Kubernetes集群。
如图1.2所示,Docker并非Kubernetes唯一支持的容器运行时。事实上,Kubernetes基于一系列特性实现了对容器运行时的抽象(从而可以兼容不同的底层容器运行时)。
(1)容器运行时接口(Container Runtime Interface, CRI)是Kubernetes用来与第三方容器运行时进行对接的标准化的抽象层。这样容器运行时与Kubernetes是解耦的,同时又能够以一种标准化的方式予以支持。
(2)运行时类(Runtime Class)是Kubernetes 1.12引入的新特性,并在1.14版中升级为beta。它对不同的运行时进行了归类。例如,gVisor或Kata容器运行时或许比Docker和Containerd能提供更优的隔离性。
至本书撰写时,Containerd已经赶超Docker成为Kubernetes中最普遍使用的容器运行时。它实际上是Docker的精简版本,只保留了Kubernetes需要的部分。
虽有提及,不过这些底层技术不会影响到Kubernetes的学习体验。无论使用哪种容器运行时,Kubernetes层面的操作(命令等)都是一样的。
2016—2017年间,在Docker Swarm、Mesosphere DCOS以及Kubernetes之间展开了一场容器编排平台之战。总之,Kubernetes赢得了胜利。
虽然Docker Swarm和其他容器编排平台依然存活,但是它们的发展势头和市场份额都小于Kubernetes。
读者很可能听到过有关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版。
Kubernetes(读作koo-ber-net-eez)一词来源于希腊语“舵手”——轮船的掌舵之人。这一主题也在图标(见图1.4)中得以体现。
Kubernetes的部分创始人想将其称作九之七(Seven of Nine)。如果读者了解星际迷航,就会知道九之七是一个被联邦星舰企业号解救的女性博格(Borg),下令解救她的是凯瑟琳·珍妮薇舰长。然而,版权法不允许用这个名字。不过图标中的“七个把手”也有向“九之七”致敬的意味。
关于名称需要交代的最后一点是,Kubernetes经常被写作K8s。其中的数字8替代了K和s中的8个字母——这一点倒是方便了发推,也方便了像我这样懒惰的人。
Kubernetes已经成为部署和管理云原生应用的事实上的标准平台。从多种方面来看,它就类似于云上的操作系统(OS)。试想一下以下情况。
●当在物理服务器上安装一套传统的操作系统(Linux或Windows)时,操作系统会对服务器的物理资源进行抽象,并对进程进行调动,等等。
●当在云上安装Kubernetes时,它会对云上的资源进行抽象,并对多种云原生微服务应用进行调度。
就像Linux能够对不同的服务器硬件进行统一的抽象一样,Kubernetes也能够对不同的私有云和共有云进行统一的抽象。最终,只要运行Kubernetes,就不需要关心底层是运行在自建数据中心,还是边缘计算集群,抑或是共有云中了。
这样来说,Kubernetes能够实现真正意义上的混合云,使用户跨越不同的公有云或私有云实现对负载的无缝迁移和均衡。当然,也可以在不同的云之间进行迁移,这意味着不会永远被绑定在最初确定的云上。
总体来说,容器让人们能够轻松应对大规模系统的扩展性的挑战——前面刚刚提到,Google每周可以运行数十亿的容器!
这很不错,但是并非所有组织或公司都有Google这样的体量。其他的情况呢?
通常来说,如果原有的应用运行在数百个虚拟机上,那么很可能相应的容器化的云原生应用会运行到数千个容器上。这么说来,确实迫切需要一种管理它们的方法。
劝君尝试一下Kubernetes。
而且,我们生活在一个商业和科技日新月异且越来越专精的世界。有鉴于此,我们迫切需要一种无所不在的框架或平台能够屏蔽这些复杂性。
再次劝君尝试一下Kubernetes。
一台典型的计算机是由CPU、RAM、存储和网络构成的。不过现代操作系统已经能够对大多数的底层进行很好的抽象。举例来说,有多少开发者会去关心程序运行在哪个CPU核心上呢?并没有多少,OS已经为我们搞定了这些。这是一种很好的方式,这使应用程序的开发过程变得友好许多。
Kubernetes对云和数据中心的资源进行了类似的管理。总体来说,云或数据中心就是一个包含计算、存储与网络的资源池。Kubernetes对它进行了抽象。这意味着我们无须明确对应用运行在哪个节点或存储卷上进行硬编程,我们甚至无须关心应用运行在哪个云上——让Kubernetes操心这事即可。从此无须为服务器命名,无须将卷的使用情况记录在电子表格中,总之,无须像对待“宠物”(pet)一样管理数据中心的资产。Kubernetes这样的系统并不关心这些。对应用进行类似“把某应用模块运行在某个指定的节点上,配置它的IP,将其数据至于某个具体的卷上……”这样进行运维操作的日子,已经一去不复返了。
思考一下快递货物的过程。
发件人将货物按照快递公司的标准打包,写明送货信息,然后交给快递小哥。仅此而已,其他的事情交给快递公司来操心就好了:物流过程是走航运还是陆运,跑哪条高速,由哪个司机来驾驶等。快递公司还提供类似于包裹追踪、调整目的地等服务。重点在于,快递公司所需要的仅仅是打包的货物以及送货信息。
Kubernetes中的应用也是类似的。将应用打包成容器,声明其运行方式,然后交给Kubernetes来启动它们并保持其运行状态。Kubernetes同样也提供了丰富的用来检查运行状态的工具和API。特别好用。
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和云原生交流会。
在本章中,读者将学习搭建Kubernates集群并部署某个应用所需的核心组件。本章的主要目的是帮助读者对这些核心概念有一个整体的了解,即使读者在阅读本章的过程中遇到不了解的概念也无须担心,本章的大部分概念会在本书其他章节中进一步介绍。
本章主要分为如下几部分。
●Kubernetes概览。
●主节点与工作节点。
●打包一个App。
●声明式配置与期望状态。
●Pod。
●Deployment。
●Service。
从整体上看,Kubernetes承担了如下两个角色。
●支撑应用运行的集群。
●支持云原生微服务应用的编排器。
作为集群的Kubernetes,正如集群的字面含义一样:包含若干个节点与控制平面。控制平面对外提供API,对内负责各节点的任务分配与调度,并在持久化存储中记录各节点的状态。应用服务就运行在每个节点上。
如果把集群比作一个人,控制平面(control plan)就是大脑,工作节点(node)就是人的肌肉。把控制平面比作大脑,是因为它提供了Kubernetes中的全部重要特性,例如自动扩缩容与不停机更新等功能。而工作节点就像肌肉一样,日夜不停地执行应用代码。
编排器(orchestrator)这个词其实是为了更方便地概况一个包含应用部署与管理的系统,而没有太多的实际含义。
一起来简单地了解一下这个概念。
在真实世界中,一个足球队是由多名球员组成的。没有两名球员是一模一样的,而且每名球员在球队中扮演的角色也是不同的:某些球员负责防守,某些球员负责攻击,某些球员擅长传球,某些球员擅长抢断,还有一些球员射门很厉害……这时候就需要一个教练把球队中所有人组织起来,制定统一的战术目标,并为每个人分配一个场上位置,如图2.1和图2.2所示。
教练要确保球队可以保持阵型并贯彻战术的执行,同时还能处理场上受伤等突发情况。
我认为,这跟微服务应用在Kubernetes上的运行非常相似。
请跟我继续往下看。
下面用一些互相独立的特定服务来进行说明:有一部分服务提供Web网页,有一部分服务提供鉴权,有一部分服务提供搜索,还有提供持久存储的服务。Kubernetes在其中扮演的角色就跟教练在足球队中的角色有点相似了:负责将这些应用组织起来并保持顺畅的运行,当出现一些特定事件或者变化时也要做出响应。
在足球领域中,这种行为称之为指导(coaching),而在服务应用的领域中,这种行为称之为编排(orchestration)。Kubernetes就是负责完成云原生微服务应用的这种行为,我们称之为编排(orchestration)。
为了让Kubernetes运行起来,读者首先需要将自己的App打包并部署到集群(Kubernetes)。一个或多个主节点(master)与若干工作节点(node)构成一个完整的集群。
主节点负责管理整个集群,有时主节点也被称为头结点(head node)。这意味着主节点完成调度决策、监控集群、响应事件与集群变化等工作。因此通常将主节点称作控制平面(control plan)。
应用服务运行在工作节点上,有时也将工作节点称作数据平面(data plan)。每个工作节点都有属于自己的向主节点汇报关系,并监控若干任务的运行。
在Kubernetes上运行应用的过程可以简单分为如下几个部分。
●选用最喜欢的语言将应用以独立的微服务方式实现。
●将每个微服务在容器内打包。
●将每个容器集成到Pod。
●使用更高层面的控制面板将Pod在集群中部署,例如Deployment、DaemonSet、StatefulSet、CronJob等。
不过目前仍处于本书的开始阶段,在现阶段也不需要读者理解上面全部名词的含义。但为了方便理解,对上面的名词做一个概括性介绍:部署(Deployment)提供可扩展性和滚动更新,DaemonSet在集群的每个工作节点中都运行相应服务的实例,有状态应用部署于StatefulSet,同时那些需要不定期运行的临时任务则由定时任务(CronJob)来管理。当然,关于Kubernetes的知识远不止这些,不过当前阶段了解这些就已足够。
Kubernetes习惯通过声明式(declaratively)的方式来管理应用。读者可以通过YAML 文件来描述希望应用程序如何运行与管理。将这些文件发送给Kubernetes,然后剩下的工作交给Kubernetes来完成就可以了。
但是到这里还没有结束。因为声明式的方式仅仅告诉Kubernetes应该如何运行并管理应用,除此之外,Kubernetes还会监控并保证应用在运行期间不会出现用户期望外的情况。当意外发生时,Kubernetes会尝试解决这些问题。
Kubernetes整体介绍就到这里,接下来请随本书一起深入了解其中细节。
一个Kubernetes集群由主节点(master)与工作节点(node)组成。这些节点都是Linux主机,可以运行在虚拟机(VM)、数据中心的物理机,或者公有云/私有云的实例上。
Kubernetes的主节点(master)是组成集群的控制平面的系统服务的集合。
一种最简单的方式是将所有的主节点服务(Service)运行在同一个主机上。但是这种方式只适用于实验或测试环境。在生产环境上,主节点的高可用部署是必需的。这也是为什么主流的云服务提供商都实现了自己的多主节点高可用性(Multi-master High Availability),并将其作为自身Kubernetes平台的一部分,比如Azure Kubernetes Service(AKS)、AWS Elastic Kubernetes Service(EKS)以及Google Kubernetes Engine(GKE)。
一般来说,建议使用3或5个副本来完成一个主节点高可用性部署方案。
接下来请跟随本书一起,快速了解构成主节点的各个服务间有什么不同。
API Server(API服务)是Kubernetes的中央车站。所有组件之间的通信,都需要通过API Server来完成。在接下来的章节中将会对这部分进行深入的介绍,但理解全部组件的通信都是通过API Server来完成这一点非常重要,这包括了系统内置组件以及外部用户组件。
API Server对外通过HTTPS的方式提供了RESTful风格的API接口,读者上传YAML配置文件也是通过这种接口实现的。这些YAML文件有时也被称作manifest文件,它们描述了用户希望应用在运行时达到的期望状态(desired state)。期望状态中包含但不限于如下内容:需要使用的容器镜像、希望对外提供的端口号,以及希望运行的Pod副本数量。
访问API Server的全部请求都必须经过授权与认证,一旦通过之后,YAML文件配置就会被认为是有效的,并被持久化到集群的存储中,最后部署到整个集群。
在整个控制层中,只有集群存储是有状态(stateful)的部分,它持久化地存储了整个集群的配置与状态。因此,这也是集群中的重要组件之一——没有集群存储,就没有集群。
通常集群存储底层会选用一种常见的分布式数据库etcd。因为这是整个集群的唯一存储源,用户需要运行3~5个etcd副本来保证存储的高可用性,并且需要有充分的手段来应对可能出现的异常情况。
在关于集群的可用性(availability)这一点上,etcd认为一致性比可用性更加重要。这意味着etcd在出现脑裂的情况时,会停止为集群提供更新能力,来保证存储数据的一致性。但是,就算etcd不可用,应用仍然可以在集群性持续运行,只不过无法更新任何内容而已。
对于所有分布式数据库来说,写操作的一致性都至关重要。例如,分布式数据库需要能够处理并发写操作来尝试通过不同的工作节点对相同的数据进行更新。etcd使用业界流行的RAFT一致性算法来解决这个问题。
controller管理器实现了全部的后台控制循环,完成对集群的监控并对事件作出响应。
controller管理器是controller的管理者(controller of controller),负责创建controller,并监控它们的执行。
一些控制循环包括:工作节点controller、终端controller,以及副本controller。对应的每个controller都在后台启动了独立的循环监听功能,负责监控API Server的变更。这样做的目的是保证集群的当前状态(current state)可以与期望状态(desired state)相匹配(接下来会用具体案例来解释与证明)。
每个控制循环实现上述功能的基础逻辑大致如下。
(1)获取期望状态。
(2)观察当前状态。
(3)判断两者间的差异。
(4)变更当前状态来消除差异点。
上面的逻辑是Kubernetes与声明式设计模式的关键所在。
每个控制循环都极其定制化,并且仅关心Kubernetes集群中与其相关的部分。感知系统的其他部分并调用这种复杂的事情我们是绝对不会尝试的,每个控制循环都只关心与自己相关的逻辑,剩下的部分会交给其他控制循环来处理。这就是如Kubernetes这样的分布式系统设计的关键点所在,也与UNIX设计哲学不谋而合:每个组件都专注做好一件事,复杂系统是通过多个专一职责的组件组合而构成的。
从整体上来看,调度器的职责就是通过监听API Server来启动新的工作任务,并将其分配到适合的且处于正常运行状态的节点中。为了完成这样的工作,调度器实现了复杂的逻辑,过滤掉不能运行指定任务的工作节点,并对过滤后的节点进行排序。排序系统非常复杂,在排序之后会选择分数最高的节点来运行指定的任务。
当确定了可以执行任务的具体节点之后,调度器会进行多种前置校验。这些前置校验包括:节点是否仍然存在、是否有affinity或者anti-affinity规则、任务所依赖的端口在当前工作节点是否可以访问、工作节点是否有足够的资源等。不满足任务执行条件的工作节点会被直接忽略,剩下的工作节点会依据下面的判定规则计算得分并排序,具体包括:工作节点上是否已经包含任务所需的镜像、剩余资源是否满足任务执行条件,以及正在执行多少任务。每条判定规则都有对应的得分,得分最高的工作节点会被选中,并执行相应任务。
如果调度器无法找到一个合适的工作节点,那么当前任务就无法被调度,并且会被标记为暂停状态。
调度器并不负责执行任务,只是为当前任务选择一个合适的节点运行。
如果用户的集群运行在诸如AWS、Azure、GCP、DO和IBM等类似的公有云平台上,则控制平面会启动一个云controller管理器(cloud controller manager)。云controller管理器负责集成底层的公有云服务,例如实例、负载均衡以及存储等。举一个例子,如果用户的应用需要一个面向互联网流量的负载均衡器,则云controller管理器负责提前在对应的公有云平台上创建好相应的负载均衡器。
Kubernetes主节点运行了集群上所有的控制平面服务。可以将其看作一个集群的大脑,负责集群内全部控制与调度的决策。在其背后,一个主节点由无数个负责特定功能的控制循环与服务组成,其中包括API Server、集群存储、controller管理器以及调度器。
API Server位于控制平面的最前端,所有的指令与通信均需要通过API Server来完成。默认情况下,API Server通过443端口对外提供RESTful风格的接口。
图2.3展示了Kubernetes主节点的全貌(控制平面)。
工作节点是Kubernetes集群中的工作者。从整体上看,工作节点主要负责如下3件事情。
1.监听API Server分派的新任务。
2.执行新分派的任务。
3.向控制平面回复任务执行的结果(通过API Server)。
如图2.4所示,工作节点的结构相比主节点要简单一些。
接下来看一下工作节点的3个主要功能。
Kubelet是每个工作节点上的核心部分,是Kubernetes中重要的代理端,并且在集群中的每个工作节点上都有部署。实际上,通常工作节点与Kubelet这两个术语基本上是等价的。
在一个新的工作节点加入集群之后,Kubelet就会被部署到新节点上。然后Kubelet负责将当前工作节点注册到集群当中,集群的资源池就会获取到当前工作节点的CPU、内存以及存储信息,并将工作节点加入当前资源池。
Kubelet的一个重要职责就是负责监听API Server新分配的任务。每当其监听到一个任务时,Kubelet就会负责执行该任务,并维护与控制平面之间的一个通信频道,准备将执行结果反馈回去。
如果Kuberlet无法运行指定任务,就会将这个信息反馈给控制平面,并由控制平面决定接下来要采取什么措施。例如,如果Kubelet无法执行一个任务,则其并不会负责寻找另外一个可执行任务的工作节点。Kubelet仅仅是将这个消息上报给控制平面,由控制平面决定接下来该如何做。
Kubelet需要一个容器运行时(container runtime)来执行依赖容器才能执行的任务,例如拉取镜像并启动或停止容器。
在早期的版本中,Kubernetes原生支持了少量容器运行时,例如Docker。而在最近的版本中,Kubernetes将其迁移到了一个叫作容器运行时接口(CRI)的模块当中。从整体上来看,CRI屏蔽了Kubernetes内部运行机制,并向第三方容器运行时提供了文档化接口来接入。
Kubernetes目前支持丰富的容器运行时。一个非常著名的例子就是cri-containerd。这是一个开源的、社区维护的项目,将CNCF运行时通过CRI接口接入Kubernetes。该项目得到了广泛的支持,在很多Kubernetes场景中已经替代Docker成为当前最流行的容器运行时。
注意:containerd(发音如“container-dee”)是基于Docker Engine剥离出来的容器管理与运行逻辑。该项目由Docker公司捐献给CNCF,并获得了大量的社区支持。同期也存在其他的符合CRI标准的容器运行时。
关于工作节点的最后一个知识点就是kube-proxy。kube-proxy运行在集群中的每个工作节点,负责本地集群网络。例如,kube-proxy保证了每个工作节点都可以获取到唯一的IP地址,并且实现了本地IPTABLE以及IPVS来保障Pod间的网络路由与负载均衡。
除种类丰富的控制平面与工作节点组件外,每个Kubernetes集群都有自己内部的DNS服务,这对于集群操作也是非常重要的。
集群DNS服务有一个静态IP地址,并且这个IP地址集群总每个Pod上都是硬编码的,这意味着每个容器以及Pod都能找到DNS服务。每个新服务都会自动注册到集群DNS服务上,这样所有集群中的组件都能根据名称找到相应的服务。一些其他的组件也会注册到集群DNS服务,例如Statefulset以及由Statefulset管理的独立Pod。
集群DNS是基于CoreDNS来实现的。
现在读者应该对主节点与工作节点的主要部分有了一个基础的了解,接下来请跟随本书一起换一个角度,看一下一个应用是如何打包并在Kubernetes上运行的。
一个应用想要在Kubernetes上运行,需要完成如下几步。
1.将应用按容器方式进行打包。
2.将应用封装到Pod中。
3.通过声明式manifest文件部署。
打包的详细过程如下:用户需要选择某种语言来编写一个应用程序,完成之后需要将应用构建到容器镜像当中并存放于某个私有仓库(Registry)。此时,已经完成了应用服务的容器化(containerized)。
接下来,用户需要定义一个可以运行容器化应用的Pod。抽象来说,Pod就是一层简单的封装,允许容器在Kubernetes集群上运行。在用户定义好Pod之后,就可以随时将其部署到集群上运行了。
在Kubernetes集群中可以运行一个Pod单例,但是通常情况下不建议这么做。推荐的方式是通过更上层的controller来完成。最常见的controller就是Deployment,它提供了可扩容、自愈与滚动升级等特性。读者只需要通过一个YAML文件就可以指定Deployment的配置信息,包括需要使用哪个镜像以及需要部署多少副本。
图2.5展示了应用如何被容器化(container),并以Pod方式运行,通过部署(Deployment) controller来进行管理。
在一个Deployment文件定义好之后,读者可以通过API Server来指定应用的期望状态(desired state)并在Kubernetes上运行。
接下来介绍一下期望状态的相关内容。
声明式模型(declarative modle)以及期望状态(desired state)是Kubernetes中非常核心的概念。
在Kubernetes中,声明式模型的工作方式如下所述。
1.在manifest文件中声明一个应用(微服务)期望达到的状态。
2.将manifest文件发送到API Server。
3.Kubernetes将manifest存储到集群存储,并作为应用的期望状态。
4.Kubernetes在集群中实现上述期望状态。
5.Kubernetes启动监控循环,保证应用的当前状态(current state)不会与期望状态出现差异。
接下来请读者跟随本书一起,深入了解上述步骤。
manifest文件是按照简版YAML格式进行编写的,用户通过manifest文件来告知Kubernetes集群自己希望应用运行的样子。这就是所谓的期望状态。其中包括:需要使用哪个镜像、有多少副本需要运行、哪个网络端口需要监听,以及如何执行更新。
在用户创建了manifest文件之后,需要将其发送到API Server。最常见的方式是通过kubectl命令行工具来完成这个操作。kubectl会将manifest文件通过HTTP POST请求发送到控制平面,通常HTTP服务使用的端口是443。
在请求经过认证以及授权后,Kubernetes会检查manifest文件,确定需要将该文件发送到哪个控制器(例如Deployment controller),并将其保存到集群存储当中,作为整个集群的期望状态(desired state)中的一部分。在上述工作都完成之后,就要在集群中执行相应的调度工作了。调度工作包括拉取镜像、启动容器、构建网络以及启动应用进程。
最终,Kubernetes通过后台的reconciliation(调谐)循环来持续监控集群状态。如果集群当前状态(current state)与期望状态(desired state)存在差异,则Kubernetes会执行必要的任务来解决对应的差异点,如图2.6所示。
理解本书当前强调的声明式模式与传统的命令式模式(imperative model)之间的区别是一件非常重要的事情。命令式模式是指用户需要指定一大串针对特定平台的命令来解决相应的问题。
但是关于声明式模式的介绍到此还未结束:当前系统可能出现变化或者出现某些问题。这意味着集群的当前状态(current state)与期望状态(desired state)不再一致。当这种情况发生时,Kubernetes会尝试采取相应措施来消除这种不一致的情况。
接下来通过一个例子来看一下具体情况。
声明式示例
假设读者有一个前端Web应用Pod,期望状态中需要运行10个副本。在其中某个工作节点运行的两个副本失败之后,当前状态(current state)就会减少到8个副本,但是期望状态(desired state)仍然是10个副本。这种情况会被调谐循环检测到,Kubernetes也会重新调度两个新的副本来保证当前状态副本数量重新恢复到10。
当读者尝试主动地调高或者调低副本数量的时候,上述流程也会被触发执行。读者甚至可以改变应用运行所需的镜像。比如,当前应用使用了v2.00版本的镜像,而读者希望将期望状态中的镜像版本调整到v2.01,Kubernetes会检测到这两者之间的差异,并会通过更新全部副本的镜像版本到期望状态(desired state)中的版本这种方式来实现该功能。
需要说明的一点是,与编写一长串命令来将每个副本更新到最新版本这种方式相比,读者现在只需要简单地告诉Kubernetes自己期望升级的新版本,剩下的大量工作由Kubernetes替读者来完成。
尽管一切看起来都非常简单,但这个功能确实很强大,并且是Kubernetes工作原理中很重要的一部分。读者在Kubernetes中提交了一个声明式的manifest文件,其中描述了读者希望应用所达到的运行状态。这个文件构成了应用期望状态的基础。Kubernetes控制平面记录下这个配置文件并会实现文件描述中的内容,同时还会在后台运行一个调谐循环来持续检查当前运行状态是否满足读者诉求。如果当前状态与期望状态相符,则皆大欢喜;但是如果存在差异,Kubernetes也会马上修复这些问题。
在VMware的世界中,调度的原子单位是虚拟机(VM);在Docker的世界中,调度的原子单位是容器;而在Kubernetes的世界中,调度的原子单位是Pod,如图2.7所示。
Kubernetes的确支持运行容器化应用。但是,用户无法直接在Kubernetes集群中运行一个容器,容器必须并且总是需要在Pod中才能运行。
首先需要介绍一下Pod这个术语的起源:在英语中,会将a group of whales(一群鲸鱼)称作a Pod of whales,Pod就是来源于此。因为Docker的Logo是鲸鱼,所以在Kubernetes中会将包含了一组容器的事物称作Pod。
一种最简单的方式就是,在每个Pod中只运行一个容器。当然,还有一种更高级的用法,在一个Pod中会运行一组容器。像这种多容器Pod(multi-container Pod)不在当前的讨论范围之内,不过可以先列举几种常见场景。
●服务网格(Service Mesh)。
●需要依赖helper容器来获取最新内容的Web容器。
●那些强依赖log清理工具的容器。
这其中最关键的地方即Pod是一种包含了一个或多个容器的结构。图2.8展示了一个多容器Pod。
整体来看,Pod是一个用于运行容器的有限制的环境。Pod本身并不会运行任何东西,只是作为一个承载容器的沙箱而存在。换一种说法,Pod就是为用户在宿主机操作系统中划出有限的一部分特定区域,构建一个网络栈,创建一组内核命名空间,并且在其中运行一个或者多个容器,这就是Pod。
如果在Pod中运行多个容器,那么多个容器间是共享相同的Pod环境的。共享环境中包括了IPC命名空间,共享的内存,共享的磁盘、网络以及其他资源等。举一个具体的例子,运行在相同Pod中的所有容器都有相同的IP地址(Pod的IP地址),如图2.9所示。
如果在同一个Pod中运行的两个容器之间需要通信(在Pod内部的容器间),那么就可以使用Pod提供的localhost接口来完成,具体如图2.10所示。
对于存在强绑定关系的多个容器,比如需要共享内存与存储,多容器Pod就是一个非常完美的选择。但是,如果容器间并不存在如此紧密的关系,则更好的方式是将容器封装到不同的Pod,通过网络以松耦合的方式来运行。这样可以在任务级别实现容器间的隔离,降低相互之间的影响。当然这样也会导致大量的未加密的网络流量产生。读者在使用时,最好考虑通过服务网格来完成Pod与应用服务间的加密。
Kubernetes中最小的调度单元也是Pod。如果读者需要扩容或缩容自己的应用,可以通过添加或删除Pod来实现。千万不要选择通过向一个已经存在的Pod中增加更多的容器这种方式来完成扩容。多容器Pod仅适用于那种两个的确是不同容器但又需要共享资源的场景。图2.11以Nginx为例,展示了使用Pod正确扩容的方式。
Pod的部署是一个原子操作。这意味着,只有当Pod中的所有容器都启动成功且处于运行状态时,Pod提供的服务才会被认为是可用的。对于部分启动的Pod,绝对不会响应服务请求。整个Pod要么全部启动成功,并加入服务;要么被认为启动失败。
一个Pod只会被唯一的工作节点调度。这一点对于多容器Pod来说也是一样的,一个多容器Pod中的全部容器都会运行在相同的工作节点上。
Pod的生命周期是有限的。Pod会被创建并运行,并且最终被销毁。如果Pod出现预期外的销毁,用户无须将其重新启动。因为Kubernetes会启动一个新的Pod来取代有问题的Pod。尽管新启动的Pod看起来跟原来的Pod完全一样,本质上却并不是同一个。这是一个有全新的ID与IP地址的Pod。
这种方式可能会对应用程序的设计思路产生影响。不要在设计程序的时候使其依赖特定的Pod,相反,需要使程序满足Pod特性,使其可以在某个Pod出现问题后,启动一个全新的Pod(有新的ID与IP地址)并无缝地取代原来Pod的位置。
大多数时间,用户通过更上层的控制器来完成Pod部署。上层的控制器包括Deployment、DaemonSet以及StatefulSet。
举例说明一下:Deployment是对Pod的更高一层的封装,除Pod之外,还提供了如扩缩容管理、不停机更新以及版本控制等其他特性。
除此之外,Deployment、DaemonSet以及StatefulSet还实现了自己的controller与监控循环,可以持续监控集群状态,并确保当前状态与期望状态相符。
在Kubernetes 1.2版本中Deployment就已经存在了,在1.9版本中正式发布(稳定版本)。在本书的后面还有更多的机会见到它。
在前面的内容中刚刚介绍了Pod是非常重要的,并且可能会出现故障并销毁。如果通过Deployment或者DaemonSet对Pod进行管理,出现故障的Pod会自动被替换。但是替换后的新Pod会拥有完全不同的IP地址。这种情况也会在水平扩/缩容时发生,扩容时会创建拥有新IP地址的Pod,缩容时会移除掉现有的Pod。这些都会引起IP地址变化(IP churn)。
这其中的关键点是Pod是不可靠的,这时就出现一个新的挑战:假设用户需要通过一个由多个Pod构成的微服务来完成视频渲染工作。如果这个时候应用的其他部分需要依赖渲染服务,但是由于Pod不可靠,又不能直接依赖Pod服务,这时候该怎么办呢?
此时需要正式介绍Service(服务)机制。Service为一组Pod提供了可靠且稳定的网络。
图2.12展示了上传这个微服务并通过Kubernetes中的Service机制来与渲染微服务进行交互的过程。Kubernetes Service提供了一个稳定的服务名称与IP地址,并且对于其下的两个Pod提供了请求级别的负载均衡机制。
展开介绍一下其中的细节。Service在Kubernetes API中是一个成熟且稳定的组件,就像Pod与Deployment一样。DNS名称、IP地址与端口共同组成了其前端。在其后端实现了对一组Pod间的动态负载均衡。同时,跟Pod一样,Service也实现了自我监控机制,可以自动更新,并持续提供稳定的网络终端。
如果对于Pod进行数量上的增加,则在Service中同样会生效。新的Pod会被无缝添加到Service并承担请求流量。已经终止的Pod会被平滑地从当前Service中移除,并不再处理请求流量。
这就是Service的职责:一个稳定的网络终端,提供了基组动态Pod集合的TCP以及UDP负载均衡能力。
因为Service作用于TCP以及UDP层,所以Service层并不具备应用层的智能,即无法提供应用层的主机与路径路由能力。因此,用户需要一个入口来解析HTTP请求并提供基于主机与路径的路由能力。
将Pod连接到Service
Service使用标签(label)与一个标签选择器(label selector)来决定应当将流量负载均衡到哪一个Pod集合。Service中维护了一个标签选择器(label selector),其中包含了一个Pod所需要处理的全部请求对应的标签。基于此,Service层才能将流量路由到对应的Pod。
图2.13展示了一个特定的服务配置:需要将流量路由到集群中的所有标记了如下标签的Pod。
●zone=prod。
●Env=be。
●ver=1.3。
当前图中所展示的Pod都具有这3种标签,Service会把流量均匀地分配到这些Pod之中。
图2.14展示了一个类似的场景。但是在图中右侧的增加了一个额外的Pod,这个Pod上面的标签与Service中标签选择器中的配置并不相符。这意味着服务不会将请求路由给这个新增的Pod。
关于Service还有最后一件事情。Service只会将流量路由到健康的Pod,这意味着如果Pod的健康检查失败,那么Pod就不会接收到任何流量。
以上就是关于Service的基础介绍。Service为不稳定的Pod集合提供了稳定的IP地址以及DNS名称。
本章主要对Kubernetes集群中的核心组件进行了介绍。
控制平面运行在主节点上。在其背后,还有几个系统服务,包括对集群提供了RESTful接口的API Server。主节点负责所有的部署与调度决策,并且对于生产环境来说,基于多主节点的HA方案是非常重要的。
工作节点上运行了用户的应用程序。每个工作节点上都运行了Kubelet这个服务,负责将当前工作节点注册到集群,并且通过API Server与集群进行交互。Kubelet通过监听API的方式来获取新任务,并维护相应的上报通道。工作节点上还有一个容器运行时,以及kube-proxy服务。容器运行时,比如Docker或者containerd,负责响应全部与容器相关的操作。kube-proxy负责节点上的网络功能。
除此之外,本章还介绍了Kubernetes的一些核心API组件,比如Pod、Deployment以及Service。Pod是执行构建的最小单元。Deployment在Pod基础上增加了自愈、水平扩缩容与更新能力。而Service提供了稳定的网络与负载均能能力。
现在基础部分已经介绍完成,接下来请随本书一起进一步了解其中的细节。