带你读《Kubernetes进阶实战》之一:Kubernetes系统基础-阿里云开发者社区

开发者社区> 华章出版社> 正文

带你读《Kubernetes进阶实战》之一:Kubernetes系统基础

简介: 本书几乎涵盖了应用Kubernetes系统的所有主流知识点,它甚至可以作为计划考取CKA认证的读者的配套参考图书。

Kubernetes核心技术系列
点击这里查看第二章:Kubernetes快速入门
点击这里查看第三章:资源管理基础

Kubernetes进阶实战 立.jpg


Kubernetes艺术
马永亮 著

前  言

为什么要写这本书

作为置身于IT技术领域多年的实践者和教育者,我们一直盼望着行业迎来这样一个时刻:异构的IT基础设施环境所造成的开发和部署系统应用纷繁复杂的局面终于迎来了终结者,开发人员无须再考虑复杂多样的运行环境下软件程序的移植问题,运维人员不用再手动解决运行环境中组件间的依赖关系等,从而让各自的核心职责都回归到开发和保证系统稳定运行本身。终于,以Docker为首的容器技术为此带来了基础保障,并在容器编排技术的支撑下尘埃落定,甚至连IT管理者心心念念多年的DevOps文化运动也借此找到了易于落地的实现方案。于是,系统运行割据多年的局面终于将走向天下一统。
尽管距Kubernetes 1.0的发布不过三四年的光景,但其如今的影响力在IT技术领域完全算得上空前绝后,目前,一众大小公司都在使用或正筹划使用这一IT技术发展史上可能最为成功的开源项目。Linux软件基金会的常务董事Jim Zemlin在Google Cloud Next 17大会上曾表示,Kubernetes是“云时代的Linux”。的确,Kubernetes应该是开源世界有史以来迭代最快的项目,而且在几乎所有需要采用容器技术的场景里成为占统治地位的解决方案,其发展速度恐怕也仅有Linux内核项目可堪匹敌。2018年3月,Kubernetes成为CNCF旗下“毕业”的第一个项目,并荣获2018年 OSCON最具影响力奖项。
目前,Kubernetes保持着每年发布四个重要版本的节奏,版本的每次更新都会引入数个新特性。这种快速迭代的机制在为用户不断带来惊喜的同时,也给他们在学习和使用上造成了一些困扰:相关领域的可参考书籍仍不丰富,互联网上可以得到的众多文档并非源于同一个版本,以及厘清脉络拼凑成完整的知识框架所需的时间成本较大。因此,我在课程以及直接或间接参与生产或测试环境的交付之余便萌生了撰写一本Kubernetes入门、进阶与实战的书籍的想法,将自己学习和使用的经验总结、沉淀并分享给更多有此需求的技术同行,帮助大家快速找到入门路径,降低时间成本,并迅速投入测试和生产之用。
的确,在写作过程中,Kubernetes这种快速迭代的机制,以及每每引入的新特性,在小惊喜之余带给笔者更多的却是真真切切的梦魇般的恐惧感:在一年多的写作时间里,许多章节几易其稿,却也依然无法确保能够涵盖即将成为核心功能的特性,于是沮丧感几度如影随形,直到自我安慰着“基础的核心特性基本不会发生大的变动,只要能帮助读者弄清楚Kubernetes系统的基础架构及核心工作逻辑就算工夫没有白费”之后方才释然。于是便有了这本力图尽量多地包罗Kubernetes系统目前主流特性及实践路径的入门和进阶之书、工具之书。

本书特色

本书致力于帮助容器编排技术的初级和中级用户循序渐进地理解与使用Kubernetes系统,因此本书的编写充分考虑到初学者进入新知识领域时的茫然,采用由浅入深、提纲挈领、再由点到面的方式讲解每一个知识细节。对于每个知识点,不仅介绍了其概念和用法,还分析了为什么要有这个概念,实现的方式是什么,背后的逻辑为何,等等,使读者不仅能知其然,还能知其所以然。
本书不仅要带领读者入门,更是一本可以随时动手加以验证的实践手册,而且对于部分重要的内容还会专门一步步地给出具体的实操案例,帮助读者在实践中升华对概念的理解。本书几乎涵盖了应用Kubernetes系统的所有主流知识点,它甚至可以作为计划考取CKA认证的读者的配套参考图书。

读者对象

云计算工程师
运维工程师
系统开发工程师
程序架构师
计划考取CKA认证的人员
其他对容器编排感兴趣的人员

如何阅读本书

