阿里云数字新基建系列:云原生操作系统Kubernetes
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

5.3 择优而居

5.3.1 两种节点,一种任务

如开始所讲,Kubernetes是管理集群多个节点的操作系统,这些节点在集群中的角色却不必完全一样。Kubernetes集群有两种节点,Master节点和Worker节点,如图5-6所示。

这种角色的区分,实际上就是一种分工:Master节点负责整个集群的管理,其上运行的以集群管理组件为主,这些组件包括实现集群入口的API Server;而Worker节点主要负责承载普通任务。

在Kubernetes集群中,任务被定义为Pod。Pod是集群可承载任务的原子单元。Pod被翻译成容器组,其实是意译,因为一个Pod实际上封装了多个容器化的应用。从原则上讲,被封装在一个Pod里边的容器之间应该存在较大程度上的耦合关系。

图5-6 Kubernetes集群和集群节点

5.3.2 择优而居

调度算法需要解决的问题,是替Pod选择一个舒适的“居所”,让Pod所定义的任务可以在这个节点上顺利地完成。

为了实现“择优而居”的目标,Kubernetes集群调度算法采用了两步走的策略:第一步,从所有节点中排除不满足条件的节点,这一步是预选;第二步,给剩余的节点打分,最后得分高者胜出,这一步是优选。

下面,我们使用5.1节中制作的镜像创建一个Pod,并通过日志来具体分析一下,这个Pod怎样被调度到某一个集群节点。

5.3.3 Pod配置

首先,我们创建Pod的配置文件,配置文件格式是json。这个配置文件有三个地方比较关键,分别是镜像地址、命令及容器的端口。

5.3.4 日志级别

集群调度算法被实现为运行在Master节点上的系统组件,这一点和API Server类似。其对应的进程名是kube-scheduler。

kube-scheduler支持多个级别的日志输出,但社区并没有提供详细的日志级别说明文档。在查看调度算法对节点进行筛选、打分的过程中,我们需要把日志级别提高到10,即加入参数--v=10。

5.3.5 创建Pod

使用curl,以证书和Pod配置文件等作为参数,通过POST请求访问API Server的接口,我们可以在集群里创建对应的Pod。

5.3.6 预选

预选是Kubernetes调度的第一步,这一步要做的事情,是根据预先定义的规则,把不符合条件的节点过滤掉。不同版本的Kubernetes所实现的预选规则有很大的不同,但基本趋势是,预选规则会越来越丰富。

比较常见的两个预选规则是PodFitsResourcesPred和PodFitsHostPortsPred。前一个规则用来判断一个节点上的剩余资源能不能满足Pod的需求,后一个规则检查一个节点上某一个端口是不是已经被其他Pod所使用了。

以下日志是调度算法在处理测试Pod时输出的预选规则的日志。这段日志记录了预选规则CheckVolumeBindingPred的执行情况。某些类型的存储卷只能挂载到一个节点上,这个规则可以过滤掉不满足Pod对存储卷需求的节点。

预选规则CheckVolumeBindingPred日志:

从app的编排文件里可以看到,Pod对存储卷并没有什么需求,所以这个条件并没有过滤掉节点。

5.3.7 优选

调度算法的第二个阶段是优选阶段。在这个阶段,kube-scheduler会根据节点可用资源及其他一些规则给剩余节点打分。

目前,CPU和内存是调度算法考量的两种主要资源,但考量的方式并不是简单地认为剩余CPU、内存资源越多得分就越高。

日志记录了两种计算方式:LeastResourceAllocation和BalancedResourceAllocation。前一种方式计算Pod调度到节点之后,节点剩余CPU和内存占总CPU和内存的比例,比例越大得分就越高;第二种方式计算节点上CPU和内存使用比例之差的绝对值,绝对值越大得分就越低。

● 资源打分。

这两种方式,第一种倾向于选出资源使用率较低的节点,第二种希望选出两种资源使用比例接近的节点。这两种方式有一些矛盾,最终依靠一定的权重来平衡这两个因素。

除了资源之外,优选算法会考虑其他一些因素,比如Pod与节点的亲和性,或者当一个服务由多个相同Pod组成时,多个Pod在不同节点上的分散程度,这是保证高可用的一种策略。

● 其他因素打分。

5.3.8 得分

最后,调度算法会让所有的得分乘它们的权重,然后求和得到每个节点最终的得分。因为测试集群使用的是默认调度算法,而默认调度算法把日志中出现的得分项所对应的权重都设置成了1,所以如果按日志里有记录的得分项来计算,最终三个节点的得分应该分别是29、28和29。

● 节点得分。

之所以会出现日志输出的得分和我们自己计算的得分不一致的情况,是因为日志并没有输出所有的得分项,猜测漏掉的策略应该是NodePreferAvoidPodsPriority,这个策略的权重是10 000,每个节点得分为10,所以才得出日志最终输出的结果。