1.K8S历史
K8S是谷歌的项目,它的前身是Borg
Borg是Google用来管理公司内部所有作业的这样一个作业管理平台。过去的一段时间里面,对于作业管理或者对于云管理,那主要其实是两条路,第一条路就是以Openstack这类虚拟化技术为主的这种云管平台,就相当于说我把很多物理机在这个基础之上装上Hypervisor,然后在上面在启一些虚拟机,那么再把这些虚拟机组成一个大的云平台。这是以Openstack为例的,它主要的云平台交付的最核心的产品或者是它最终的交付形态就是一个个的操作系统,在这个操作系统之上我们需要部署自己的应用,后续应用的升级,应用的管理跟底层的基础云平台它是相对有比较明确的界限。所以在以前的云平台里面,都会有比较清晰的像这种基础架构的Inrasturcture as a Service.平台的Platform as a Service.Saas Software as a Service,就会有这样明确的界限。
那么另外一类就是以Google的Borg系统为主的,它没有虚拟化技术,它的主要的一个实现方式就是用轻量级的作业调度,在做kubernetes之前,IBM有几年其实是做这种传统High Performance Computing平台的(高性能运算),其核心就是作业调度,调度的是一个个的进程。所以Borg就是一个这样的平台,Borg本身利用了一些容器技术,比如说Cgroup技术,就是Google开源给Linux。
1.1 Borg简介
1.2 基本概念
1.3 Borg架构
1.4 应用高可用
1.5 Borg系统自身高可用
1.6 资源利用率
1.7 Borg调度原理
1.8隔离性
2.什么是K8S
2.1命令式VS声明式
2.2声明式系统规范
2.3 K8S:声明式系统
pod是描述一个个作业的,它是基本的一个调度单元,用户可以在pod里面定义要运行哪个容器镜像。
Kubernetes里面允许用户去定义一个Service对象,Service这个对象一旦被创建出来,Kubernetes就会完成负载均衡的配置以及域名配置,就类似于刚才Borg的Naming Service
2.4 K8S采用与Borg类似的架构
集群里面会分为管理节点和Worker节点(作业节点)
2.4.1 API Server
管理节点会运行API Server,API Server其实就是一个简单的restServer,它接受Web请求,所有Web请求无论是通过命令行还是浏览器也好都会转换成一个REST的调用,发到API Server里面。API Server本身逻辑简单,没有太多的业务逻辑,它会把这个请求直接存到自己的数据库里面(etcd,作为整个集群的一个分布式键值存储体系)。etcd有一个watcher模式,也就是说当我们去get一个对象的时候,我们可以加一个watch的参数,那么加了watch参数以后,那么你客户端的这次get请求首先会完成,第二这次连接不会断掉的话,你客户端就会跟服务器端保持一个长连接,如果所请求完了之后的对象发生后续的变化,etcd会主动把这个变化以事件的形式推给客户端。所以一旦etcd那里发生了变化,也会通知到API Server,API Server也可以把这个变化给推送出去。
2.4.2 scheduler
scheduler:用户创建一个pod(作业)的时候,那么这个请求会被API Server接收到,API Server就会告诉调度器说有这样一个Pod的调度需求,那么scheduler就会去做调度,scheduler主要看这个pod需要多少资源,另外也要看当前集群里面的资源利用状况,这些利用状况都是从worker节点的kubelet上得到的。kublet会把节点的状况报告给API Server,API Server会把这些信息存储到etcd,同时scheduler就能接收到这些变化的请求。然后scheduler可以把pod和节点做一个绑定,并告诉API Server。API Server相当于把Pod的信息里面的NameNode属性更新到etcd里面去。接下来每个节点上运行的kubelet就会看跟我这个节点相关的pod有哪些,如果这个新的pod跟我这个节点相关,那我就去启动进程。
2.4.3 Controllers
K8S不仅仅只有Pod,还有其他抽象对象,每个抽象对象都一些特定的职责,比如说刚才用户要建立的Service,那么K8S要帮它去配域名的对吧,要配负载均衡的。每个worker节点上有个kube-proxy去配置负载均衡
那controller里面就有一些更加高级的功能,是面向K8S的不同对象去做整个集群的自动化配置的。
2.5 主要组件
API Server,注册了一些对象Handler,当你这个对象要操作任何对象的时候,它实际上转化成了一个REST的调用,由API Server来接收,API Server其实就是整个集群控制面的API网关。
Controller manager管理了一堆的控制器。比如Deployment控制器,ReplicaSet控制器,NodeLifeCycle的控制器,分别用来管理不同的对象。它相当于一个大脑。API Server收到请求之后只是存储起来,具体该怎么做,是由这个controller manager去做的。
kublet:上传节点的而健康装填,维护当前节点的所有Pod的生命周期
kube-proxy:当你去定义一个Service的时候,要发布一个服务的时候,需要为这个服务配置负载均衡,这个是由Proxy去做的。
Pod:每一个Pod里面,都是通过container的RuntimeService去启的应用。
cAdvisor:用于收集容器进程的一些健康状况。包括资源容量,比如说你用了CPU多少memory。以此做到一个监控。
2.6 K8S的主节点
其实controller和Scheduler没有什么本质区别,只不过controller是专职做调度的
2.7 etcd
选主是很重要的事情,所有的写操作都由leader去做。另外master需要把写操作指令下发到其他节点上面去,保证这些节点跟leader同步
我们直接可以进到etcd的pod里面查看数据。关键的是etcd是有状态的
2.8 API Server
这个是无状态的。Mutating是什么意思呢,当API Server收到请求后,可能想在这个请求里面加一些属性操作,这个就是Mutating。
APIServer本身是一个RestServer,RestServer它就要去注册自己的每一个不同对象的Handler。所以它有个APIHandler的注册的过程,然后接下来会去做认证,认证可以用自带的认证,也可以用户自定义一些认证,通过挂钩的方式弄进来
在接下来就是限流--审计--鉴权
2.9 Controller Manager
Controller Manager监控了整个APIServer,里面有很多的控制器,不同的控制器会负责不通的职责。那么其有些控制器,其实所有的控制器遵循同样的规范,就是先去读用户的这个抽象对象,那么这个抽象对象里面有用户的期望状态(Desired State)。当读到这个状态之后,接下来就要开始干活了,也就是去做真实的配置,它要确保这个系统的真实状态跟用户的期望状态保持一致。如果这次配置出现了错误,它就要自动重试。
比如说你要创建一个Pod,这个Pod需要4个CPU,但是当前的集群已经没有任何的节点,能够满足你的4个CPU的需求,这个时候你的Pod就会处于一个Pending的状态,它就不会被调成功。然后需要不断的重试去满足要求。
2.10 控制器的工作流程
针对任何对象,K8S其实它有一些辅助的一些工具叫CodeGenerator,会帮忙生成这个对象的一些代码框架,这个代码框架其实主要就是它的Controller Interface.
这个Intereface氛围Listener和Informer。K8S中任何的对象是允许去做监听的,这个Informer相当于是去监听某个对象,对象发生了任何变化后,把这个对象放到队列里面,然后后续由worker从队列里面获取这些事件。
Listener:它提供了一些接口,让用户从client-cache里面获取对象,而不需要去访问API Server了。
2.11 Informer的机制
List&Watch。List会把当前的所有对象List返回回来,第二作为一个长连接,它会关注后续的变化。
Reflector:按照给定的这个对象的类型,把API Server里面的一些JSON和Protobuf类型的对象按照反射的方式转换成对象。
转换好后的对象就会存到一个Thread safe Store里面来。这里面的对象凡是被list到还是watch到,都会通过Informer发送到handler,来处理这些事件。
2.12 控制器的协同工作原理
当我们创建一个Deployment(包含一个Nginx镜像的Pod),我们会发起一条命令给API Server。发起的时候,客户端会去读取confile file文件(在/root/.kube/config目录下面),这个文件是kubctl默认读取的一个配置,这个配置里面有API Server的地址,以及客户身份的一些认证信息。
API Server收到请求以后,就会把这个请求存到etcd里面去,存好以后,这个时候控制器就开始工作了,控制器里面有一对的Controller,Deployment这个Controller就会去解析用户传递过来的Deployment对象,然后根据里面的模板创建ReplicaSet(副本集对象)。
当这个副本集创建好了以后,它又一样经过认证、鉴权等存到etcd里面,这个时候ReplicaSet Controller会Watch API Server,它发现有个replicaSet对象被创建了,那么它就要去解析了,看其中的pod模板是咋样的,接下来就会创建一个Pod。这个Pod创建请求就会被提交到APIServer。
这个Pod被创建的时候,没有经过调度,没有和任何节点产生绑定关系。那么这个时候调度器就要开始工作了,它去监听这个Pod,发现这个Pod没有跟节点产生过绑定关系,那么它就去找现有集群里面的所有可用节点,并匹配一个适合这个Pod的节点。这个时候Pod的Nodename就会被赋予一个值。
这个时候节点的kubelet会尝试去加载这个Pod,通过Container Runtime Interface先把这个容器进程拉起来,通过Container Network Interface把网络配置好,通过Container Storage Interface帮它把这个存储挂上去。这样就完成了整个Pod应用的加载
2.13 Scheduler
2.14 kubelet
2.15 kube-proxy
当我们把一个Service发布出来以后,kube-proxy去配负载均衡。为服务发布做出努力的这样一个组件。