阅读使用本书之前,读者需要具备Docker容器技术的基础使用能力。本书逻辑上共分为五大部分,15章。
第一部分(第1~2章),介绍Kubernetes系统的基础概念及其基本应用。
第1章介绍容器编排系统出现的背景,以及Kubernetes系统的功能、特性、核心概念、系统组件及应用模型。
第2章讲解Kubernetes的核心对象,以及直接使用命令管理资源对象的快速入门技巧。
第二部分(第3~6章),介绍核心资源类型及其应用。
第3章介绍资源管理模型、陈述式与声明式资源管理接口,并通过命令对比说明两种操作方式的不同之处。
第4章介绍Pod资源的常用配置、生命周期、存储状态和就绪状态检测,以及计算资源的需求及限制等。
第5章介绍Pod控制器资源类型,重点讲解了控制无状态应用的ReplicaSet、Deployment、DaemonSet控制器,并介绍了Job和CronJob控制器。
第6章介绍Service和Ingress资源类型,涵盖Service类型、功用及其实现,以及Ingress控制器、Ingress资源的种类及其实现,并通过案例详细说明了Ingress资源的具体使用方式。
第三部分(第7~9章),介绍存储卷及StatefulSet控制器。
第7章主要介绍存储卷类型及常见存储卷的使用方式、PV和PVC出现的原因及应用,以及存储类资源的应用和存储卷的动态供给。
第8章介绍使用一等资源类型Conf?igMap和Secret为容器应用提供配置及敏感信息的方式。
第9章主要介绍有状态应用的Pod控制器资源StatefulSet,包括基础应用、动态扩缩容及更新机制等。
第四部分(第10~11章),介绍安全相关的话题,主要涉及认证、授权、准入控制、网络模型与网络策略。
第10章重点讲解认证方式、Service Account和TLS认证、授权插件类型及RBAC,并于章节的最后介绍LimitRanger、ResourceQuota和PodSecurityPolicy三种类型的准入控制器及相关的资源类型。
第11章主要介绍网络插件基础及f?lannel的三种后端实现与应用、借助Canal插件实现网络策略的方式,以及Calico网络插件的基础使用。
第五部分(第12~15章),介绍Kubernetes系统的高级话题。
第12章介绍Pod资源的调度策略及高级调度方式的应用,包括节点亲和、Pod资源亲和以及基于污点和容忍度的调度。
第13章介绍系统资源的扩展方式,包括自定义资源类型、自定义资源对象、自定义API及控制器、Master节点的高可用、基于Kubernetes的PaaS系统等话题。
第14章介绍资源指标、自定义指标、监控系统及HPA控制器的应用。
第15章介绍简化应用管理的工具Helm,并基于Helm介绍如何为Kubernetes系统提供统一的日志收集与管理工具栈EFK。

精彩导读

第1章:Kubernetes系统基础

近十几年来,IT领域新技术、新概念层出不穷,例如DevOps、微服务(Microservice)、容器(Container)、云计算(Cloud Computing)和区块链(Blockchain)等,直有“乱花渐欲迷人眼”之势。另外,出于业务的需要,IT应用模型也在不断地变革,例如,开发模式从瀑布式(Waterfall)到敏捷(Agile)再到精益(Lean),甚至是与QA和Operations融合的DevOps,应用程序架构从单体(monolithic)模型到分层模型再到微服务,部署及打包方式从面向物理机到虚拟机再到容器,应用程序的基础架构从自建机房到托管再到云计算,等等,这些变革使得IT技术应用的效率大大提升,同时却以更低的成本交付更高质量的产品。
尤其是以Docker为代表的容器技术的出现,终结了DevOps中交付和部署环节因环境、配置及程序本身的不同而造成的动辄几种甚至十几种部署配置的困境,将它们统一在容器镜像(image)之上。如今,越来越多的企业或组织开始选择以镜像文件作为交付载体。容器镜像之内直接包含了应用程序及其依赖的系统环境、库、基础程序等,从而能够在容器引擎上直接运行。于是,IT运维工程师(operator)无须关注开发应用程序的编程语言、环境配置等,甚至连业务逻辑本身也不必过多关注,而只需要掌握容器管理的单一工具链即可。
部署的复杂度虽然降低了,但以容器格式运行的应用程序间的协同却成了一个新的亟待解决的问题,这种需求在微服务架构中表现得尤为明显。结果,以Kubernetes为代表的容器编排系统应需而生。

1.1 容器技术概述

容器是一种轻量级、可移植、自包含的软件打包技术,它使得应用程序可以在几乎任何地方以相同的方式运行。软件开发工程师在自己笔记本上创建并测试完成的容器,无须任何修改就能够在生产系统的虚拟机、物理机或云主机上运行。
容器由应用程序本身和它的环境依赖(库和其他应用程序)两部分组成,并在宿主机(Host)操作系统的用户空间中运行,但与操作系统的其他进程互相隔离,它们的实现机制有别于诸如VMWare、KVM和Xen等实现方案的传统虚拟化技术。容器与虚拟机的对比关系如图1-1所示。

1.png


图1-1 容器和虚拟机对比


由于同一个宿主机上的所有容器都共享其底层操作系统(内核空间),这就使得容器在体积上要比传统的虚拟机小得多。另外,启动容器无须启动整个操作系统,所以容器部署和启动的速度更快,开销更小,也更容易迁移。事实上,容器赋予了应用程序超强的可移植能力。

