关于我
中国科学技术大学计算机硕士毕业,毕业以来一直在美团猫眼,先后从事交易系统研发、基础架构中间件研发,目前专注于 服务治理 & Service Mesh 方向。更多信息见 关于我
个人爱好:跑步(半马)、游泳、骑行、电影
关于本博客
- 博客里大部分内容属于原创;
- 早期的博客写的比较粗糙,后期将会陆续翻新,不足之处请多包涵。
scheduler是k8s集群中负责调度的组件。它监听apiserver,查询未绑定Node资源的Pod,并跟据调度策略为其选择一个最合适的节点。
下面本节将从两个方面来介绍scheduler的实现:
scheduler的初始化过程与其他组件非常类似。创建初始化配置,并将启动参数应用到该配置上,再基于此参数来运行scheudler,同样也会进行初始化参数的验证。
在运行前,scheduler会执行一些init方法注册调度策略(predicates过滤策略、priority优先级策略)register_predicates | register_priority、策略提供器配置(默认提供器和集群自动扩容提供器)defaults。位置位于algorithprovider/defaults。
注册时,注册的是策略构建工厂,并将其保存在全局变量中scheduler/algorithm_factory.go/。
注册的过滤算法有如下几种:
PodFitsPorts:被
PodFitsHostPorts取代
PodFitsHostPorts:检查是否有Host Ports冲突;
PodFitsResources:检查资源可用性(CPU、内存等是否充足),其也是默认的过滤策略;
HostName: 检查pod.Spec.NodeName是否与候选节点一致;
MatchNodeSelector:检查候选节点的pod.Spec.NodeSelector是否匹配;
NoVolumeZoneConflict:检查volume zone是否冲突;
MaxEBSVolumeCount:(废弃)检查AWS EBS Volume数量是否过多(默认不超过 39)
MaxGCEPDVolumeCount:(废弃)检查GCE PD Volume数量是否过多(默认不超过16)
MaxAzureDiskVolumeCount:(废弃)检查Azure Disk Volume数量是否过多(默认不超过16)
MatchInterPodAffinity:检查是否匹配Pod Affinity(亲和度)要求
NoDiskConflict:检查是否存在Volume 冲突;
GeneralPredicates:由多个过滤策略聚合,所有k8s组件都强制执行,包括PodFitsResources、PodFitsHost,PodFitsHostPorts和PodSelectorMatches;
PodToleratesNodeTaints:检查Pod是否容忍Node误点Node Taints;
CheckNodeMemoryPressure:检查Pod是否可以调度到MemoryPressure的节点上。
CheckNodeUnschedulable: 检查Pod是否可以调度到 带有Unschedulable的节点上;
CheckVolumeBinding: 检查是否能满足Pod的PVC上下界需求。
注册的优先级排序算法有以下几种:
SelectorSpreadPriority:优先减少同一
Service下的Pod在同一Node节点上的可能;
MostRequestedPriority:尽量调度到已经使用过的Node上,介绍节点使用;
RequestedToCapacityRatioPriority:跟据Node上的资源分配情况计算其分数;
ServiceSpreadingPriority:尽量将同一个service的Pod分布到不同节点上,被SelectorSpreadPriority替代
InterPodAffinityPriority:优先将Pod调度到相同的拓扑域上(如同一个节点、地域等);
LeastRequestedPriority:优先调度到请求资源少的节点上;
BalancedResourceAllocation:优先平衡各节点的资源使用;
NodePreferAvoidPodsPriority:跟据节点scheduler.alpha.kubernetes.io/preferAvoidPods注解来计算Node权重, 权重为 10000,避免其他优先级策略的影响;
NodeAffinityPriority:优先调度到匹配NodeAffinity的节点上;
TaintTolerationPriority:优先调度到匹配TaintToleration的节点上;
ImageLocalityPriority:尽量将使用大镜像的容器调度到已经下拉了该镜像的节点上。
controller-manager是整个k8s的大脑,
其由kube-conrtoller-manager和cloud-controller-manager组成。其中clound-controller-manager用来配合云服务提供商的控制,因此本章将不对其做详细描述。controller-manager中包含众多控制器见附件^1,通过这些控制器来完成集群管理的作用。监控集群状态,并确保集群处于预期的状态。
本节,将从如下几个方面来讲解controller-manager的工作原理:
controller-manager启动入口cmd/kube-controller-manager/controller-manager.go,与apiserver一样其也是基于CLI框架Cobra来实现。
其初始化过程如下:
KubeControllerManagerOption,用于构建控制器管理器;cobra将输入参数应用到KubeControllerManagerOption上,运行前,会先对参数进行校验;KubeControllerManagerOptions构建创建众多控制器的配置参数kubecontrollerconfig.Configapiserver交互的client;leaderElectionClient;v1.Event发送给apiserver;KubeControllerManagerOptions中的配置应用到kubecontrollerconfig.Config。控制器管理器。controller-manager创建两个http服务,分别用来做健康检查、配置查询;ControllerContext,实际是提前构建一些通用的组件Informer工厂,shared-informers以及metadata-informers;apiserver就绪,最多等待10s;apiserver中所有可用的资源;ServiceAccount控制器;app/controllermanager.go.NewControllerInitializer方法中保存了所有控制器的初始化函数,遍历并执行所有控制器的初始化函数,开启这些控制器的执行。比如DeploymentController、ReplicaSetController等;Informer工厂,开始同步并监听资源更新。到此就完成了controller-manager的初始化过程。
下面我们以DeploymentController来讲解其初始化详细过程,DeploymentController的初始化函数是startDeploymentController:
1 | dc, err := deployment.NewDeploymentController( |
可以看到,其关注监听Deployment、ReplicaSets和Pod资源。再继续查看DeploymentController的创建过程,其关注这三种资源,并且添加事件监听器,当Deployment资源更新时回调addDeplotment\updateDeployment\deleteDeployment方法,ReplicaSets和Pod的更新也会回调DeploymentController的相应方法。
1 | dc := &DeploymentController{ |
[TOC]
在介绍完apiserver之后,在介绍其他重要组件之前,本章将介绍各组件与apiserver交互的重要工具Informer。通过其我们可以轻松List\Get所有资源对象,同时可以监听资源的变更事件,当变化发生时触发回调函数。
下面将从Informer的初始化过程、更新变更两个方便来讲解其工作原理。
首先,k8s 里 Informer 的创建需要借助于SharedInformerFactory,其可以提供k8s中已知所有API组版本资源的 informer ,其接口定义如下 :
1 | type SharedInformerFactory interface { |
可以看出其包含所有资源(Api组、版本)操作的接口定义。SharedInformerFactory的默认实现如下:
1 | type sharedInformerFactory struct { |
其中client是k8s中所有API资源操作(更删改查)的工具(其通过http与apiserver通信)。
下面,就以PodInformer为例来讲解其创建过程:
1 | sharedInformerFactory.Core().V1().Pods().Informer() |
@v1.17.2)[TOC]
ApiServer是K8S服务调度的核心,其同时负责与外界的交互、集群内其他组件的交互,也是K8S中唯一与持久化存储Etcd交互的组件。
下面将从以下几点来解析 ApiSever:
Scheme构建过程 ApiServer启动位置:cmd/kube-apiserver/apiserver.go,启动先需要先启动一个Etcd。调试启动参数如下:
–secure-port=6445 –storage-backend=etcd3 –etcd-servers=http://127.0.0.1:2379 –enable-swagger-ui=true
首先创建ApiServerCommond,然后执行命令:(整个k8s代码体系都引用CLI框架Cobra)
创建命令的过程: