k8s学习(八)-- 调度器
学习目标:掌握调度器原理,能够根据要求把pod定义到想要的节点运行
一、简介:
A、Scheduler是作为单独的程序运行的,启动之后会一直坚挺API Server,获取Pod.Spec.NodeName为空的pod,对每个pod都会创建一个binding,表明该pod应该放在哪个节点上。
二、调度过程
A、调度分为几个部分,首先是过滤掉不满足条件的节点,这个过程成为predicate。然后对通过的节点按照优先级排序,这个是priority;最后从中选择优先级最高的节点。如果中间任何一步骤有错,就直接返回错误。
1. predicate算法:
a. PodFitsResources:节点上剩余的资源是否大于pod请求的资源。
b. PodFitsHost:如果pod指定了NodeName,检查节点名称和NodeName是否匹配
c. PodFitsHostPorts:节点上已经使用的port是否和pod申请的port冲突
d. PodSelectorMatches:过滤掉和pod指定的label不匹配的节点。
e. NoDiskConflict:已经mount的volume和pod指定的volume不冲突,除非它们都是只读
2. 如果在predicate过程中没有合适的节点,pod会一直处于pending状态,不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足要求,就继续priority过程:按照优先级大小对节点排序,优先级由一系列键值对组成,键是该优先级的名称,值是它的权重(该项的重要性)。这些优先级选项包括:
a. LeastRequestedPriority:通过计算CPU和Memory的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点。
b. BalancedResourceAllocation:节点上CPU和Memory使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用。
c. ImageLocalityPriority:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高。
通过算法对所有的优先级项目和权重进行计算,得出最终结果。
三、调度亲和性
A、节点亲和性
1. pod.spec.nodeAffinity
a. preferredDuringSchedulingIgnoredDuringExecution:软策略
apiVersion: v1
kind: Pod
metadata:
name: preferred-node-affinity-pod
labels:
app: preferred-node-affinity-pod
spec:
containers:
- name: node-affinity-container
image: hub.atguigu.com/library/myapp:v1
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-node02
b. requiredDuringSchedulingIgnoredDuringExecution:硬策略
apiVersion: v1
kind: Pod
metadata:
name: node-affinity-pod
labels:
app: node-affinity-pod
spec:
containers:
- name: node-affinity-container
image: hub.atguigu.com/library/myapp:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- k8s-node02
3. 键值运算关系
a. In:label的值在某个列表中
b. NotIn:label的值不在某个列表中
c. Gt:label的值大于某个值
d. Lt:label的值小于某个值
e. Exists:某个label存在
f. DoesNotExist:某个label不存在
4. 注意:如果nodeSelectorTerms下面有多个选项的话,满足任何一个条件就可以了;如果matchExperssions有多个选项的话,则必须同时满足这些条件才能正常调度
B、Pod亲和性
1. pod.spec.affinity.podAffinity/podAntiAffinity(在一个拓扑域/不在一个拓扑域)
a. preferredDuringSchedulingIgnoredDuringExecution:软策略
apiVersion: v1
kind: Pod
metadata:
name: preferred-pod-affinity-pod
labels:
app: preferred-pod-affinity-pod
spec:
containers:
- name: preferred-pod-affinity-container
image: hub.atguigu.com/library/myapp:v1
imagePullPolicy: IfNotPresent
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- test-pod1
topologyKey: kubernetes.io/hostname
b. requiredDuringSchedulingIgnoreDuringExecution:硬策略
apiVersion: v1
kind: Pod
metadata:
name: required-pod-affinity-pod
labels:
app: required-pod-affinity-pod
spec:
containers:
- name: required-pod-affinity-container
image: hub.atguigu.com/library/myapp:v1
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- test-pod1
topologyKey: kubernetes.io/hostname
2. 拓扑域(选择的标签相同的一组node就是一个拓扑域)
四、Taint和Toleration(污点和容忍)
A、节点亲和性,是pod的一种属性(偏好或硬性要求),它使pod被吸引到一类特定的节点。Taint则相反,它使节点能够排斥一类特定的pod。taint和toleration互相配合,可以用来避免pod被分配到不合适的节点上。每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的pod,是不会被该节点接受的。如果将toleration应用于pod上,则表示这些pod可以(但不要求)被调度到具有匹配taint的节点上
B、Taint(污点)
1. 污点的组成
a. 使用kubectl taint命令可以给某个node节点设置污点,node被设置上污点之后就和pod之间存在了一种互斥的关系,可以让node拒绝pod的调度执行,甚至将已经存在的pod驱逐出去
b. 组成:key=value:effect,每个污点有一个key和value作为污点的标签,其中value可以为空,effect描述污点的作用。当前taint effect有以下三种:
1) NoSchedule:表示k8s将不会将pod调度至具有该污点的node上
2)PreferNoSchedule:表示k8s将尽量避免将pod调度至该pod上
3)NoExecute:表示k8s将不会将pod调度到具有该污点的node上,同时会将Node上已经存在的Pod驱逐出去
2. 污点的设置、查看和去除
a. 设置污点
kubectl taint nodes node1 key1=value1:NoSchedule
b. 查看污点
kubectl describe node node-name(查找Taints字段)
c. 去除污点
kubectl taint nodes node1 key1:NoSchedule-
C、容忍
1. 设置了污点的node将根据taint的effect:NoSchedule、PreferNoSchedule、NoExecute和pod之间产生互斥关系,Pod将在一定程度上不会被调度到Node上。但我们可以在pod上设置容忍(toleration),意思是设置了容忍的pod将可以容忍污点的存在,可以被调度到存在污点的ode上。
2. 例子
apiVersion: v1
kind: Pod
metadata:
name: test-pod1
labels:
app: test-pod1
spec:
containers:
- name: test-pod1-container
image: hub.atguigu.com/library/myapp:v1
tolerations:
- key: "app"
operator: "Equal"
value: "test-pod1"
effect: "NoExecute"
tolerationSeconds: 120
其中key、value、effect要与node上设置的taint保持一致
operato的值为Exists会忽略value值
tolerationSeconds用于描述当pod需要被驱逐时还可以在pod上继续保留运行的时间
3. 当不指定key时,表示容忍所有的污点key:
toleration:
- operator: "Exists"
4. 当不指定effect值时,表示容忍所有的污点作用
toleration:
- key: "key"
operator: "Exists"
5. 有多个master时,为了防止资源浪费,可以如下设置
kubectl taint odes Node-Name node-role.kubernetes.io/master=:PreferNoSchedule
五、指定调度节点
A、Pod.spec.nodeName将pod直接调度到指定的node节点上,会跳过schedule的调度策略,该匹配是最强匹配
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: node-name-schedule-deployment
spec:
replicas: 7
template:
metadata:
name: node-name-schedule-pod
labels:
app: node-name-schedule-label
spec:
nodeName: k8s-node01
containers:
- name: node-name-schedule-container
image: hub.atguigu.com/library/myapp:v1
ports:
- containerPort: 80
B、Pod.spec.nodeSelector:通过kubernetes的label-selector机制选择节点,由调度器调度策略匹配label,而后调度pod到目标节点,该匹配规则属于强制约束
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: node-selector-deployment
spec:
replicas: 2
template:
metadata:
name: node-selector-pod
labels:
app: node-selector-pod-label
spec:
nodeSelector:
disk: ssd
containers:
- name: node-selector-container
image: hub.atguigu.com/library/myapp:v1
ports:
- containerPort: 80