目录html
Scheduler调度器作为Kubernetes三大核心组件之一, 承载着整个集群资源的调度功能,其根据特定调度算法和策略,将Pod调度到最优工做节点上,从而更合理与充分的利用集群计算资源。 其做用是根据特定的调度算法和策略将Pod调度到指定的计算节点(Node)上,其作为单独的程序运行,启动以后会一直监听API Server,获取PodSpec.NodeName为空的Pod,对每一个Pod都会建立一个绑定。 默认状况下,k8s的调度器采用扩散策略,将同一集群内部的pod对象调度到不一样的Node节点,以保证资源的均衡利用。 完成调度操做的步骤:节点预选(Predicate)、节点优先级排序(Priority)、节点择优(Select) |
Predicates是强制性规则,用来形容主机匹配Pod所须要的资源,若是没有任何主机知足该Predicates, 则该Pod会被挂起,直到有主机可以知足。 |
Kubernetes调度器做为集群的大脑,在如何提升集群的资源利用率、保证集群中服务的稳定运行中也会变得愈来愈重要Kubernetes的资源分为两种属性。node
可压缩资源(例如CPU循环,Disk I/O带宽)都是能够被限制和被回收的,对于一个Pod来讲能够下降这些资源的使用量而不去杀掉Pod。python
不可压缩资源(例如内存、硬盘空间)通常来讲不杀掉Pod就无法回收。将来Kubernetes会加入更多资源,如网络带宽,存储IOPS的支持。算法
预选策略 | 做用 |
---|---|
CheckNodeCondition | 检查是否能够在节点报告磁盘、网络不可用或未准备好时将Pod调度其上 |
HostName | 若是Pod对象拥有spec.hostname属性,则检查节点名称字符串是否和该属性值匹配。 |
PodFitsHostPorts | Pod的spec.hostPort属性时,检查端口是否被占用 |
MatchNodeSelector | Pod的spec.nodeSelector属性时,检查节点标签 |
NoDiskConflict | Pod请求的存储卷在此节点是否可用 |
PodFitsResources | 检查节点上的资源(CPU、内存)可用性是否知足Pod对象的运行需求。 |
PodToleratesNodeTaints | Pod的spec.tolerations属性,仅关注NoSchedule和NoExecute两个效用标识的污点 |
PodToleratesNodeNoExecuteTaints | Pod的spec.tolerations属性,是否能接纳节点的NoExecute类型污点 |
CheckNodeLabelPresence | 仅检查节点上指定的全部标签的存在性 |
CheckServiceAffinity | 将相同Service的Pod对象放置在同一个或同一类节点上以提升效率 |
MaxEBSVolumeCount | 检查节点已挂载的EBS存储卷数量是否超过设置的最大值,默认为39 |
MaxGCEPDVolumeCount | 检查节点上已挂载的GCE PD 存储卷数量是否超过最大值,默认为16 |
MaxAzureDiskVolumeCount | 检查节点上已挂载的Azure Disk存储卷数量是否超过最大值,默认为16 |
CheckVolumeBinding | 检查节点上已绑定和未绑定的PVC是否知足需求 |
NoVolumeZoneConflict | 在给定区域zone限制下,检查此节点部署的Pod对象是否存在存储卷冲突 |
CheckNodeMemoryPressure | 若给定节点已报告内存资源压力过大,检查当前Pod是否可调度至该节点 |
CheckPodePIDPressure | 检查节点PID资源压力 |
CheckNodeDiskPressure | 检查节点磁盘资源压力 |
MatchInterPodAffinity | 检查节点是否知足Pod对象亲和性或反亲和性条件 |
函数名称 | 详细说明 |
---|---|
LeastRequestedPriority | 节点的优先级就由节点空闲资源与节点总容量的比值,即由(总容量-节点上Pod的容量总和-新Pod的容量)/总容量)来决定。 CPU和内存具备相同权重,资源空闲比越高的节点得分越高。 cpu((capacity – sum(requested)) * 10 / capacity) + memory((capacity – sum(requested)) * 10 / capacity) / 2 |
BalancedResourceAllocation | CPU和内存使用率越接近的节点权重越高,该策略不能单独使用,必须和LeastRequestedPriority组合使用,尽可能选择在部署Pod后各项资源更均衡的机器。 若是请求的资源(CPU或者内存)大于节点的capacity,那么该节点永远不会被调度到。 |
InterPodAffinityPriority | 经过迭代 weightedPodAffinityTerm 的元素计算和,而且若是对该节点知足相应的PodAffinityTerm,则将 “weight” 加到和中,具备最高和的节点是最优选的。 |
SelectorSpreadPriority | 为了更好的容灾,对同属于一个service、replication controller或者replica的多个Pod副本,尽可能调度到多个不一样的节点上。 若是指定了区域,调度器则会尽可能把Pod分散在不一样区域的不一样节点上。当一个Pod的被调度时,会先查找Pod对于的service或者replication controller, 而后查找service或replication controller中已存在的Pod,运行Pod越少的节点的得分越高。 |
NodeAffinityPriority | 亲和性机制。Node Selectors(调度时将pod限定在指定节点上), 支持多种操做符(In, NotIn, Exists, DoesNotExist, Gt, Lt),而不限于对节点labels的精确匹配。 另外支持两种类型的选择器,一种是“hard(requiredDuringSchedulingIgnoredDuringExecution)”选择器, 它保证所选的主机必须知足全部Pod对主机的规则要求。 这种选择器更像是以前的nodeselector,在nodeselector的基础上增长了更合适的表现语法。 另外一种是“soft(preferresDuringSchedulingIgnoredDuringExecution)”选择器, 它做为对调度器的提示,调度器会尽可能但不保证知足NodeSelector的全部要求。 |
NodePreferAvoidPodsPriority(权重1W) | 若是 节点的 Anotation 没有设置 key-value:scheduler. alpha.kubernetes.io/ preferAvoidPods = "...",则节点对该 policy 的得分就是10分, 加上权重10000,那么该node对该policy的得分至少10W分。若是Node的Anotation设置了, scheduler.alpha.kubernetes.io/preferAvoidPods = "..." ,若是该 pod 对应的 Controller 是 ReplicationController 或 ReplicaSet, 则该 node 对该 policy 的得分就是0分。 |
TaintTolerationPriority | 使用 Pod 中 tolerationList 与 节点 Taint 进行匹配,配对成功的项越多,则得分越低。 |
ImageLocalityPriority | 根据Node上是否存在一个pod的容器运行所需镜像大小对优先级打分,分值为0-10。遍历所有Node, 若是某个Node上pod容器所需的镜像一个都不存在,分值为0; 若是Node上存在Pod容器部分所需镜像,则根据这些镜像的大小来决定分值,镜像越大,分值就越高;若是Node上存在pod所需所有镜像,分值为10。 |
EqualPriority | 是一个优先级函数,它给予全部节点相等权重。 |
MostRequestedPriority | 在 ClusterAutoscalerProvider 中,替换 LeastRequestedPriority,给使用多资源的节点,更高的优先级。 计算公式为: (cpu(10 sum(requested) / capacity) + memory(10 sum(requested) / capacity)) / 2 |
节点亲和性规则:硬亲和性 required 、软亲和性 preferred。centos
# 调度至 zone = foo 的节点 kubectl label nodes kube-node1 zone=foo
apiVersion: v1 kind: Pod metadata: name: with-required-nodeaffinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: # 定义硬亲和性 nodeSelectorTerms: - matchExpressions: - {key: zone,operator: In,values: ["foo"]} containers: - name: myapp image: ikubernetes/myapp:v1
可有多个nodeSelectorTerms,相互间为逻辑或关系 同个nodeSelectorTerms下可有多个matchExpressions,各matchExpressions间为逻辑与关系 同个matchExpressions下可有多条标签选择规则,相互间为逻辑与关系 节点亲和性仅是节点预选策略中的一项,其余预选策略依然生效 |
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy-with-node-affinity spec: replicas: 2 selector: matchLabels: app: myapp template: metadata: name: myapp-pod labels: app: myapp spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 60 preference: matchExpressions: - {key: zone, operator: In, values: ["foo"]} - weight: 30 preference: matchExpressions: - {key: ssd, operator: Exists, values: []} containers: - name: myapp image: ikubernetes/myapp:v1
亲和性
,将一些Pod对象组织在相近的位置(同一节点、机架、区域、地区)反亲和性
,将一些Pod在运行位置上隔开调度器将第一个Pod放置于任何位置,而后与其有亲和或反亲和关系的Pod据此动态完成位置编排
# 基于MatchInterPodAffinity
预选策略完成节点预选,基于InterPodAffinityPriority
优选函数进行各节点的优选级评估api
位置拓扑,定义"同一位置"tomcat
Pod亲和性描述一个Pod与具备某特征的现存Pod运行位置的依赖关系;即须要事先存在被依赖的Pod对象网络
# 被依赖Pod kubectl run tomcat -l app=tomcat --image tomcat:alpine kubectl explain pod.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.topologyKey
apiVersion: v1 kind: Pod metadata: name: with-pod-affinity spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: # 硬亲和调度 - labelSelector: matchExpressions: - {key: app, operator: In, values: ["tomcat"]} # 选择被依赖Pod topologyKey: kubernetes.io/hostname # 根据挑选出的Pod全部节点的hostname做为同一位置的断定 containers: - name: myapp image: ikubernetes/myapp:v1
调度器先基于标签选择器查询拥有匹配标签的全部被依赖Pod,再获取它们所属节点的topologyKey指示的属性的标签值,再查询全部拥有匹配这些标签值的全部节点,从而完成节点预选,再根据优选函数计算节点优先级,挑选出运行新建Pod的节点 若节点标签在运行时发生更改,再也不知足Pod亲和性规则时,该Pod会继续运行;即仅对亲建的Pod生效 |
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-with-preferred-pod-affinity spec: replicas: 3 selector: matchLabels: app: myapp template: metadata: name: myapp labels: app: myapp spec: affinity: podAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 podAffinityTerm: labelSelector: matchExpressions: - {key: app, operator: In, values: ["cache"]} topologyKey: zone - weight: 20 podAffinityTerm: labelSelector: matchExpressions: - {key: app, operator: In, values: ["db"]} topologyKey: zone containers: - name: myapp image: ikubernetes/myapp:v1
Pod反亲和调度用于分散同一类应用,调度至不一样的区域、机架或节点等
将 spec.affinity.podAffinity
替换为 spec.affinity.podAntiAffinity
app
反亲和调度也分为柔性约束和强制约束ide
apiVersion: v1 kind: Pod metadata: name: pod-first labels: app: myapp tier: fronted spec: containers: - name: myapp image: ikubernetes/myapp:v1 --- apiVersion: v1 kind: Pod metadata: name: pod-second labels: app: backend tier: db spec: containers: - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent command: ["/bin/sh", "-c", "sleep 3600"] affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - {key: app, operator: In, values: ["myapp"]} topologyKey: zone
污点 taints 是定义在节点
上的键值型属性数据,用于让节点拒绝将Pod调度运行于其上,除非Pod有接纳节点污点的容忍度容忍度 tolerations 是定义在Pod
上的键值属性数据,用于配置可容忍的污点,且调度器将Pod调度至其能容忍该节点污点的节点上或没有污点的节点上
使用PodToleratesNodeTaints
预选策略和TaintTolerationPriority
优选函数完成该机制
污点定义于nodes.spec.taints
容忍度定义于pods.spec.tolerations
语法: key=value:effect
NoSchedule
,不能容忍,节点现存Pod不受影响PreferNoSchedule
,柔性约束,节点现存Pod不受影响NoExecute
,不能容忍,当污点变更时,Pod对象会被驱逐一个节点可配置多个污点,一个Pod也可有多个容忍度
同一个键值数据,effect不一样,也属于不一样的污点
kubectl taint node <node-name> <key>=<value>:<effect>
kubectl get nodes <nodename> -o go-template={{.spec.taints}}
kubectl taint node <node-name> <key>[:<effect>]- kubectl patch nodes <node-name> -p '{"spec":{"taints":[]}}' kubectl taint node kube-node1 node-type=production:NoSchedule kubectl get nodes kube-node1 -o go-template={{.spec.taints}}
# 删除key为node-type,effect为NoSchedule的污点 kubectl taint node kube-node1 node-type:NoSchedule- # 删除key为node-type的全部污点 kubectl taint node kube-node1 node-type- # 删除全部污点 kubectl patch nodes kube-node1 -p '{"spec":{"taints":[]}}'
spec.tolerations
字段添加
tolerationSeconds
用于定义延迟驱逐Pod的时长
# 等值判断 tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute" tolerationSeconds: 3600 # 存在性判断 tolerations: - key: "key1" operator: "Exists" effect: "NoExecute" tolerationSeconds: 3600
上面两个例子表示若是某个Node存在key1=value1的污点或者存在key1的污点,Pod将不会调度到这样的节点。 |
apiVersion: v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 tolerations: - key: "node-type" operator: "Equal" value: "production": effect: "NoExecute" tolerationSeconds: 3600
自动为节点添加污点信息,使用NoExecute效用标识,会驱逐现有Pod
K8s核心组件一般都容忍此类污点
node.kubernetes.io/not-ready 节点进入NotReady状态时自动添加
node.alpha.kubernetes.io/unreachable 节点进入NotReachable状态时自动添加
node.kubernetes.io/out-of-disk 节点进入OutOfDisk状态时自动添加
node.kubernetes.io/memory-pressure 节点内存资源面临压力
node.kubernetes.io/disk-pressure 节点磁盘面临压力
node.kubernetes.io/network-unavailable 节点网络不可用
node.cloudprovider.kubernetes.io/uninitialized kubelet由外部云环境程序启动时,自动添加,待到去控制器初始化此节点时再将其删除
优选级,Pod对象的重要程度
优选级会影响节点上Pod的调度顺序和驱逐次序
一个Pod对象没法被调度时,调度器会尝试抢占(驱逐)较低优先级的Pod对象,以即可以调度当前Pod
Pod优选级和抢占机制默认处于禁用状态
启用:同时为kube-apiserver、kube-scheduler、kubelet程序的 --feature-gates 添加 PodPriority=true
使用:
事先建立优先级类别,并在建立Pod资源时经过 priorityClassName属性指定所属的优选级类别
https://pdf.us/2019/04/08/3222.html
https://www.cnblogs.com/centos-python/articles/10884738.html