1.1.1 容器技术的功用

IT系统在架构上已经迭代数十年之久,其环境复杂程度日趋加重,直有积重难返之势。现如今,应用程序开发人员通常需要同时使用多种服务构建,并要架构IT信息系统,涉及MQ、Cache和DB等,且很可能要部署到不同的环境中,如物理服务器、虚拟服务器、私有云或公有云之上。这些不同的主机或许还有着不同的系统环境,如RHEL、Debian或SUSE等Linux发行版,甚至是UNIX、Windows等。
结果,一方面应用程序包含了多种服务,每种服务均可能存在依赖的库和软件包;另一方面存在多种部署环境,而服务在运行时又可能需要动态迁移到不同的环境中。于是,各种服务和环境通过排列组合产生了一个大部署矩阵。应用程序开发工程师在编写代码时需要考虑不同的运行环境,而运维工程师则需要为不同的服务和平台配置环境。对他们双方来说,这都必将是一项困难而艰巨的任务。
幸运的是,货运系统的集装箱机制为解决这个难题提供了有效的借鉴方案。Docker正是将集装箱思想运用到软件打包上,为代码提供了一个基于容器的标准化运输系统。Docker可以将几乎任何应用程序及其依赖的运行环境都打包成一个轻量级、可移植、自包含的容器,并能够运行于支持Docker容器引擎的所有操作系统之上。简言之,容器的优势主要表现在以下两个方面。

  • 应用程序开发工程师:“一次构建,到处运行”(Build Once,Run Anywhere)。容器意味着环境隔离和可重复性,开发人员只需为应用创建一个运行环境,并将其打包成容器便可在各种部署环境上运行,并与它所在的宿主机环境隔离。
  • 运维工程师:“一次配置,运行所有”(Conf?igure Once,Run Anything)。一旦配置好标准的容器运行时环境,服务器就可以运行任何容器,这使得运维人员的工作变得更高效、一致和可重复。容器消除了开发、测试、生产环境的不一致性。

1.1.2 容器简史

容器技术的概念最初出现在2000年,当时称为FreeBSD jail,这种技术可将FreeBSD系统分区为多个子系统(也称为Jail)。2001年,通过Jacques Gélinas的VServer项目,隔离环境的实施理念进入了Linux领域。
Jail的目的是让进程在经过修改的chroot环境中创建,而不会脱离和影响整个系统—chroot环境对文件系统、网络和用户的访问都实现了虚拟化。然而,Jail在实施方面存在着不少的局限性,当它与Namespaces和CGroups等技术结合在一起之后,才让这种隔离方法从构想变为了现实。后来,Linux容器项目(LXC)又为其添加了一些用户常用的工具、模板、库和语言绑定,从而较好地改善了用户使用容器技术时的体验。
Docker在LXC项目的基础上,从文件系统、网络互联到进程隔离等方面对容器技术进行了进一步的封装,极大地简化了容器的创建和维护过程,从而促进了容器技术的大流行。Docker最初是由dotCloud公司创始人Solomon Hykes在法国期间发起的一个公司内部项目,并于2013年3月以Apache 2.0授权协议开源,其项目代码托管于GitHub之上。虽然其最初的实现是基于LXC项目的,但Docker在后来的0.7版本转为使用自行开发的libcontainer容器引擎,而1.11版本又将其换作了runC和containerd。
在2017年4月举行的DockerCon上,Docker公司将GitHub上原本隶属于Docker组织的Docker项目直接转移到了一个新的名为Moby的组织下,并将其重命名为Moby项目。

1.1.3 Docker的功能限制

Docker本身非常适合用于管理单个容器,不过,一旦开始使用越来越多的容器封装和运行应用程序,必将会导致其管理和编排变得越来越困难。最终,用户不得不对容器实施分组,以便跨所有容器提供网络、安全、监控等服务。于是,以Kubernetes为代表的容器编排系统应运而生。
真正的生产型应用会涉及多个容器,这些容器必须跨多个服务器主机进行部署。Kubernetes可以提供所需的编排和管理功能,以便用户针对这些工作负载轻松完成大规模容器部署。而且,借助于Kubernetes的编排功能,用户可以构建出跨多个容器的应用服务,并且可以实现跨集群调度、扩展容器,以及长期持续管理这些容器的健康状况等。使用中,Kubernetes还需要与网络、存储、安全性、监控及其他服务进行整合,以提供全面的容器基础架构,如图1-2所示。

2.png
图1-2 容器与容器编排(来源:RedHat Inc.)


Kubernetes利用容器的扩缩容机制解决了许多常见的问题,它将容器归类到一起,形成“容器集”(Pod),为分组的容器增加了一个抽象层,用于帮助用户调度工作负载(workload),并为这些容器提供所需的联网和存储等服务。Kubernetes的其他部分可帮助用户在这些Pod之间达成负载均衡,同时确保运行正确数量的容器,以充分支持实际的工作负载。

