scheduler组件:负责调度资源,根据调度算法(预算策略、优先策略)把pod调度到node节点

1、list-watch监听

(1)定义:在k8s集群中,通过list-watch的机制进行每个组件之间的写作,保持数据同步,保证每个组件之间的解耦

(2)数据流向

kubectl配置文件,向apiserver发送命令,通过apiserver把命令发送到各个组件

①创建pod

• 第一步把创建命令发送到apiserver

• 第二步由apiserver把消息传给controller manager

• 第三步由scheduler资源调度器根据调度算法把命令传给kubelet节点控制器

• 第四步由kubelet节点控制器具体分发到哪个节点

kubectl run nginx --image=nginx:1.22→apiserver→controller manager→scheduler→kubelet

②创建成功后,pod的详细信息均保存在etcd的数据库中

list-watch会监听apiserver6443的端口,controller manager,scheduler,kubelet,etcd都会监听apiserver6443的端口

注:只有apiserver在etcd上有读写权限

2、调度过程和策略

scheduler是k8s集群的资源调度器,作用:把pod分配到集群节点

(1)调度规则

①公平分配:每个节点都能分配资源

②资源高效利用:整个集群中的资源可以最大化使用

③效率:调度性能好,若pod数量对,能尽快完成大批量的pod的调度工作

④灵活:允许用户根据需求控制、改变调度逻辑

scheduler是一个单独运行的程序,启动后会一直监听apiserver,获取报文中的spec:nodeName字段。创建pod时,为每个pod创建binding,表示该往哪个节点上部署

(2)调度策略(先执行预算策略,再执行优先策略。两个策略结合使用)

1)预算策略

(predicate自带算法,选择node节点,不需要人工干预)

podfitsresources

pod适应资源。检查节点上的剩余资源是否满足pod请求的资源

(主要是CPU和内存资源)

podfitshost

pod适应主机。若要指定pod部署再哪个节点上,检测的主机名是否存在,存在要和pod指定名称匹配才能调度过去

podselectormatches

pod选择器匹配。创建pod时可以根据node节点标签进行匹配,查找指定的node节点上标签是否存在,若存在,再检查标签是否匹配

nodiskconflict

无磁盘冲突。确保已挂载的卷与pod卷不发生冲突,除非目录是只读,可以覆盖原pod

优先执行预算策略,再执行优先策略,若预算策略都不满足,pod将始终处于pending状态,scheduler不断的重试调度,直到有节点满足条件为止

2)优先策略

leastrequestedpriority

最低请求优先级策略。通过算法计算节点上的CPU和内存的使用率,来确定节点的权重,使用率越低的节点权重越高。调度时倾向于权重高的节点,实现资源合理利用

balanceresourceallocation

平衡资源分配策略。考虑CPU和内存的使用率,根据CPU和内存使用率接近给节点赋予权重,越接近权重越高

结合leastrequestedpriority最低请求优先级策略一起使用

imagelocalitypriority

节点上是否已存在要部署的镜像。与镜像总数成正比,满足的镜像数越多,权重越高

以上策略均是scheduler自带的算法。通过预算策略选择出可以部署的节点,再通过优先策略选择出最好的节点

注:部署的node节点必须同时满足预算策略和优先策略,否则立刻报错

3)指定节点(不经过scheduler资源调度器调度)

spec设置参数nodeName:node2

在参数中设置nodeName,指定节点名称会跳过scheduler的调度策略,这个规则是强制匹配,不走调度算法,不考虑该节点资源是否足够

4)指定标签(经过scheduler资源调度器调度)

spec设置参数nodeSelector:标签名

查看节点标签(节点自带标签)

kubectl get nodes --show-labels

自定义节点标签

kubectl label nodes node2 ttt=c

③修改标签

kubectl label nodes node1 sss=b --overwrite

④删除标签(-减号)

kubectl label nodes master yyy-

⑤指定标签部署pod

指定节点标签部署pod经过scheduler调度算法,若节点不满足条件,pod进入pending算法,直到节点满足条件为止

键值运算关系

根据标签选择亲和性

In

在,选择的标签值在node节点上

NotIn

不在,选择的标签值不在node节点上

Gt

大于选择的标签值(只能比较整数值)

Lt

小于选择的标签值(只能比较整数值)

Exists

存在,只选择标签对象。只要node节点上有这个标签对象即可,无论标签值是什么(不能使用values字段)

DoesNotExist

不存在,选择不具有指定标签的对象,无论标签值是什么(不能使用values字段)

亲和性根据标签进行选择

5)节点亲和性

 硬策略requiredDuringSchedulingIgnoredDuringExecution

选择node节点时,声明部署在node1节点,硬策略必须满足这个条件(强制性要求)

注:先满足软策略,再满足硬策略

 软策略preferredDuringSchedulingIgnoredDuringExecution

选择node节点时,声明最好部署在node1,软策略会尽量满足这个条件,但不一定能完全实现

注:多个软策略看权重,权重高,执行指定的软策略

A 硬策略

 In方式调度node节点

 NotIn方式调度node节点

 Gt方式调度node节点

 Lt方式调度node节点

 Exists方式调度node节点

 DoesNotExist方式调度node节点

B 软策略(因为有权重,一个策略中可以有多个软策略)

 一个策略中可以有多个软策略(优先执行权重高的策略)

 一个策略中同时有硬策略和软策略(先满足硬策略,再满足软策略)

 不满足硬策略的条件,不再执行软策略,pod始终处于pending状态

在部署pod时如何选择策略?【面试题】

结合业务举例说明:目前有3个node

node1

4核8G

node2

4核8G

node3

2核4G

若集群中节点都正常运行,但性能高低不一致,选择软策略,性能高的多部署一点pod,性能低的少部署一点pod

若其中一个节点故障或维护中,选择硬策略,将pod部署在正常运行的节点

node亲和性和pod亲和性的区别

策略

匹配标签

操作符

拓扑域

调度目标

node亲和性

主机标签

In、NotIn、Exists、DoesNotExist、Gt、Lt

不支持

指定主机

pod亲和性

pod标签

In、NotIn、Exists、DoesNotExist

支持

pod和指定标签的pod部署在同一拓扑域

pod反亲和性

pod标签

In、NotIn、Exists、DoesNotExist

支持

pod和指定标签的pod部署不在同一拓扑域

(6)pod亲和性

1)作用:把相关联的pod部署在同一节点【面试】

2)拓扑域k8s集群节点中的一个组织结构,可以根据节点的物理关系或逻辑关系进行划分,拓扑域可以用来表示节点之间的空间关系、网络关系或其他类型的关系。这里的拓扑域指的是标签

3)策略

①硬策略requiredDuringSchedulingIgnoredDuringExecution

要求调度器将pod调度到其他pod的亲和性匹配的节点上,硬策略必须满足这个要求

 In方式分配node节点给pod

第一步:运行一个yaml文件在node节点上设置pod标签

第二步:设置pod亲和性

podAffinity:指定策略是pod亲和性

此时要满足三个条件:①pod标签是app

②pod标签值是nginx1

③拓扑域是yst(节点标签是yst)

三个条件要同时满足,否则处于pending状态

此时各个节点上的node节点标签和pod标签如下:

master

node1

node2

节点标签

yst=200

yst=500

ttt=800

pod标签

app=nginx1

app=nginx1

app=nginx1

 Exists方式分配node节点给pod

第一步:运行一个yaml文件在node节点上设置pod标签

第二步:设置pod亲和性

podAffinity:指定策略是pod亲和性

此时要满足两个条件:①pod标签是app

②拓扑域是yst(节点标签是yst)

两个条件要同时满足,否则处于pending状态

此时各个节点上的node节点标签和pod标签如下:

master

node1

node2

节点标签

yst=200

yst=500

ttt=800

pod标签

app=nginx1

app=nginx1

app=nginx1

 DoesNotExist方式分配node节点给pod

第一步:运行一个yaml文件在node节点上设置pod标签

第二步:设置pod亲和性

此时要满足两个条件:①pod标签不是app1

②拓扑域是yst(节点标签是yst)

两个条件要同时满足,否则处于pending状态

此时各个节点上的node节点标签和pod标签如下:

master

node1

node2

节点标签

yst=200

yst=500

ttt=800

pod标签

app=nginx1

app=nginx1

app=nginx1

②软策略preferredDuringSchedulingIgnoredDuringExecution

要求调度器将pod调度到其他pod的亲和性匹配的节点上,软策略尽量满足这个要求

 DoesNotExist方式分配node节点给pod

第一步:运行一个yaml文件在node节点上设置pod标签

第二步:设置pod亲和性

