K8S因为引入了对底层硬件的抽象层,我们部署应用程序不用太多关注底层的硬件资源,因此对传统的部署和运维都带来了比较大的变化,今天我们接着上一篇文章,看看K8S对应用程序的部署具体带来了哪些“颠覆”。
我们先从抽象这个概念说起,计算机整个体系结构中,无不充斥了各种类型的抽象,笔者之前说过,抽象是人类认知事物的基本手段,抽象可以让我们从纷繁复杂的事物中,找到某个角度的规律,进而形成对事物认知的知识,这样的角度越来越多,我们对事物的认知也会更加全面,然而抽象最大的好处是,符合直觉,因为抽象是站在“人”的角度来进行信息的聚合活动。
回到计算机体系中,我们说操作系统是硬件的抽象(当然还有驱动程序,但是大部分硬件的驱动程序都包含在操作系统中,并且笔者也不打算把操作系统分为内核和外部应用,因为这不是讲操作系统的文章),而编程语言是对操作系统提供的抽象,让我们在大多数情况下不用太关心操作系统提供的接口(除非你是写高性能计算框架,编译器,或者基础设施层代码的同学)。可以看到抽象可以提供巨大的易用性,而Kubernetes就是对一组计算机集群的抽象,或者说Kubernetes是大规模分布部署的计算机集群操作系统。
为了让大家对上边这句话有一个感性的认识,咱来画个图说明一下:
操作系统为我们提供了使用底层硬件资源的抽象接口,比如我们可以基于操作系统接口,来让计算机执行某种任务,并产生结果;而Kubernetes和服务器上的操作系统的角色类似,将计算任务调度到底层集群中任意一台还有空余计算空间的机器上,因此我们可以看到,Kubernetes其实也是扮演了这种“操作接口”,最大的区别是,操作系统抽象的是一组计算机,或者叫集群。
正是因为Kubernetes提供的这层抽象,开发人员在编写应用程序的时候,特别是分布式系统,不再需要在代码里编写处理基础设施差异的功能,取而代之的是依赖于代码运行之上的Kubernetes提供的能力,这些之前需要自己处理的逻辑,下推到依赖Kubernetes抽象的关注点包括但不限于:
- 服务发现,提供分布式多实例部署的应用程序之间相互调用地址解析能力的组件。
- 水平扩展,随着应用程序流量的波动,可以灵活的增加或者减少处理实例的机制,帮助企业在服务等级和花费两个维度达成平衡。
- 负载均衡,将请求流量均衡的分布到应用的多个分布部署的实例上。
- 容错能力,也叫自愈能力,保证系统健康平稳运行。当出现应用的某个实例故障,或者应用依赖的某个组件故障,通过重启或者移动应用到健康的计算节点的方式来提供可用性和可靠性保障。
- 选主能力,在需要提供Active-Passive部署模式的应用中,K8S提供了一种确定哪些实例是Active,而哪些是Passive实例的机制,并且当主实例出现问题,Passive实例可以马上承接后续的计算任务和流量。
通过使用K8S提供的如上这些能力,我们在编写应用代码的时候,就可以把宝贵的时间花费在开发新功能,优化现有逻辑上,而不用浪费在和不同的底层部署平台的适配上,这不光让开发人员人员开发效率更高,也会让开发人员心情更加愉悦,写出质量更高的代码。
对新事物有好奇心的小伙伴可能会发现一个问题,你说Kubernetes是个操作系统,那么我们是如何安装这个操作系统呢?我们能理解单台服务器初始化的过程,我们不论是通过手动,还是在自举的时候从外部加载操作系统完成安装,最终都会有安装操作系统这么个过程,但是如果你需要在1000台机器上安装1个操作系统,这个貌似不太容易理解,我们还是先看图:
从上图我们可以看到, Kubernetes集群会无差别的将提供的计算机分成两组:Master节点组和Worker节点组。Master节点组中的机器上,部署了和Kubernetes集群管理有关的组件,这些组件共同构成了Kuberntes的管理大脑,负责控制整个集群的运行和维护等工作;而对于开发人员和运维人员来说,我们通过kubectl -f xx.yaml部署的应用程序,就运行在Worker节点组的一台或者多台机器上。
题外:熟悉Istio的同学应该知道数据平面的概念,并且很多文章中把Kubernetes的Worker节点也称作是Data Node,但是由于Kubernetes平台的核心是解决应用的部署,运维和资源调度等工作,因此笔者还是会沿用Worker节点的命名,但是当你碰到Kubernetes的文章说说Data Node的时候,知道说的是Worker Node就行,但是因为Istio本身就是基于Kubernetes部署,因此要特别注意上下文。
控制节点需要机器的数量一般是一台或者三台,取决于我们对可靠性的需求,具体来说,如果K8S集群是用来测试,那么部署一台机器就足够了,但是如果是生产环境,那就需要至少三台机器。而Worker集群的节点数量,取决于我们会部署多少应用到集群上,因此可以按照自己项目的实际需求来规划资源。
当我们在多台机器上部署了Kubernetes集群之后,我们对这些机器的操作,就当做一个整体来看待了,我们不用再像传统的单机那样对待每台机器,特别是对于Worker节点组来说,无论有多少台机器加入的工作节点组中,Kubernetes会按一个统一的计算资源来对待,如下图所示:
说有工作节点组成一个连续的空间供应用程序部署这句话其实不是很严谨,因为我们其实不能部署一个需要横跨两台机器的应用,Kubernetes并不支持一个应用的实例横跨两台机器的能力,因此我们的应用实例必须足够小,能够最少被部署到一台机器的资源上。
Kubernetes在部署应用程序的时候,会有一套完整的逻辑来完成“调度”工作,调度在分布式系统里是个高频出现的词汇,简单理解就是将资源申请,找到一个无论从资源的平衡性,可用性,系统的稳定性角度最佳的节点,这个过程是整个Kubernetes的核心,我们后续会专门介绍。另外调度在大数据平台,分布式系统中有广泛的应用,比如在Hadoop中,就有专门的调度组件来将计算任务下推到具体的计算节点上,完成计算。
K8S的调度组件目前并没有标准化,标准化的意思是,不像我们后边会提到的CSI(通用存储接口)),CNI(通用网络接口)以及CRI(容器运行接口),关于调度引擎,目前Kubernetes不提供定制化和扩展,这部分会是后续Kubernetes重点开发的方向。
当应用部署到K8S集群上之后,其实用户并不用太关心具体部署到哪个节点了。但是这句话不能太绝对,考虑到具体调度算法的差异,需要针对特殊场景来特殊处理。比如笔者在之前在华南作为大促总负责人,在大促之前会做一个叫:聚合度的排查,也就是说看看我的订单中心的实例是否被比较均衡的调度到了多太机器上,而不是都堆在一台物理机器上,这种排查其实不应该需要用户关注,但是我们一定要清楚背后的逻辑,的确在特殊的场景下,会出现一台机器上的资源很充足,大部分实例都在一台机器上,那么这台机器的网络和磁盘IO等就会在并发量高的时候,出现问题。
虽然笔者举了个例子证明了我们有时候还是需要关注,但是这里要强调的是:Kubernetes可能会移动你的应用程序,因此你不应该特别关注应用运行的Node节点。
其实笔者已经基本介绍了整个Kubernetes集群的大致架构,但是上边的介绍就想隔靴搔痒一般,并不是很痛快,那么接下来,我们就把靴子脱了,看看K8S集群的完整架构。下图是展示了更多细节的Kubernetes架构图,我们来一起看看:
从上边的架构图可以看到,Kubernetes的核心就是两个平面,控制平面和工作节点平面,这两个平面上运行的不同Kubernetes组件,共同组成整个K8S集群,我们来分别介绍一下。
【控制平面上的组件介绍 - Control Panel】
控制平面是整个集群的大脑,又多个运行在Master节点上的组件组成,在高可用的环境中,Maser节点一般由多台机器组成,来提供高可用能力,关于控制平面包含的组件,如下图所示:
基于上图的描述,管理平面包含的组件和简单的介绍如下:
- Kubernetes的API Server暴露了Restful风格的操作接口,开发和运维人员可以通过这些接口来部署,更细和下线应用程序,包括运维和监控等工作。
- ETCD是一个分布式的KV存储引擎,我们通过API Server提供的API来部署应用程序的时候,应用的描述信息(yaml文件)会被持久化到ETCD中,并且API Server是唯一可以对ETCD进行CRUD操作的组件。
- 控制器负责将我们通过API Server部署到集群的应用运行起来,大部分控制器只是简单的创建对象,但是有些也需要和集群外部的服务组件进行通信,比如集群中的PV不够了,当我的YAML声明了一个新的PVC,那么这个时候就需要外部的比如说云平台存储提供接口来提供更多的存储卷。关于PV和PVC,如果你不能理解,也没有关系,后边会有介绍。
- 调度器,调度器就是笔者前边说的,为新部署的应用找合适的部署节点的组件,这个过程异常的复杂,目前你只需要理解到这个节点会基于应用申请的资源和整个集群现在有的资源余量,来找到最佳匹配,其实找到就是将应用的Nodename设置一下,因为笔者还没有介绍容器,POD的概念,因此先简单这么理解。
以上就是整个管理平面的所有Kubernetes组件的介绍。读到这里,你可能会问,说了半天,我还是不知道我的应用具体在哪里运行啊,我们接着调度器的执行结果来继续讨论,因为通过调度器已经为应用找到了合适的运行节点,那么这个时候焦点就转到了Wroker node,我们来看看工作节点上有哪些组件。
【工作节点上的组件介绍 - Worker Node plane】
工作节点比起来控制节点简单很多,工作节点就是单纯的运行我们通过API Server部署到集群上应用,除了运行应用,还包括监控,提供应用多个实际之间的联通,工作节点上的Kubernetes组件如下图所示:
基于上图的信息,我们可以看到Kubernetes工作节点上包含了如下一些组件:
- Kubelet组件,这个组件非常重要,这个组件是形成集群的关键。Kubelet是运行在工作节点上的代理插件, 负责和API Server通信,以及管理运行在工作节点上应用程序。另外Kubelet也会将应用运行的状态反馈给控制节点上的组件。
- 容器运行时,可以是Docker或者任何Kubernetes提供支持的容器组件,容器运行时的主要工作就是基于提供的接口,和Kublets配合将我们的应用运行起来。
- Kube代理,此代理负责将入口请求流量代理到应用的多个实例上。
除了这些组件之外,Kubernets中还包括DNS,网络插件等,这些组件大部分情况下都是运行在工作节点上的。
好了,今天的文章就这么多内容了,笔者接下来会介绍如何在K8S行启动一个应用程序,敬请期待。