1.2 Kubernetes概述

尽管公开面世不过短短数年时间,Kubernetes业已成为容器编排领域事实上的标准,其近一两年的发展状态也在不断地验证着Urs H?lzle曾经的断言:无论是公有云、私有云抑或混合云,Kubernetes都将作为一个为任何应用、任何环境提供的容器管理框架而无处不在。

1.2.1 Kubernetes简史

Kubernetes(来自希腊语,意为“舵手”或“飞行员”)由Joe Beda、Brendan Burns和Craig McLuckie创立,而后Google的其他几位工程师,包括Brian Grant和Tim Hockin等加盟共同研发,并由Google在2014年首次对外宣布。Kubernetes的开发和设计都深受Google内部系统Borg的影响,事实上,它的许多顶级贡献者之前也是Borg系统的开发者。
Borg是Google内部使用的大规模集群管理系统,久负盛名。它建构于容器技术之上,目的是实现资源管理的自动化,以及跨多个数据中心的资源利用率最大化。2015年4月,Borg论文《Large-scale cluster management at Google with Borg》伴随Kubernetes的高调宣传被Google首次公开,人们终于有缘得窥其全貌。
事实上,正是由于诞生于容器世家Google,并站在Borg这个巨人的肩膀之上,充分受益于Borg过去十数年间积累的经验和教训,Kubernetes甫一面世就立即广受关注和青睐,并迅速称霸了容器编排技术领域。很多人将Kubernetes视为Borg系统的一个开源实现版本,在Google内部,Kubernetes的原始代号曾经是Serven of Nine,即星际迷航中友好的“Borg”角色,它标识中的舵轮有七个轮辐就是对该项目代号的致意,如图1-3所示。

3.png


Kubernetes v1.0于2015年7月21日发布,紧随其后,Google与Linux基金会合作组建了Cloud Native Computing Foundation(云原生计算基金会,简称为CNCF),并将Kubernetes作为种子技术予以提供。这之后,Kubernetes进入了版本快速迭代期,从此不断地融入着新功能,如Federation、Network Policy API、RBAC、CRD和CSI,等等,并增加了对Windows系统的支持。
2017年可谓是容器生态发展史上具有里程碑意义的一年。这一年,AWS、Azure和Alibaba Cloud都相继在其原有容器服务上新增了对Kubernetes的支持,而Docker官方也在2017年10月宣布同时支持Swarm和Kubernetes编排系统。这一年,RKT容器派系的CoreOS舍弃掉自己的调度工具Fleet,将其商用平台Tectonic的重心转移至Kubernetes。这一年,Mesos也于9月宣布了对Kubernetes的支持,其平台用户可以安装、扩展和升级多个生产级的Kubernetes集群。这一年,Rancher Labs推出了其2.0版本的容器管理平台并宣布all-in Kubernetes,放弃了其内置多年的容器编排系统Cattle。类似的故事依然在进行,并且必将在一个时期内持续上演。

1.2.2 Kubernetes特性

Kubernetes是一种用于在一组主机上运行和协同容器化应用程序的系统,旨在提供可预测性、可扩展性与高可用性的方法来完全管理容器化应用程序和服务的生命周期的平台。用户可以定义应用程序的运行方式,以及与其他应用程序或外部世界交互的途径,并能实现服务的扩容和缩容,执行平滑滚动更新,以及在不同版本的应用程序之间调度流量以测试功能或回滚有问题的部署。Kubernetes提供了接口和可组合的平台原语,使得用户能够以高度的灵活性和可靠性定义及管理应用程序。简单总结起来,它具有以下几个重要特性。
(1)自动装箱
建构于容器之上,基于资源依赖及其他约束自动完成容器部署且不影响其可用性,并通过调度机制混合关键型应用和非关键型应用的工作负载于同一节点以提升资源利用率。
(2)自我修复(自愈)
支持容器故障后自动重启、节点故障后重新调度容器,以及其他可用节点、健康状态检查失败后关闭容器并重新创建等自我修复机制。
(3)水平扩展
支持通过简单命令或UI手动水平扩展,以及基于CPU等资源负载率的自动水平扩展机制。
(4)服务发现和负载均衡
Kubernetes通过其附加组件之一的KubeDNS(或CoreDNS)为系统内置了服务发现功能,它会为每个Service配置DNS名称,并允许集群内的客户端直接使用此名称发出访问请求,而Service则通过iptables或ipvs内建了负载均衡机制。
(5)自动发布和回滚
Kubernetes支持“灰度”更新应用程序或其配置信息,它会监控更新过程中应用程序的健康状态,以确保它不会在同一时刻杀掉所有实例,而此过程中一旦有故障发生,就会立即自动执行回滚操作。
(6)密钥和配置管理
Kubernetes的Conf?igMap实现了配置数据与Docker镜像解耦,需要时,仅对配置做出变更而无须重新构建Docker镜像,这为应用开发部署带来了很大的灵活性。此外,对于应用所依赖的一些敏感数据,如用户名和密码、令牌、密钥等信息,Kubernetes专门提供了Secret对象为其解耦,既便利了应用的快速开发和交付,又提供了一定程度上的安全保障。
(7)存储编排
Kubernetes支持Pod对象按需自动挂载不同类型的存储系统,这包括节点本地存储、公有云服务商的云存储(如AWS和GCP等),以及网络存储系统(例如,NFS、iSCSI、GlusterFS、Ceph、Cinder和Flocker等)。
(8)批量处理执行
除了服务型应用,Kubernetes还支持批处理作业及CI(持续集成),如果需要,一样可以实现容器故障后恢复。

1.2.3 Kubernetes概念和术语

Kubernetes使用共享网络将多个物理机或虚拟机汇集到一个集群中,在各服务器之间进行通信,该集群是配置Kubernetes的所有组件、功能和工作负载的物理平台。集群中一台服务器(或高可用部署中的一组服务器)用作Master,负责管理整个集群,余下的其他机器用作Worker Node(早期版本中也称为Minion),它们是使用本地和外部资源接收和运行工作负载的服务器,如图1-4所示。集群中的这些主机可以是物理服务器,也可以是虚拟机(包括IaaS云端的VPS)。

4.png
图1-4:Kubernetes


(1)Master
Master是集群的网关和中枢,负责诸如为用户和客户端暴露API、跟踪其他服务器的健康状态、以最优方式调度工作负载,以及编排其他组件之间的通信等任务,它是用户或客户端与集群之间的核心联络点,并负责Kubernetes系统的大多数集中式管控逻辑。单个Master节点即可完成其所有的功能,但出于冗余及负载均衡等目的,生产环境中通常需要协同部署多个此类主机。Master节点类似于蜂群中的蜂王。
(2)Node
Node是Kubernetes集群的工作节点,负责接收来自Master的工作指令并根据指令相应地创建或销毁Pod对象,以及调整网络规则以合理地路由和转发流量等。理论上讲,Node可以是任何形式的计算设备,不过Master会统一将其抽象为Node对象进行管理。Node类似于蜂群中的工蜂,生产环境中,它们通常数量众多。
Kubernetes将所有Node的资源集结于一处形成一台更加强大的“服务器”,如图1-5所示,在用户将应用部署于其上时,Master会使用调度算法将其自动指派至某个特定的Node运行。在Node加入集群或从集群中移除时,Master也会按需重新编排影响到的Pod(容器)。于是,用户无须关心其应用究竟运行于何处。

5.png
图1-5 Node组成的虚拟资源池


从抽象的视角来讲,Kubernetes还有着众多的组件来支撑其内部的业务逻辑,包括运行应用、应用编排、服务暴露、应用恢复等,它们在Kubernetes中被抽象为Pod、Service、Controller等资源类型,下面列出了几个较为常用的资源抽象。
(1)Pod
Kubernetes并不直接运行容器,而是使用一个抽象的资源对象来封装一个或者多个容器,这个抽象即为Pod,它也是Kubernetes的最小调度单元。同一Pod中的容器共享网络名称空间和存储资源,这些容器可经由本地回环节口lo直接通信,但彼此之间又在Mount、User及PID等名称空间上保持了隔离。尽管Pod中可以包含多个容器,但是作为最小调度单元,它应该尽可能地保持“小”,即通常只应该包含一个主容器,以及必要的辅助型容器(sidecar),如图1-6所示。

6.png
图1-6:Pod


(2)资源标签
标签(Label)是将资源进行分类的标识符,资源标签其实就是一个键值型(key/values)数据。标签旨在指定对象(如Pod等)辨识性的属性,这些属性仅对用户存在特定的意义,对Kubernetes集群来说并不直接表达核心系统语义。标签可以在对象创建时附加其上,并能够在创建后的任意时间进行添加和修改。一个对象可以拥有多个标签,一个标签也可以附加于多个对象(通常是同一类对象)之上,如图1-7所示。

7.png
图1-7 Kubernetes资源标签


(3)标签选择器
标签选择器(Selector)全称为“Label Selector”,它是一种根据Label来过滤符合条件的资源对象的机制。例如,将附有标签“role: backend”的所有Pod对象挑选出来归为一组就是标签选择器的一种应用,如图1-8所示。用户通常使用标签对资源对象进行分类,而后使用标签选择器挑选出它们,例如将其创建为某Service的端点。

8.png
图1-8 标签选择器