此时要满足两个条件:①pod标签不是app1

②拓扑域是yst(节点标签是yst)

只能尽量满足,但不是必须满足

此时各个节点上的node节点标签和pod标签如下:

master

node1

node2

节点标签

yst=200

yst=500

ttt=800

pod标签

app=nginx1

app=nginx1

app=nginx1

7pod反亲和性

①软策略

 In方式分配node节点给pod

第一步:运行一个yaml文件在node节点上设置pod标签

\

第二步:设置pod亲和性

此时要满足三个条件:①pod标签是app

②pod标签值是nginx1

②拓扑域是ttt(节点标签是ttt)

只能尽量满足,但不是必须满足

此时各个节点上的node节点标签和pod标签如下:

master

node1

node2

节点标签

yst=200

yst=500

ttt=800

pod标签

app=nginx1

app=nginx1

app=nginx1

②硬策略

 In方式分配node节点给pod

第一步:运行一个yaml文件在node节点上设置pod标签

第二步:设置pod亲和性

此时要满足三个条件:①pod标签是app

②pod标签值是nginx1

②拓扑域是ttt(节点标签是ttt)

三个条件必须同时满足,否则处于pending状态

此时各个节点上的node节点标签和pod标签如下:

master

node1

node2

节点标签

yst=200

yst=500

ttt=800

pod标签

app=nginx1

app=nginx1

app=nginx1

注意事项:

 pod的亲和性策略,在配置时必须加上拓扑域关键字topologyKey(指向的是节点标签)

 pod亲和性策略分为硬策略和软策略

 pod亲和性的NotIn可以替代反亲和性,所以反亲和性很少用

 pod亲和性主要作用是把相关联的pod部署在同一节点

8污点

1)定义:污点和容忍可以配合node节点的亲和性一起使用,污点是node的调度机制,不是pod。被设为污点的节点不会部署pod,污点和亲和性相反,亲和性是尽量选择,设为污点的节点一定不被选择(不一定,看污点类型)

2)污点(taint)类型

①NoSchedule:不会把pod部署在这个节点上

②PreferNoSchedule:尽量避免把pod部署在该节点上(master节点一般设为此污点类型)

NoExecute:把该节点上的所有命名空间的pod全部驱逐出去,且不会调度此节点,系统集群组件不会被驱逐(慎重)【面试】

①基于控制器创建的pod虽然被驱逐,但会在其他节点重新部署

②自主pod会被直接杀死

适用场景:节点服务器需要维护,服务器关机,节点上的所有pod失效,在工作中主要部署pod的方式是基于控制器deployment部署。一旦节点设置为驱逐,控制器创建的pod会在其他节点重新部署

适用于资源回收或节点维护、故障【面试】

3)污点命令

①查看污点

kubectl describe nodes master|grep -i taints

②设置污点

 kubectl taint node node1 key=1:NoSchedule

 kubectl taint node node1 key=1:PreferNoSchedule

 kubectl taint node node1 key1=2:NoExecute

③去除污点

kubectl taint node node1 key:NoSchedule-

 设置NoExecute污点

此时要满足三个条件:①pod标签是app

②pod标签值是nginx1

②拓扑域是yst(节点标签是yst)

三个条件必须同时满足,否则处于pending状态

此时各个节点上的node节点标签和pod标签如下:

master

node1

node2

节点标签

yst=200

yst=500

yst=800

pod标签

app=nginx1

app=nginx1

app=nginx1

原本三个节点均满足条件的节点,但因为在master节点上设置污点NoExecute,把该节点上的pod全部驱逐,并且不会部署pod在此节点上,所以只有node1和node2节点可部署pod

 设置NoSchedule污点

此时要满足三个条件:①pod标签是app

②pod标签值是nginx1

②拓扑域是yst(节点标签是yst)

三个条件必须同时满足,否则处于pending状态

此时各个节点上的节点标签和pod标签如下:

master

node1

node2

节点标签

yst=200

yst=500

yst=800

pod标签

app=nginx1

app=nginx1

app=nginx1

原本三个节点均满足条件的节点,但因为在node1节点上设置污点NoSchedule,不会在该节点上部署pod,所以只有master和node2节点可部署pod

9容忍

1)定义:即使节点上设置了污点,有了容忍机制,依然可以在设置为污点的节点上部署pod

