背景
前不久公司领导跟我聊天,
K8S
是什么? 它能干什么?
二话不说,直接搬出概念,它的本质是工业级编排平台,负责容器的弹性、管理和编排。
我之前没有怎么接触
K8S
相关的概念,啥是容器?怎么弹性?如何管理和编排?
容器是利用了集装箱的思想,把可运行程序打包成可运行、自包含、标准化的镜像。通过K8S
能够管理和编排我们打的镜像,举例来说,如果你想运行两个副本,直接在编排文件中配置replicas
为2
即可,你也可以使用HPA
通过检测CPU
、内存使用率实现自动扩缩容。
又是镜像,又是编排,引入这么多新概念,能
hold
住?你就给我说说,它和SpringCloud
、dubbo
...等微服务框架有什么不同?
SpringCloud、dubbo
等框架和K8S
切入点不同,K8S
能够支撑所有框架和语言,并提供了平台级别的服务;而SpringCloud
仅仅是整合了Java
库以及各种运行时概念,是通过JVM
级别来管理的。
到此结束吧,说到底,还是没有讲清楚它的本质、不能用通俗易懂的语言说清楚
K8S
到底是什么!
对于一个没有接触到云原生概念的人,如何讲清楚云原生时代的操作系统K8S
到底是什么?和普通微服务框架有什么区别?如果问我K8S
中的核心组件的功能,又该如何解答?
后来仔细想了想, 可以把K8S
比喻成一栋精装修大楼,每间都是统一的标准,拎包入住即可;而其它的一些微服务框架则可以看作毛坯房,需要各种定制化,无法做到开箱即用,至于精装修是否适合自己,还要看自己房子的数量。
就本人而言是不喜欢拿IT
技术打比方的,因为IT
技术是一门严谨的科学,通过打比方的方式,虽然能够对一门技术有个大致的了解,但是不能从根本上搞明白核心技术点,从而不能起到关键性帮助,有时还会造成曲解。所以直接抠概念中核心关键点文档即可。
本文会用本人自己通俗的语言叙述K8S
中核心组件的概念,概念段落中黑体字会用浅显易懂的语言描述该概念,紧接着会进一步解释该组件的功能。适用于K8S
小白,如果你是高手,出门左转,不送!
Controller-控制器
- 宏观上来说
控制器本质上就是一个死循环,不断获取实际状态,然后跟期望状态做对比,通过对比决定下一步的操作;如果跟实际状态一致,维持现状,否则将实际状态调整为期望状态。
![384132dc595e7986e3a7c4b7ca439411.png](https://i-blog.csdnimg.cn/blog_migrate/1c6289612bea5e642c92d69a041dcb8b.png)
- 微观上来说
控制器的设计原理是用一种对象控制另一种对象的艺术。
![91f55d7dce04d6ddc33a214d751b2427.png](https://i-blog.csdnimg.cn/blog_migrate/341aab3ddfa80c4cf0ee8d7495eb9b93.png)
另外我们在一些架构图中经常看到kube controller manager
和cloud 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
,用来监听etcd
中Pod、Node、Service
等资源对象的变化,并通过Informer Handler
把待调度Pod
加入的到优先级队列,Node
等信息缓存到Cache
中。
Informer
是Client-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
将会被选中。调度算法完成后需要将Pod
和NodeName
进行绑定,这个过程就是最后一步Bind
,当然这个Bind
只是更新缓存中绑定信息,称之为乐观绑定。
Predicates
在调度过程中的作用,可以理解为filter
,它按照调度策略,从集群节点中过滤出一系列符合条件的节点。这些节点都是可以运行待调度Pod
的宿主机。Priorities
阶段的工作主要就是为这些节点大根,这个打分的范围是0-10
分,得分最高的节点就是Pod
绑定的最佳节点。
APIServer
对比Kubernetes
和单机操作系统,Kubernetes
相当于操作系统,控制着整个集群硬件资源管理,并提供统一的入口,用户可以通过这个入口使用集群、这个入口正是API Server
,通过这个入口,使我们才能进入K8S
内部操作其资源对象。
![783563edf6b1a815c79d2da6159e2d20.png](https://i-blog.csdnimg.cn/blog_migrate/c081b03c5ca0b75cf081af4bcf5db5f0.png)
举个例子,一个Pod
从提交到运行时序图,如下所示:
- 提交一个
yaml
编排文件到APIServer
APIServer
会把创建Pod
编排文件信息透传到etcd
数据库中- 调度器
Scheduler
通过listandwatch
观察到有新的Pod
需要调度,调度器会为这个Pod
寻找一个合适的节点并放置上去,并且把节点信息回传到APIServer
保存到etcd
中 Kubelet
发现有一个Pod
调度到自己所在节点,会进行docker run
操作启动服务,并且把Pod
状态信息回传给APIServer
,最终APIServer
把Pod
信息记录到etcd
中。
通过这幅图可以看出一个Pod
在创建过程,除了APIServer
之外,其它组件之间的通信都要经过APIServer
。但是你可能会产生一个疑问,控制器呢?请看下图,控制器正是保证和控制服务正常运行的大脑。
![a98fd492486216330d181a723dd4cf89.png](https://i-blog.csdnimg.cn/blog_migrate/c33e74a6394dbf652d156f60b37b28da.png)
etcd
![fd904635570ab37a0db806cde4783bf1.png](https://i-blog.csdnimg.cn/blog_migrate/288faaf742610b2ac7bd7d02d5357ed0.png)
etcd
是一个分布式,可靠的key value存储系统,它用于存储分布式系统中的关键数据。得益于etcd
自身的租约、历史数据版本控制等机制,Kubernetes
自身状态数据流转到etcd
中,Kubernetes
自身不在需要处理复杂的状态数据,从而简化Kubernetes
自身架构。
一个
etcd
集群,通常会由3
个或者5
个节点组成,多个节点之间,通过一个叫做Raft
一致性算法的方式完成分布式一致性协同,算法会选举出一个主节点作为leader
,由leader
负责数据的同步与数据的分发,当leader
出现故障后,系统会自动地选取另一个节点成为leader
,并重新完成数据的同步与分发。客户端在众多的leader
中,仅需要选择其中的一个就可以完成数据的读写。其内部机制非常复杂,采用B+树数据存储,但是对外提供接口非常简单,我们可以直接通过HTTP
协议进行访问。
ETCD
中主要使用使用场景有选主、并发控制进程执行、服务发现(租约检测节点存活}、版本机制控制历史数据
总结
本文主要是通过通俗易懂的语言描述了K8S中核心组件的功能以及用途,使其看起来简单,但内部执行流程及细节却是非常复杂,本人目前也正在阅读和实践client-go
的源码,后续会有输出,欢迎有兴趣的同学,关注公众号、加我微信一起讨论。
推荐
如何使用 Ingress-nginx 进行前后端分离?
深入探究 K8S ConfigMap 和 Secret
Kubernetes入门培训(内含PPT)
从Ice到Kubernetes容器技术,微服务架构经历了什么?
原创不易,随手关注或者”三连“,诚挚感谢!