(4)Pod控制器
尽管Pod是Kubernetes的最小调度单元,但用户通常并不会直接部署及管理Pod对象,而是要借助于另一类抽象—控制器(Controller)对其进行管理。用于工作负载的控制器是一种管理Pod生命周期的资源抽象,它们是Kubernetes上的一类对象,而非单个资源对象,包括ReplicationController、ReplicaSet、Deployment、StatefulSet、Job等。以图1-9中所示的Deployment控制器为例,它负责确保指定的Pod对象的副本数量精确符合定义,否则“多退少补”。使用控制器之后就不再需要手动管理Pod对象了,用户只需要声明应用的期望状态,控制器就会自动对其进行进程管理。

9.png
图1-9 Deployment控制器示意图


(5)服务资源(Service)
Service是建立在一组Pod对象之上的资源抽象,它通过标签选择器选定一组Pod对象,并为这组Pod对象定义一个统一的固定访问入口(通常是一个IP地址),若Kubernetes集群存在DNS附件,它就会在Service创建时为其自动配置一个DNS名称以便客户端进行服务发现。到达Service IP的请求将被负载均衡至其后的端点—各个Pod对象之上,因此Service从本质上来讲是一个四层代理服务。另外,Service还可以将集群外部流量引入到集群中来。
(6)存储卷
存储卷(Volume)是独立于容器文件系统之外的存储空间,常用于扩展容器的存储空间并为它提供持久存储能力。Kubernetes集群上的存储卷大体可分为临时卷、本地卷和网络卷。临时卷和本地卷都位于Node本地,一旦Pod被调度至其他Node,此种类型的存储卷将无法访问到,因此临时卷和本地卷通常用于数据缓存,持久化的数据则需要放置于持久卷(persistent volume)之上。
(7)Name和Namespace
名称(Name)是Kubernetes集群中资源对象的标识符,它们的作用域通常是名称空间(Namespace),因此名称空间是名称的额外的限定机制。在同一个名称空间中,同一类型资源对象的名称必须具有唯一性。名称空间通常用于实现租户或项目的资源隔离,从而形成逻辑分组,如图1-10所示。创建的Pod和Service等资源对象都属于名称空间级别,未指定时,它们都属于默认的名称空间“default”。

10.png
图1-10 名称空间


(8)Annotation
Annotation(注解)是另一种附加在对象之上的键值类型的数据,但它拥有更大的数据容量。Annotation常用于将各种非标识型元数据(metadata)附加到对象上,但它不能用于标识和选择对象,通常也不会被Kubernetes直接使用,其主要目的是方便工具或用户的阅读及查找等。
(9)Ingress
Kubernetes将Pod对象和外部网络环境进行了隔离,Pod和Service等对象间的通信都使用其内部专用地址进行,如若需要开放某些Pod对象提供给外部用户访问,则需要为其请求流量打开一个通往Kubernetes集群内部的通道,除了Service之外,Ingress也是这类通道的实现方式之一。

1.3 Kubernetes集群组件

一个典型的Kubernetes集群由多个工作节点(worker node)和一个集群控制平面(control plane,即Master),以及一个集群状态存储系统(etcd)组成。其中Master节点负责整个集群的管理工作,为集群提供管理接口,并监控和编排集群中的各个工作节点。各节点负责以Pod的形式运行容器,因此,各节点需要事先配置好容器运行依赖到的所有服务和资源,如容器运行时环境等。Kubernetes的系统架构如图1-11所示。
Master节点主要由apiserver、controller-manager和scheduler三个组件,以及一个用于集群状态存储的etcd存储服务组成,而每个Node节点则主要包含kubelet、kube-proxy及容器引擎(Docker是最为常用的实现)等组件。此外,完整的集群服务还依赖于一些附加组件,如KubeDNS等。

1.3.1 Master组件

Kubernetes的集群控制平面由多个组件组成,这些组件可统一运行于单一Master节点,也可以以多副本的方式同时运行于多个节点,以为Master提供高可用功能,甚至还可以运行于Kubernetes集群自身之上。Master主要包含以下几个组件。

11.png
图1-11 Kubernetes系统组件


(1)API Server
API Server负责输出RESTful风格的Kubernetes API,它是发往集群的所有REST操作命令的接入点,并负责接收、校验并响应所有的REST请求,结果状态被持久存储于etcd中。因此,API Server是整个集群的网关。
(2)集群状态存储(Cluster State Store)
Kubernetes集群的所有状态信息都需要持久存储于存储系统etcd中,不过,etcd是由CoreOS基于Raft协议开发的分布式键值存储,可用于服务发现、共享配置以及一致性保障(如数据库主节点选择、分布式锁等)。因此,etcd是独立的服务组件,并不隶属于Kubernetes集群自身。生产环境中应该以etcd集群的方式运行以确保其服务可用性。
etcd不仅能够提供键值数据存储,而且还为其提供了监听(watch)机制,用于监听和推送变更。Kubernetes集群系统中,etcd中的键值发生变化时会通知到API Server,并由其通过watch API向客户端输出。基于watch机制,Kubernetes集群的各组件实现了高效协同。
(3)控制器管理器(Controller Manager)
Kubernetes中,集群级别的大多数功能都是由几个被称为控制器的进程执行实现的,这几个进程被集成于kube-controller-manager守护进程中。由控制器完成的功能主要包括生命周期功能和API业务逻辑,具体如下。
  • 生命周期功能:包括Namespace创建和生命周期、Event垃圾回收、Pod终止相关的垃圾回收、级联垃圾回收及Node垃圾回收等。
  • API业务逻辑:例如,由ReplicaSet执行的Pod扩展等。
    (4)调度器(Scheduler)