特殊情况:NoExecute依然可以部署pod,但有生命周期,生命周期结束后,会驱逐一部分pod到其他节点,有的pod会保留在污点节点上被销毁重新拉起

2)适用场景:该节点维护完毕,测试该节点是否正常工作

 设置NoSchedule污点的容忍时间

所有节点均设置污点NoSchedule(不能部署pod在污点节点上)

此时满足三个条件仍可部署pod:

①污点标签是key

②污点标签值是1

③污点类型是NoSchedule

此时各个节点上的污点标签如下:

master

node1

node2

污点标签

key=1:NoSchedule

key=2:NoSchedule

key=3:NoSchedule

三个节点均设置了污点标签NoSchedule,该节点不能部署pod,但有了容忍机制,满足条件:污点标签是key、污点标签值是1、污点类型是NoSchedule的节点仍然可以部署pod

 设置NoExecute污点的容忍时间(需指定容忍时间)

此时满足四个条件仍可部署pod:

①污点标签是key

②污点标签值是2

③污点类型是NoExecute

④生命周期60秒(测试环境设置成60秒,生产环境至少10分钟)

此时各个节点上的污点标签如下:

master

node1

node2

污点标签

key=1:NoSchedule

key=2:NoExecute

key=3:NoExecute

设置污点NoSchedule,该节点不能部署pod,

设置污点NoExecute,该节点将所有pod驱逐,不部署pod在该节点,

但有了容忍机制,满足条件:污点标签是key、污点标签值是2、污点类型是NoExecute的节点在生命周期60秒内仍然可以部署pod,一旦生命周期结束pod会重新拉起

3)污点容忍机制

①不指定key:会容忍所有污点的key,但只能容忍指定的污点类型的节点,其他类型的节点仍然不能容忍

此时各个节点上的污点标签如下:

master

node1

node2

污点标签

key=1:NoSchedule

key=2:NoExecute

key=3:NoExecute

设置污点NoSchedule,该节点不能部署pod,

设置污点NoExecute,该节点将所有pod驱逐,不部署pod在该节点,

但有了容忍机制,①不指定key,所以可以容忍所有污点节点②但设置了污点类型,只能在这个类型的污点节点上部署pod

②不指定effect:所有节点都能部署,可以容忍所有节点的污点类型

方式1:


 

此时各个节点上的污点标签如下:

master

node1

node2

污点标签

key=1:NoSchedule

key=2:NoExecute

key=3:NoExecute

设置污点NoSchedule,该节点不能部署pod,

设置污点NoExecute,该节点将所有pod驱逐,不部署pod在该节点,

但有了容忍机制,不指定effect,所有该污点标签为key的都可以部署pod

方式2:

此时各个节点上的污点标签如下:

master

node1

node2

污点标签

key=1:NoSchedule

key=2:NoExecute

key=3:NoExecute

设置污点NoSchedule,该节点不能部署pod,

设置污点NoExecute,该节点将所有pod驱逐,不部署pod在该节点,

但有了容忍机制,不指定effect,所有该污点标签为key的都可以部署pod

4)污点适用场景

多个master节点,设置为PreferNoSchedule,防止资源浪费

业务维护时,master节点上还有业务pod在运行,把该节点的污点设置为NoExecute。一般是基于deployment部署,设置了NoExecute污点会在其他节点上重新部署,并不是被杀死。但自主创建的pod会被杀死,一旦节点恢复一定要去除污点

(10)cordon标记和drain排水(命令行标记节点不可用)

1)cordon直接把节点标记为不可用状态

标记为不可部署状态kubectl cordon master

取消标记不可部署状态kubectl uncordon master

2)drain把该节点下的pod全部转移到其他的node节点上运行

①一旦执行drain,该node节点会变成不可调度状态

②会驱逐该节点上的所有pod

排水为不可部署状态

kubectl drain node1 --ignore-daemonsets --delete-emptydir-data --force

drain

标记node节点为不可调度,然后驱逐pod

--ignore-daemonsets

忽视daemonset部署的pod,daemonset部署的pod还在原节点上(daemonset部署的一般是重要的、后台运行的、系统的pod,不能动)

--delete-local-data

有本地挂载卷的数据会被强制杀死

--force

强制释放不是控制器管理的pod(不是控制器创建的pod被杀死,基于控制器创建的pod被转移)

设置node1排水之后:

取消排水kubectl uncordon node1

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