kubernetes架构-组件交互篇
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kubernetes架构-组件交互篇相关的知识,希望对你有一定的参考价值。
参考技术A Kubernetes的节点包含两种角色:Master节点和Node节点。Master节点部署apiserver 、scheduler、controller manager (replication controller、node controller等),Node节点上部署kubelet和proxy。当然可以把Master和Node节点部署到一起,只是生产环境通常不建议这样做。以下涉及各个组件实现了什么,有什么处理逻辑,部分组件涉及该组件的高可用,并以deployment创建为例串了下流程。整个下来,对kunernetes各个组件有一定的了解。
Apiserver 是Kubernetes最核心的组件,是整个集群API的入口,每个组件都需要和它交互。Kubernetes所有资源数据都是通过Apiserver保存到后端Etcd的,它本身还提供了对资源的缓存。因为Apiserver是无状态的,所以在集群的高可用部署可以为多活。
Apiserver启动 后会将每个版本的接口注册到一个 核心的路由分发器(Mux) 。Kubernetes API接口主要分为组、版本和资源三层。举例:“/apis/batch/v1/jobs”接口,batch是组,v1是版本,jobs是资源。Kubernetes的核心资源都放在“/api”接口下,扩展的接口放在“/apis”下。
Apiserver请求处理流程拆分如下:
1) 当客户端请求到达Apiserver后,首先经过Authentication认证和Authorization授权。认证支持Basic、Token及证书认证等。授权目前默认使用的是RBAC。
2) 认证成功后,请求到达路由分发器(Mux),然后路由分发到指定接口。
3) 经过路由分发后,为了兼容多个接口版本,将请求中不同版本的资源类型统一转化为一个内部资源类型。
4) 转换为内部模型后, 进入Admission准入控制 ,在准入控制采用插件机制,用户可以定义自己的注入控制器验证,并更改资源配置。
5) 准入控制通过后,进入 Validation资源校验 。资源校验主要是验证参数是否合法,必传参数是否齐备等。
6) 最后转化到用户最初的资源版本,并保存到 Etcd 中。
Controller manager是负责资源管理的组件,它主要负责容器的副本数管理、节点状态维护、节点网段分配等,是Kubernetes负责实现生命式API和控制器模式的核心。
以ReplicaSet为例,Controller manager会周期地检测理想的“目标容器数”和真实的“当前容器数”是否相同。如果不相等,则会将实际的容器数调整到目标容器数。当设置一个ReplicaSet的副本数为10的时候,如果实际的容器数小于10,则会执行调用Apiserver创建Pod。如果当前容器数大于10,则会执行删除Pod操作。
Scheduler负责容器调度组件。每个Pod会在一台node节点上启动,通过 Scheduler 调度组件的筛选、打分,选择出Pod启动的最佳节点。当Pod创建后,Pod的NodeName属性为空,Scheduler会查询所有NodeName为空的Pod,并执行调度策略。选择最优的部署节点后,调用 Apiserver 绑定Pod对应的主机(设置Pod NodeName属性)。绑定成功后,对应节点的 Kubelet 便可以启动容器。
Scheduler的调度过程分为两个步骤:
第一步是筛选(Predicate),筛选满足需要的节点。筛选的条件主要包括(1)Pod所需的资源(CPU、内存、GPU等);(2)端口是否冲突(针对Pod HostPort端口和主机上面已有端口,我认为这个应该是容器的网络模式为host);(3)nodeSelector及亲和性(Pod亲和性和Node亲和性);(4)如果使用本地存储,那么Pod在调度时,将只会调度存储绑定的节点;(5)节点的驱赶策略,节点可以通过taint(污点)设置驱赶Pod策略,对应的Pod也可以设置Toleration(容忍)。
第二步是根据资源分配算法排序打分(Priorities),选择得分最高的节点作为最终的调度节点,主要调度策略包括LeastRequestedPriority(最少资源请求)、BalancedResourceAllocation(均衡资源使用)、ImageLocalityPriority(镜像本地优先)和NodeAffinityPriority(主机亲和算法)等。为了归一化每种算法的权重,每种算法取值范围都是0~10,累加所有算法的总和,取得分最大的主机作为Pod的运行主机。
Scheduler组件本地维护了一个调度队列和本地缓存, 调度队列 暂存了需要被调度的Pod,调度的先后顺序可以调整。 本地缓存 主要是缓存Pod和Node信息,可以避免每次调度时都从Apiserver获取主机信息。
为了提高调度效率,Scheduler采用了乐观锁,即Predicate和Priorities是并行操作的,那么有可能会出现数据的不一致,即Pod调度时主机上面资源是符合要求的。当容器启动时,由于其他容器也调度到该节点导致资源又不满足要求了。所以在Kubelet启动容器之前首先执行一遍审计(在Kubelet上重新执行一遍Predicate)操作,确认资源充足才会启动容器,否则将更新Pod状态为Failed。
Scheduler是典型的单体调度。为了 支持高可用 ,可以部署多个Scheduler,但只有一个Scheduler处于Active状态,其他都为Standby状态。当处于Active的Scheduler宕机后,由于无法续约,会从Etcd中摘除,其他Scheduler节点便可以通过争抢注册Etcd的方式获得调度权限。
Kubelet 接收 Apiserver 分配的启动容器的任务,然后拉起容器。当然,如果收到销毁指令,同样会执行删除容器的操作。
本地镜像也是由Kubelet负责维护,配合GC机制,删除无用的镜像和容器。
除此之外,Kubelet还需定时向 Apiserver 上报自己的状态,一方面告知Apiserver自身还存活着,另一方面将本节点的Pod状态、存储使用等信息上报到Apiserver。
Kubelet启动一个主线程,用于保持和Apiserver的通信,主线程不能被阻塞,否则将无法定时完成上报,导致Apiserver将该节点设置为NotReady状态。所以Kubelet会启动很多协程用于检测节点状态,回收废旧资源,驱赶低优先级Pod,探测Pod健康状态等。 syncLoop 是Kubelet的核心,它通过一个死循环不断接收来自Pod的变化信息,并通过各种Manger执行对应的操作,如下图。
Kube-proxy 是代理服务,为Kubernetes的Service提供负载均衡,本质上是iptables或ipvs实现的。Kubernetes将服务和Pod通过标签的方式关联到一起,通过服务的标签筛选找到后端的Pod,但服务的后端通过Endpoint(端点)关联Pod,Endpoint可以理解为“Pod地址:Pod端口”的组合。
举例:kube-proxy如何生成iptables规则的?当创建一个服务后,Kubernetes默认会为每个服务生成一个虚拟IP( VIP )。通过访问VIP即以负载均衡的方式访问后端Pod的服务。举例一个服务:对内提供服务的端口8080,对外提供服务的端口31341,并通过paas.io/serviceName选择后端容器。这会在每台机器上生产如下iptables规则。
1)将进和出的流量都转到KUBE-SERVICES链上。
2)目标是VIP(10.0.0.41)或访问NodePort的流量都转发到某个链上(KUBE-SVC-HDARFCJAQENGWQ37)。
3)KUBE-SVC-HDARFCJAQENGWQ37链通过iptables的随机模块分发流量,第一个是50%,第二个是100%。如果后端有3个Pod,那么比例将会是33%、50%、100%,以此类推。
4)最终通过DNAT进入容器。
通过kubectl run(eg:kubectl run nginx--image=nginx--replicas=5)命令去创建一个Deployment。
这个请求先到达 Apiserver ,Apiserver负责保存到 Etcd , Controller manager 中的Deployment控制器会监测到有一个Deployment被创建,此时会创建相应的ReplicaSet,ReplicaSet的控制器也会监测到有新的ReplicaSet创建,会根据相应的副本数调用Apiserver创建Pod。
此时Pod的主机字段是空的,因为还不知道将要在哪台机器上面启动,然后 Scheduler 开始介入,调度没有分配主机的Pod,通过预先设定的调度规则,包括节点标签匹配、资源使用量等选择出最合适的一台机器,在通过apiserver的bind请求将Pod的主机字段设置完成。
Kubelet 监测到属于自己的节点有新容器创建的事件,于是便拉起一个容器,并上报给apiserver容器的状态。
以上是关于kubernetes架构-组件交互篇的主要内容,如果未能解决你的问题,请参考以下文章