Kubernetes是用于部署和管理大规模容器应用的平台,根据集群规模的不同,其托管运行的容器很可能会数以千计甚至更多。API Server确认Pod对象的创建请求之后,便需要由Scheduler根据集群内各节点的可用资源状态,以及要运行的容器的资源需求做出调度决策,其工作逻辑如图1-12所示。另外,Kubernetes还支持用户自定义调度器。

12.png
图1-12 Kubernetes调度器

1.3.2 Node组件

Node负责提供运行容器的各种依赖环境,并接受Master的管理。每个Node主要由以下几个组件构成。
(1)Node的核心代理程序kubelet
kubelet是运行于工作节点之上的守护进程,它从API Server接收关于Pod对象的配置信息并确保它们处于期望的状态(desired state,后文不加区别地称之为“目标状态”)。kubelet会在API Server上注册当前工作节点,定期向Master汇报节点资源使用情况,并通过cAdvisor监控容器和节点的资源占用状况。
(2)容器运行时环境
每个Node都要提供一个容器运行时(Container Runtime)环境,它负责下载镜像并运行容器。kubelet并未固定链接至某容器运行时环境,而是以插件的方式载入配置的容器环境。这种方式清晰地定义了各组件的边界。目前,Kubernetes支持的容器运行环境至少包括Docker、RKT、cri-o和Fraki等。
(3)kube-proxy
每个工作节点都需要运行一个kube-proxy守护进程,它能够按需为Service资源对象生成iptables或ipvs规则,从而捕获访问当前Service的ClusterIP的流量并将其转发至正确的后端Pod对象。

1.3.3 核心附件

Kubernetes集群还依赖于一组称为“附件”(add-ons)的组件以提供完整的功能,它们通常是由第三方提供的特定应用程序,且托管运行于Kubernetes集群之上,如图1-11所示。下面列出的几个附件各自为集群从不同角度引用了所需的核心功能。

  • KubeDNS:在Kubernetes集群中调度运行提供DNS服务的Pod,同一集群中的其他Pod可使用此DNS服务解决主机名。Kubernetes自1.11版本开始默认使用CoreDNS项目为集群提供服务注册和服务发现的动态名称解析服务,之前的版本中用到的是kube-dns项目,而SkyDNS则是更早一代的项目。
  • Kubernetes Dashboard:Kubernetes集群的全部功能都要基于Web的UI,来管理集群中的应用甚至是集群自身。
  • Heapster:容器和节点的性能监控与分析系统,它收集并解析多种指标数据,如资源利用率、生命周期事件等。新版本的Kubernetes中,其功能会逐渐由Prometheus结合其他组件所取代。
  • Ingress Controller:Service是一种工作于传统层的负载均衡器,而Ingress是在应用层实现的HTTP(s)负载均衡机制。不过,Ingress资源自身并不能进行“流量穿透”,它仅是一组路由规则的集合,这些规则需要通过Ingress控制器(Ingress Controller)发挥作用。目前,此类的可用项目有Nginx、Traef?ik、Envoy及HAProxy等。

1.4 Kubernetes网络模型基础

云计算的核心是虚拟化技术,网络虚拟化技术又是其最重要的组成部分,用于在物理网络上虚拟多个相互隔离的虚拟网络,实现网络资源切片,提高网络资源利用率,实现弹性化网络。Kubernetes作为容器云技术栈中的容器编排组件,必然需要在多租户(名称空间)的基础上实现弹性网络管理,这也是“基础设施即代码”的要求之一。

1.4.1 网络模型概述

