关于我
中国科学技术大学计算机硕士毕业,毕业以来一直在美团猫眼,先后从事交易系统研发、基础架构中间件研发,目前专注于 服务治理 & 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.Config
apiserver
交互的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
)
创建命令的过程: