1. 简介
-
Scheduler是kubernetes的调度器,主要的任务是把定义的pod分配到集群的节点上。听起来非常简单,但有很多要考虑的问题:
- 公平:如何保证每个节点都能被分配资源
- 资源高效利用:集群所有资源最大化被使用
- 效率:调度的性能要好,能够尽快地对大批量的pod完成调度工作
- 灵活:允许用户根据自己的需求控制调度的逻辑
-
Sheduler是作为单独的程序运行的,启动之后会一直坚挺
API Server
,获取PodSpec.NodeName
为空的pod,对每个pod都会创建一个binding
,表明该pod应该放到哪个节点上
2. 调度过程
-
调度分为几个部分:首先是过滤掉不满足条件的节点,这个过程称为
predicate
;然后对通过的节点按照优先级排序,这个是priority
;最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误。 -
Predicate
有一系列的算法可以使用:PodFitsResources
:节点上剩余的资源是否大于pod清求的资源PodFitsHost
:如果pod指定了NodeName
,检查节点名称是否和NodeName
匹配PodFitsHostPorts
节点上已经使用的port是否和pod申请的port冲突PodSelectorMatches
:过滤掉和pod指定的label不匹配的节点
-
如果在
predicate
过程中没有合适的节点,pod会一直在pending
状态,不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足条件,就继续priorities
过程:按照优先级大小对节点排序。 -
优先级由一系列健值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。这些优先级选项包括:
LeastRequestedPriority
:通过计算CPU和Memory的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点BalancedResourceAllocation
:节点上CPU和Memory使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用ImageLocalityPriority
:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高
-
通过算法对所有的优先级项目和权重进行计算,得出最终的结果
3. 节点亲和性策略:
-
pod.spec.nodeAffinity
preferredDuringSchedulingIgnoredDuringExecution
:软策略requiredDuringSchedulingIgnoredDuringExecution
:硬策略
-
键值运算关系:
In
:label的值在某个列表中NotIn
:label的值不在某个列表中Gt
:label的值大于某个值Lt
:label的值小于某个值Exists
:某个label存在DoesNotExist
:某个label不存在
-
如果
nodeSelectorTerms
下面有多个选项的话,满足任何一个条件就可以了,如果matchExpressions
有多个选项的话,则必须同时满足这些条件才能正常调度POD。
3.1. 硬策略演示:
vim node-affinity-pod-1.yaml
apiVersion: v1 #定义所使用的Kubernetes API的版本
kind: Pod #定义资源类型为Pod
metadata: #包含与Pod相关的元数据信息,例如名称和标签
name: my-nginx #指定Pod的名称
labels: # 为Pod定义标签,用于标识和组织Pod
app: my-nginx
spec: #定义Pod的规范
affinity: #指定节点亲和性配置
nodeAffinity: #定义节点亲和性规则
requiredDuringSchedulingIgnoredDuringExecution: # 指定在调度过程中必须满足的节点亲和性规则
nodeSelectorTerms: #定义节点选择器的条件
- matchExpressions: # 定义节点选择器的匹配表达式
- key: kubernetes.io/hostname #指定用于匹配的节点标签键
operator: NotIn #指定匹配操作符。在此示例中,使用的是NotIn,表示排除具有指定值的节点
values: #指定要排除的节点的值列表。在此示例中,排除名为node1的节点,意思是不能在node1节点创建该pod
- node1
containers: #容器列表
- name: my-nginx #容器名称
image: nginx #容器使用的镜像
//创建pod
[root@master1 scheduler]# kubectl apply -f node-affinity-pod-1.yaml
//查看是否创建成功
[root@master1 scheduler]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx 1/1 Running 0 15s 10.244.3.17 master3 <none> <none>
---可以看的出来该pod不在node1上创建
3.2. 软策略演示:
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
app: my-nginx
spec:
affinity: #指定了Pod的亲和性策略,用于控制Pod与节点的关联
nodeAffinity: #指定了节点亲和性策略
preferredDuringSchedulingIgnoredDuringExecution: #指定了在调度期间优先选择的节点亲和性规则。这里只有一个规则。
- weight: 1 #指定了该规则的权重为1。权重越高,表示越优先选择该规则
preference: #指定了节点亲和性的偏好条件
matchExpressions: #指定了匹配条件,这里使用的是key-value形式的匹配条件
- key: kubernetes.io/hostname #指定了匹配条件的键为"kubernetes.io/hostname",表示选择具有特定主机名的节点。
operator: In #指定了匹配条件的操作符为"In",表示匹配条件中的值在节点的主机名列表中
values: #指定了匹配条件的值为"node2",表示选择主机名为"node2"的节点,意思是,选择在node2创建pod
- node2
containers:
- name: my-nginx
image: nginx
//查看k8s节点情况:
[root@master1 scheduler]# kubectl get node
NAME STATUS ROLES AGE VERSION
master1 Ready control-plane,master 7d3h v1.20.4
master2 Ready control-plane,master 7d3h v1.20.4
master3 Ready control-plane,master 7d3h v1.20.4
node1 Ready <none> 7d3h v1.20.4
--可以看的出来没有node2节点,但是我们这边用的是软策略
--意思是假如有node2节点就在node2节点创建pod,否则换其他节点创建。
//创建pod
[root@master1 scheduler]# kubectl apply -f node-affinity-pod-2.yaml
//查看pod信息:
[root@master1 scheduler]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx 1/1 Running 0 7m39s 10.244.1.62 node1 <none> <none>
4. POD亲和性策略:
-
pod.spec.affinity.podAffinity/podAntiAffinity
preferredDuringSchedulingIgnoredDuringExecution
:软策略requiredDuringSchedulingIgnoredDuringExecution
:硬策略
4.1. 实例一(硬策略):
//创建一个app=my-nginx-1的pod
vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
app: my-nginx-1
containers:
- name: my-nginx
image: nginx
[root@master1 scheduler]# kubectl apply -f pod.yaml
pod/my-nginx created
//用pod亲和性创建pod
vim pod-appinity-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: my-pod-1
spec:
containers:
- name: my-nginx
image: nginx
affinity: #定义了节点亲和性策略
podAffinity: #定义了Pod之间的亲和性规则
requiredDuringSchedulingIgnoredDuringExecution: #指定了在调度Pod时必须满足的亲和性规则
- labelSelector: #定义了要匹配的标签选择器
matchExpressions: #定义了要匹配的标签表达式列表
- key: app #定了要匹配的标签的键为app
operator: In #指定了匹配操作符为"In",表示标签的值必须在给定的值列表中
values: #指定了匹配的标签值列表,这里是my-nginx-1
- my-nginx-1
topologyKey: kubernetes.io/hostname #指定了要匹配的拓扑域的键,这里是节点的主机名,意思是和满足app=my-nginx-1的pod在一个节点上创建
[root@master1 scheduler]# kubectl get pod --show-labels -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
my-nginx 1/1 Running 0 6m36s 10.244.1.63 node1 <none> <none> app=my-nginx-1
---可以看的出来标签app=my-nginx-1的pod在node1节点创建,所以接下来我们要创建的pod应该也在node1上创建。
//创建
[root@master1 scheduler]# kubectl apply -f pod-appinity-1.yaml
//查看pod信息
[root@master1 scheduler]# kubectl get pod --show-labels -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
my-nginx 1/1 Running 0 9m39s 10.244.1.63 node1 <none> <none> app=my-nginx-1
my-pod 1/1 Running 0 10m 10.244.1.64 node1 <none> <none> app=my-pod-1
4.2. 实例二(软策略):
vim pod-appinity-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-app
labels:
app: my-app-1
spec:
containers:
- name: my-nginx
image: nginx
affinity: #定义了Pod的亲和性规则
podAntiAffinity: #定义了Pod的反亲和性规则,用于控制Pod在调度时的位置
preferredDuringSchedulingIgnoredDuringExecution: #定义了优先级较高的Pod反亲和性规则
- weight: 1 #定义了规则的权重,用于在多个规则之间进行优先级排序
podAffinityTerm: #定义了亲和性的相关条件
labelSelector: #定义了用于选择符合条件的Pod的标签选择器
matchExpressions: #定义了一组用于匹配标签的表达式
- key: app #定义了要匹配的标签的键为app
operator: In #定义了匹配操作符,比如In表示匹配标签的值在指定的值列表中
values: #定义了用于匹配的标签值列表
- my-nginx-1
topologyKey: kubernetes.io/hostname #定义了用于选择节点的拓扑键
---上面的亲和性规则的意思是:创建不和匹配app=my-nginx-1的pod在一个节点上创建。
//创建:
[root@master1 scheduler]# kubectl apply -f pod-appinity-2.yaml
pod/my-app created
//查看pod是否创建成功
[root@master1 scheduler]# kubectl get pod --show-labels -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
my-app 1/1 Running 0 6m56s 10.244.3.18 master3 <none> <none> app=my-app-1
my-nginx 1/1 Running 0 28m 10.244.1.63 node1 <none> <none> app=my-nginx-1
my-pod 1/1 Running 0 29m 10.244.1.64 node1 <none> <none> app=my-pod-1
- 亲和性/反亲和性调度策略比较如下:
调度策略 | 匹配标签 | 操作符 | 拓扑域支持 | 调度目标 |
---|---|---|---|---|
nodeAffinity | 主机 | In、NotIn、Exists、DoesNotExist、Gt、Lt | 是 | 指定主机 |
podAffinity | POD | In、NotIn、Exists、DoesNotExist | 是 | POD与指定POD同一拓扑域 |
podAntiAffinity | POD | In、NotIn、Exists、DoesNotExist | 是 | POD与指定POD不在同一拓扑域 |