Kubernetes的网络中主要存在四种类型的通信:同一Pod内的容器间通信、各Pod彼此之间的通信、Pod与Service间的通信,以及集群外部的流量同Service之间的通信。Kubernetes为Pod和Service资源对象分别使用了各自的专用网络,Pod网络由Kubernetes的网络插件配置实现,而Service的网络则由Kubernetes集群予以指定。为了提供更灵活的解决方式,Kubernetes的网络模型需要借助于外部插件实现,它要求任何实现机制都必须满足以下需求。
所有Pod间均可不经NAT机制而直接通信。
所有节点均可不经NAT机制而直接与所有容器通信。
容器自己使用的IP也是其他容器或节点直接看到的地址。换句话讲,所有Pod对象都位于同一平面网络中,而且可以使用Pod自身的地址直接通信。
Kubernetes使用的网络插件必须能为Pod提供满足以上要求的网络,它需要为每个Pod配置至少一个特定的地址,即Pod IP。Pod IP地址实际存在于某个网卡(可以是虚拟设备)上,而Service的地址却是一个虚拟IP地址,没有任何网络接口配置此地址,它由kube-proxy借助iptables规则或ipvs规则重新定向到本地端口,再将其调度至后端Pod对象。Service的IP地址是集群提供服务的接口,也称为Cluster IP。
Pod网络及其IP由Kubernetes的网络插件负责配置和管理,具体使用的网络地址可在管理配置网络插件时指定,如10.244.0.0/16网络。而Cluster网络和IP则是由Kubernetes集群负责配置和管理,如10.96.0.0/12网络。
总结起来,Kubernetes集群至少应该包含三个网络,如图1-13中的网络环境所示。一个是各主机(Master、Node和etcd等)自身所属的网络,其地址配置于主机的网络接口,用于各主机之间的通信,例如,Master与各Node之间的通信。此地址配置于Kubernetes集群构建之前,它并不能由Kubernetes管理,管理员需要于集群构建之前自行确定其地址配置及管理方式。第二个是Kubernetes集群上专用于Pod资源对象的网络,它是一个虚拟网络,用于为各Pod对象设定IP地址等网络参数,其地址配置于Pod中容器的网络接口之上。Pod网络需要借助kubenet插件或CNI插件实现,该插件可独立部署于Kubernetes集群之外,亦可托管于Kubernetes之上,它需要在构建Kubernetes集群时由管理员进行定义,而后在创建Pod对象时由其自动完成各网络参数的动态配置。第三个是专用于Service资源对象的网络,它也是一个虚拟网络,用于为Kubernetes集群之中的Service配置IP地址,但此地址并不配置于任何主机或容器的网络接口之上,而是通过Node之上的kube-proxy配置为iptables或ipvs规则,从而将发往此地址的所有流量调度至其后端的各Pod对象之上。Service网络在Kubernetes集群创建时予以指定,而各Service的地址则在用户创建Service时予以动态配置。

13.png
图1-13 Kubernetes网络环境


CNI是指容器网络接口(Container Network Interface),是由CNCF(Cloud Native Computing Foundation)维护的项目,其由一系列的用于编写配置容器网络插件的规范和库接口(libcni)组成,支持众多插件项目。后文对此有详细说明。

1.4.2 集群上的网络通信

Kubernetes集群的客户端大体可以分为两类:API Server客户端和应用程序(运行为Pod中的容器)客户端,如图1-14所示。第一类客户端通常包含人类用户和Pod对象两种,它们通过API Server访问Kubernetes集群完成管理任务,例如,管理集群上的各种资源对象。第二类客户端一般也包含人类用户和Pod对象两种,它们的访问目标是Pod上运行于容器中的应用程序提供的各种具体的服务,如redis或nginx等,不过,这些访问请求通常要经由Service或Ingress资源对象进行。另外,第二类客户端的访问目标对象的操作要经由第一类客户端创建和配置完成后才能进行。

14.png
图1-14 Kubernetes客户端及其类型


访问API Server时,人类用户一般借助于命令行工具kubectl或图形UI(例如Kubernetes Dashboard)进行,也可通过编程接口进行访问,包括REST API。访问Pod中的应用时,其访问方式要取决于Pod中的应用程序,例如,对于运行Nginx容器的Pod来说,其最常用工具自然是浏览器。
管理员(开发人员或运维人员)使用Kubernetes集群的常见操作包括通过控制器创建Pod,在Pod的基础上创建Service供第二类客户端访问,更新Pod中的应用版本(更新和回滚)以及对应用规模进行扩容或缩容等,另外还有集群附件管理、存储卷管理、网络及网络策略管理、资源管理和安全管理等,这些内容将在后面的章节中展开。不过,这一切的前提是要先构建出一个可用的Kubernetes集群,这一内容将在第2章中着重讲述。

1.5 本章小结

本章介绍了Kubernetes的历史、功用、特性及其相关的核心概述和术语,并简单描述了其架构及其各关键组件,以及集群网络中的常见通信方式,具体如下。

  • Kubernetes集群主要由Master和Node两类节点组成。
  • Master主要包含API Server、controller-manager、Scheduler和etcd几个组件,其中API Server是整个集群的网关。
  • Node主要由kubelet、kube-proxy和容器引擎等组件构成,kubelet是Kubernetes集群的工作于节点之上的代理组件。
    完整的Kubernetes集群还需要部署有CoreDNS(或KubeDNS)、Prometheus(或HeapSter)、Dashboard和Ingress Controller几个附加组件。

Kubernetes的网络中主要存在四种类型的通信:同一Pod内的容器间通信、各Pod间的通信、Pod与Service间的通信,以及集群外部的流量同Service之间的通信。

版权声明:如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:developerteam@list.alibaba-inc.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接