建议先阅读:架构 之后,再阅读该文章。 在架构 中,已经从宏观的角度讲解了K8S, 这篇文章更进一步,介绍一下K8S的业务部署流程和相关核心概念,为下一步搭建自己的K8S集群做准备。 BTW, 为提高编写效率,我使用K8S代替Kubernetes, 二者意思完全一样,K8S是业界比较通用的Kubernetes缩写。 任何错误,也请大家指正,邮箱: qiuxincsu@hotmail.com
目录
1.K8S业务部署流程
2.POD
2.1 POD概述
2.2 POD网络
2.3 cgroup
2.4 namespace
3.Deployment/Manifest
4.DNS Service
1. K8S业务部署流程
当你了解K8S的架构之后,你会想知道这个架构对我有什么用?怎样可以将自己的业务部署在这个架构上?
将一个业务部署在K8S上分为如下步骤:
a.将现有业务进行拆解,拆解成一个个子模块。拆解的原则是:尽量减少子模块之间的耦合性,例如:共享存储、共享内存、数据交互等,尽量确保每一个模块可以被单独的开发和维护,这样方便在开发过程中各个团队并行高效工作,最终以搭积木的方式,提供整个业务系统,同时也方便后续的维护,每个团队可以独立升级自己的子模块,而尽量减少对其它团队模块的影响。当然如果是一个规模很小的应用,可以放在容器内进行,也可以不拆解,完全取决于不同的业务。
b.选择合适的开发语言和环境,开发对应的子模块,将每个子模块打包封装在容器中,并上传到容器的镜像仓库。
c.将容器集中部署在POD中。
d.将业务希望部署的集群在部署文件(manifest.yaml)进行描述,并通过kubectl command-line发给K8S的管理平面。
e.K8S的管理平面收到manifest文件之后,对进行身份权限验证和校正等工作,然后解析Manifest描述的期望部署状态。
f.K8S的管理平面将Manifest描述的期望部署状态存储在存储资源中(目前主要是ectd数据库),方便后续实际部署状态和目标状态之间的比对
g.K8S的管理平面按照Manifest描述的期望部署状态在集群中部署业务POD和容器, 包括不限于: 抓取镜像仓库中的镜像、启动容器、构建网络、运行业务等等。
h.K8S的管理平面不断循环检测当前的部署状态,并和目标部署状态进行比对,如果出现一致的情况,进行调整,最大可能确保实际部署状态和目标部署状态是完全一致的。
结合下图理解,可以帮助更好理解如上的部署流程:
如上的流程中有几个专业术语,POD、 Manifest文件等,下面详细展开,帮助大家理解。
2. POD
2.1 POD概述
POD是针对容器(Contianer)的一种封装,POD本身什么都不做,仅仅是封装资源。 POD所封装的资源构成了一种共享的执行环境(Shared Execution Environment),这些共享资源包括:Network(IP地址、端口号、路由表)、 主机名(hostname)、sockets、内存(memory)、存储(volumes)等。在技术实现上,POD也是一个容器,你可以将容器封装在POD里面,理解成:将容器运行在容器中。
POD是K8S的最小调度和部署资源(原子操作,要么部署一个POD,要么不部署),在K8S体系架构中,容器无法脱离POD独立运行,所以当你希望将业务部署在K8S上,你必须要将你已经实现的容器部署在POD里面。 当你需要扩张或者减少业务部署的时候,也是以POD为独立为单位进行扩缩容。对于调度也是一样,当你希望调度业务资源的时候,必须以POD来调度,可以将一个POD从服务器A调度到服务器B,但是你永远不可能脱离POD,直接将容器从服务器A直接调度到服务器B。
在对应关系上,最简单的情况是一个POD里面仅仅封装一个容器,当然在一些业务场景下会出现一个POD里面封装了多个容器。 这就涉及到了POD对资源分配的影响,每个POD拥有独立的IP、内存、存储等资源,当一个容器独占一个POD的时候,就比较简单,这个容器独占了这些资源;当将多个容器封装在一个POD的时候,很可能是业务需要这些容器中的业务需要共享IP、内存、容器、Namespace、Port号范围等资源, 而且多个容器会随着它们所在的POD整体被调度和迁移。举个例子,当2个容器共享一个POD的时候,如下图所展示,它们共享了IP地址10.0.10.10等执行环境,同时被调度和迁移。 此外,如果位于一个POD内的2个容器需要通信的话,可以通过localhost进行数据交互。
如果容器之间不需要共享资源的话,建议还是一个POD中一个容器,这样比较简单,也方便开发和维护。 有关多个容器封装在一个POD的应用,主要的一个场景是Service Mesh.在Service Mesh架构中,在每一个POD里面都增加了Proxy Contianer, 这样就出现了业务容器和Proxy Container共存于一个POD场景,有关Service Mesh后续单独展开,这里不做深入讨论。
有关POD的原子性,另外一个理解就是POD状态,当一个POD内部的所有的容器全部处于Ready状态的时候,整个POD才处于Ready状态,才可以对外提供业务访问。当POD中的一部分容器处于非ready状态,一部分容器处于ready状态,整个POD是非ready状态,无法对外提供业务访问。
有关POD的生命周期,和人的生命周期很类似,就是一旦翘辫子了,就不可能再复活了。POD也是一样,如果一个POD故障了或者被删除了,可以启动一个新的POD替换它,但是挂掉的那个POD就再也回不来了,新的POD拥有全新的IP地址,端口号等信息。
BTW, POD这个名词的由来,在英语中将a group of whales称之为a pod of whales, 而whales(鲸鱼)是docker中承载容器的logo标志,因为这个原因开源社区选择了POD做为专业术语。
2.2 POD网络
每一个POD有自己的独立的IP地址,TCP和UDP端口的范围,localhost以及一个自己的路由表(routing table)。如果一个POD里面仅仅有一个容器,那么这个容器就完全独占这个POD里面的这些资源。如果是一个POD里面有多个容器,那么这些资源就被多个容器所共享。
如下图所展示,当希望访问Container A的时候,使用 10.0.10.10: 80, 当希望访问Container B的时候,使用10.0.10.10: 90。 Container A 和Container B都共享了POD的IP地址10.0.10.10以及同一个端口范围,但是使用不同的端口号,使用“IP+端口号”的方式来访问POD中的一个容器。 如果POD内Contioner A和Container B希望互相访问,可以采用localhost+端口号的方式,访问Contioner A 采用localhost:80,访问Contioner B采用localhost:90.
对于POD之间的通信就比较好理解,每一个POD有自己的独立IP地址,POD会组成一个IP网络进行通信。
2.3 cgroups
Control Groups(cgroups)是Linux内核的技术,用于避免一个容器消耗节点中的所有CPU,内存,带宽等资源。每一个容器都有自己的cgoups, cgroups配置为每一个容器配置了一个最大限额,规定每一个容器最多消耗多少资源。
2.4 namespace
Namespace是逻辑上将一个K8S的集群划分为多个虚拟集群,这样虚拟划分是为了管理上更加方便。
3. Deployment/Manifest
Deployment是名为Manifest的yaml文件,我们将部署要求(也就是部署目标, Desired States)写在manifest.yaml的文件中,manifest.yaml文件包括了需要使用的容器镜像(Contioner Image)、具体需要运行容器数量(Replica)、监听端口、升级方法等等,然后将这个manifest.yaml文件发送给K8S管理面的API Service,然后K8S就会根据你描述的部署目标来部署你想要的业务集群。
当然K8S的管理面不是简单的执行部署就完了,这中间还有很多复杂的内容, 在部署之后,K8S的管理面(watch loop)会对部署的业务集群的运行状态进行实时的监控,这些监控会得到业务的集群的一个当前状态current states. 然后K8S的管理面(watch loop)对于二者进行比对,如果出现current states和desired states不一致的情况,K8S的管理面(watch loop)会针对这种差异进行调整,最大可能确保实际部署和目标部署之间是一致的。
举一个例子,在Manifest.yaml文件中描述的副本(Replica)的数量为10, 而当前的集群中实际运行的数量为8, 这种“目标状态”和“现实状态”之间的差异,会被K8S管理面(watch loop)发现,然后K8S的管理面对重新启动2个副本,确保k8s集群中运行的副本数量为10。
这也是k8s最大价值所在,你只需要告诉K8S管理面你希望一个怎么样的集群(通过manifest.yaml描述),然后K8S管理面就自动帮你完成部署和管理等工作,这样大幅减少了开发者和运维者的工作量,更多时间和精力可以放到具体业务实现上。
Deployment在K8S 1.2版本中就有出现,正式被集成的稳定版本是在1.9的版本中。
4. DNS Service
在上面POD的章节中讲了POD的生命周期,当一个POD挂了,替换它的新POD会有全新的IP地址和端口号,那么POD的变化是否会影响业务访问的IP和端口号呢? 答案当然是否定的,POD并不很稳定,如果POD挂了,引起服务访问的IP等信息变化的话,那不是天天都要改服务访问的IP地址。 K8S提供了类似DNS的服务,你可以理解类比前段和后端的概念来理解。 前端就是服务的访问IP地址和端口号等信息,这部分信息是稳定不变的,后端就是一个一个提供这种服务的POD信息,DNS Server提供了前端对外访问接口和后端POD的之间的映射,有效保证了服务访问接口的稳定,同时还提供了负荷分担等功能,确保访问流量可以平均分配到不同的POD上,实现资源的高效利用。
有关负荷分担(Load Balance)的实现使用Label和Lable Selector等知识,这里暂时不做深入展开,后续详细章节单独描述。
到此为止,已经介绍了K8S基础知识,知道了这些知识,就可以搭建K8S的集群了。 更多知识内容可以通过实际动手,不断来深入学习。
领取专属 10元无门槛券
私享最新 技术干货