白话K8S核心组件概念

2020-08-20 16:40:45 浏览数 (1)

背景

前不久公司领导跟我聊天,K8S是什么? 它能干什么?

二话不说,直接搬出概念,它的本质是工业级编排平台,负责容器的弹性、管理和编排。

我之前没有怎么接触K8S相关的概念,啥是容器?怎么弹性?如何管理和编排?

容器是利用了集装箱的思想,把可运行程序打包成可运行、自包含、标准化的镜像。通过K8S能够管理和编排我们打的镜像,举例来说,如果你想运行两个副本,直接在编排文件中配置replicas2即可,你也可以使用HPA通过检测CPU、内存使用率实现自动扩缩容。

又是镜像,又是编排,引入这么多新概念,能hold住?你就给我说说,它和SpringClouddubbo...等微服务框架有什么不同?

SpringCloud、dubbo等框架和K8S切入点不同,K8S能够支撑所有框架和语言,并提供了平台级别的服务;而SpringCloud仅仅是整合了Java库以及各种运行时概念,是通过JVM级别来管理的。

到此结束吧,说到底,还是没有讲清楚它的本质、不能用通俗易懂的语言说清楚K8S到底是什么!

对于一个没有接触到云原生概念的人,如何讲清楚云原生时代的操作系统K8S到底是什么?和普通微服务框架有什么区别?如果问我K8S中的核心组件的功能,又该如何解答?

后来仔细想了想, 可以把K8S比喻成一栋精装修大楼,每间都是统一的标准,拎包入住即可;而其它的一些微服务框架则可以看作毛坯房,需要各种定制化,无法做到开箱即用,至于精装修是否适合自己,还要看自己房子的数量


就本人而言是不喜欢拿IT技术打比方的,因为IT技术是一门严谨的科学,通过打比方的方式,虽然能够对一门技术有个大致的了解,但是不能从根本上搞明白核心技术点,从而不能起到关键性帮助,有时还会造成曲解。所以直接抠概念中核心关键点文档即可。

本文会用本人自己通俗的语言叙述K8S中核心组件的概念,概念段落中黑体字会用浅显易懂的语言描述该概念,紧接着会进一步解释该组件的功能。适用于K8S小白,如果你是高手,出门左转,不送!

Controller-控制器

  • 宏观上来说

控制器本质上就是一个死循环,不断获取实际状态,然后跟期望状态做对比,通过对比决定下一步的操作;如果跟实际状态一致,维持现状,否则将实际状态调整为期望状态。

控制器基本架构

  • 微观上来说

控制器的设计原理是用一种对象控制另一种对象的艺术。

从编排文件看控制器设计模式

另外我们在一些架构图中经常看到kube controller managercloud ontroller manager,其中kube controller manager就是我们常见的有Pod控制器、Deployment控制器....的实现。cloud ontroller manager是对route控制器、Service控制器,之所以会出现cloud mananger controller是因为在不通的云环境中、控制器的实现会因为云厂商、环境的不同,存在一定的差别。

总结来说,控制器就是整个集群的大脑,有了控制器才能使集群更加智能。

Scheduler-调度器

从大体上来说,是一个择优而居的过程,调度器就是为Pod选择一个合适Node,让Pod的定义的任务在这个node上顺利完成。

整个过程如下图:

Informer Path

第一个控制循环我们称之为Informer Path,它启动一系列的Informer,用来监听etcdPod、Node、Service等资源对象的变化,并通过Informer Handler把待调度Pod加入的到优先级队列,Node等信息缓存到Cache中。

  • InformerClient-go 中的一个核心工具包。内部实现极其复杂,简单来说是一个依赖K8s List/watch API,可以监听事件并触发回调函数的工具包。
  • Priority Queue K8s的调度队列,之所以在这里添加调度队列主要是出于对调度优先级和抢占的考虑,通过使用调度队列可以对调度中的内容做特殊操作。
  • Scheduler cache调度器缓存,最大程度上将集群信息缓存化,提高Predicte调度算法的执行效率。

Scheduling Path

第二个控制循环是调度器负责Pod调度的主循环,称之为Scheduling Path,主要逻辑就是不断的从队列里拿出Pod,然后调用Predictates进行过滤,这一步的过滤是得到一组满足条件的Node,当然这些Node都是从cache中直接拿到的,接下来再调用Priority算法为上述列表中的Node打分,分数从0-10,得分最高的Node将会被选中。调度算法完成后需要将PodNodeName进行绑定,这个过程就是最后一步Bind,当然这个Bind只是更新缓存中绑定信息,称之为乐观绑定。

  • Predicates在调度过程中的作用,可以理解为filter,它按照调度策略,从集群节点中过滤出一系列符合条件的节点。这些节点都是可以运行待调度Pod的宿主机。
  • Priorities阶段的工作主要就是为这些节点大根,这个打分的范围是0-10分,得分最高的节点就是Pod绑定的最佳节点。

APIServer

对比Kubernetes和单机操作系统,Kubernetes相当于操作系统,控制着整个集群硬件资源管理,并提供统一的入口,用户可以通过这个入口使用集群、这个入口正是API Server,通过这个入口,使我们才能进入K8S内部操作其资源对象。

集群入口

举个例子,一个Pod从提交到运行时序图,如下所示:

  • 提交一个yaml编排文件到APIServer
  • APIServer会把创建Pod编排文件信息透传到etcd数据库中
  • 调度器Scheduler通过listandwatch观察到有新的Pod需要调度,调度器会为这个Pod寻找一个合适的节点并放置上去,并且把节点信息回传到APIServer保存到etcd
  • Kubelet发现有一个Pod调度到自己所在节点,会进行docker run操作启动服务,并且把Pod状态信息回传给APIServer,最终APIServerPod信息记录到etcd中。

通过这幅图可以看出一个Pod在创建过程,除了APIServer之外,其它组件之间的通信都要经过APIServer。但是你可能会产生一个疑问,控制器呢?请看下图,控制器正是保证和控制服务正常运行的大脑。

Kubernetes控制平面

etcd

etcd

etcd是一个分布式,可靠的key value存储系统,它用于存储分布式系统中的关键数据。得益于etcd自身的租约、历史数据版本控制等机制,Kubernetes自身状态数据流转到etcd中,Kubernetes自身不在需要处理复杂的状态数据,从而简化Kubernetes自身架构。

一个etcd集群,通常会由3个或者5个节点组成,多个节点之间,通过一个叫做Raft一致性算法的方式完成分布式一致性协同,算法会选举出一个主节点作为leader,由leader负责数据的同步与数据的分发,当leader出现故障后,系统会自动地选取另一个节点成为leader,并重新完成数据的同步与分发。客户端在众多的leader中,仅需要选择其中的一个就可以完成数据的读写。其内部机制非常复杂,采用B 树数据存储,但是对外提供接口非常简单,我们可以直接通过HTTP协议进行访问。

ETCD中主要使用使用场景有选主、并发控制进程执行、服务发现(租约检测节点存活}、版本机制控制历史数据

总结

本文主要是通过通俗易懂的语言描述了K8S中核心组件的功能以及用途,使其看起来简单,但内部执行流程及细节却是非常复杂,本人目前也正在阅读和实践client-go的源码,后续会有输出,欢迎有兴趣的同学,关注公众号、加我微信一起讨论。

0 人点赞