k8s的架构是怎么变成现在这个样子
引子:笔者在学习K8S的时候,总是在问自己为啥它的架构就变成了现在这个样子的呢,这样的架构和调度设计有什么好处呢?在学习了之后,笔者便整理了这篇文章,一来,算是跟自己答疑解惑,二来,分享出来给大家来共同探讨,方便大家相互学习。正文:笔者觉得K8S就是一个大型的操作系统,只不过它管理的硬件资源比较分散,类型繁琐、数量比较庞大,但是归根结底还是管理和调度,最终还是围绕着计算资源CPU、存储资源内存和磁
引子:
笔者在学习K8S的时候,总是在问自己为啥它的架构就变成了现在这个样子的呢,这样的架构和调度设计有什么好处呢?在学习了之后,笔者便整理了这篇文章,一来,算是跟自己答疑解惑,二来,分享出来给大家来共同探讨,方便大家相互学习。
正文:
笔者觉得K8S就是一个大型的操作系统,只不过它管理的硬件资源比较分散,类型繁琐、数量比较庞大,但是归根结底还是管理和调度,最终还是围绕着计算资源CPU、存储资源内存和磁盘、以及网络资源这三类核心资源进行展开,而它的处理方式还是采用了最基础的合并和拆分两种手段来进行设计,只不过当中比较模糊的地方融合了取和舍的思想在里面。
1.程序所需的三个资源和一个底座
对于程序而言,往往需要一个底座,三个基本资源才能真正运行起来,如下图所示,而操作系统中程序运行的最小单位是进程,所以一个程序往往是一个或者几个进程的集合配合起来完成的。
K8S通过容器来描述这些信息,包括:资源使用描述、镜像信息、存储的卷轴信息、业务所使用的端口信息等等,这部分会在后续的文章中专门介绍。
2.K8S里的最小调度单位Pod
K8S里面,采用了容器将程序以镜像的方式打包成一个统一的模块封装起来,这样k8S的调度就不需要去关注每个程序所带来的资源信息和操作系统有没有差别了。对于K8S来说,它对程序的调度方式便可以抽象一层出来,只需要关注如何组织和管理这些容器就可以了,当然K8S采用了另外一个东西来进行调度,它就是Pod,为了方便理解,可以将容器对标为进程中的线程,Pod对标成进程来看待。
(特别说明:K8S里面为了更好的复用,通过不同的配置来实现更灵活的功能,将程序和配置进行了分离,也就是ConfigMap方案,本文不做特殊介绍,后续会单独出来一篇文章来介绍。)
有了Pod之后,K8S就可以像操作系统调度进程一样,对这些Pod进行调度管理了,不过K8S不同的是,它的环境要比操作系统所在的宿主机环境复杂很多,因为它是分布式的,由成千上万的宿主机或者虚拟机组合而成,如此一来,K8S就需要先为Pod选择一个节点Node,也就是宿主机或者虚拟机。
K8S很少直接创建一个Pod,大多数情况下会通过RC、Deployment等控制器完成对一组Pod副本的创建、调度和生命周期的管理。
3.Pod的调度方式
K8S的调度有多种方式:
1).通过给Node打个标签的方式进行定向调度,在Pod里面设置NodeSelector来指定Pod调度的Node标签,来选择使用的Node节点的方式,调度器会根据调度算法针对这些被选中的Node节点进行资源等计算,从中选择一个最合适的Node节点。
2).全自动调度,是Deployment的主要玩法,主要针对多Pod的多副本进行调度,调度算法会从集群的所有Node节点里面选择资源等信息满足条件的节点,自动将Pod调度到这部分Node上面。
3).Node亲和性调度,这种调度会根据亲和性规则对这个Pod所归属的Node节点进行选择,主要有两种亲和性表达,一种是指定亲和性规则的表达RequireDuringSchedulingIgnoreDuringExection,一种是优先满足指定规则的表达PreferredDuringSchedulingIgnoredDuringException。这一类调度主要是Pod对Node节点有特殊的要求,例如网卡、磁盘SSD等。
4).Pod亲和与互斥调度,K8S 1.4版本之后出现,这一类的调度的Pod一般相互之间存在依赖性或者排他性,这一组Pod期望调度在同一个Node节点或者不能调度在同一个Node节点上面。一般通过指定主机名hostname,机架region,机房/地区zone这三个信息来进行设置Pod是在一起,还是不在一起。
5).污点和容忍调度,通过给Node打上污点,让Node拒绝Pod的运行,一般存在问题的Node才会被打上污点,如此一来新的Pod就不会调度过来,如果打上污点的这些Node还希望将某些Pod调度过来,可以在这些Pod上面设置容忍Toleration来操作。
6).Pod优先级调度,K8S 1.8版本之后,引入了这一类调度策略,核心思路是通过驱逐和抢占来实现,针对的是资源不足时候,运行的Pod根据优先级策略进行驱逐和抢占的方式,来优先满足高优先级的Pod运行。这一类调度方式,一般不太会使用,因为一旦使用了之后,整个集群里面的Pod调度可能就会失去控制,不太容易维护。
4.K8S的架构
Pod调度好了之后,Pod已经成功的存放到了所适合的Node节点上了,我们不妨想一想,集群里面的Node节点如此之多,部署在不同Node节点上面的Pod又是如何进行通讯和交流的呢?他们又是怎么进行管理和维护的呢?
K8S采用了分布式部署的方式,在每个Node节点上部署了两个东西,一个是kubelet,用来管理和维护该Node节点上面的Pod等信息的调度和控制,并从Master节点来Watch自己所需要的信息。另外一个是kube-proxy,节点通过这个程序来操作和管理Node节点的网络通讯。如此一来,整个K8S集群就又抽象成一层更大范围的管理。
不过Node节点还是很多,还是需要一个大脑来统一管控所有Pod的信息,以及Node等其他CR的信息,所以K8S便搞了一个Master节点来专门管控这些信息。
etcd保存了整个集群的状态;
apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);
kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;
总结:
K8S以Pod为最小的调度单位,并以它为锚点,层层扩展,通过其他的CR和CRD例如:Deployment,来对程序进行横向的管理和扩展,让程序在稳定性、容错性和可扩展性方面得到一个很大的自由度。
除此之外,K8S在垂直层面,对程序所需要的资源(CPU、mem、网络)进行了层层封装并对这些封装好的抽象层(分别是容器---》Pod---->Node)进行分层控制和管理,让整个K8S的架构设计变得层次清晰,职责单一。
更多推荐
所有评论(0)