pod调度
pod调度
NodeSelector 定向调度
将Pod调度到指定的一些Node上, 可以通过Node的标签(Label) 和Pod的nodeSelector属性相匹配来实现。
如果我们给多个Node都定义了相同的标签(例如zone=north) , 则scheduler会根据调度算法从这组Node中挑选一个可用的Node进行Pod调度。
如果我们指定了Pod的nodeSelector条件, 且在集群中不存在包含相应标签的Node, 则即使在集群中还有其他可供使用的Node, 这个Pod也无法被成功调度。
NodeAffinity: Node亲和性调度
RequiredDuringSchedulingIgnoredDuringExecution
必须满足指定的规则才可以调度Pod到Node上(功能与nodeSelector很像, 但是使用的是不同的语法), 相当于硬限制
PreferredDuringSchedulingIgnoredDuringExecution
强调优先满足指定规则, 调度器会尝试调度Pod到Node上, 但并不强求, 相当于软限制。 多个优先级规则还可以设置权重(weight) 值, 以定义执行的先后顺序。
IgnoredDuringExecution的意思是: 如果一个Pod所在的节点在Pod运行期间标签发生了变更, 不再符合该Pod的节点亲和性需求, 则系统将忽略Node上Label的变化, 该Pod能继续在该节点运行
1 | apiVersion: v1 |
NodeAffinity语法支持的操作符包括In、 NotIn、 Exists、 DoesNotExist、 Gt、 Lt。
注意事项:
- 如果同时定义了nodeSelector和nodeAffinity, 那么必须两个条件都得到满足, Pod才能最终运行在指定的Node上。
- 如果nodeAffinity指定了多个nodeSelectorTerms, 那么其中一个能够匹配成功即可。
- 如果在nodeSelectorTerms中有多个matchExpressions, 则一个节点必须满足所有matchExpressions才能运行该Pod。
PodAffinity: Pod亲和与互斥调度策略
如果在具有标签X的Node上运行了一个或者多个符合条件Y的Pod, 那么Pod应该(如果是互斥的情况, 那
么就变成拒绝) 运行在这个Node上。
这里X指的是一个集群中的节点、 机架、 区域等概念, 通过Kubernetes内置节点标签中的key来进行声明。 这个key的名字为topologyKey, 意为表达节点所属的topology范围。
- kubernetes.io/hostname
- failure-domain.beta.kubernetes.io/zone
- failure-domain.beta.kubernetes.io/region
和节点亲和相同, Pod亲和与互斥的条件设置也是requiredDuringSchedulingIgnoredDuringExecution和
preferredDuringSchedulingIgnoredDuringExecution。 Pod的亲和性被定义于PodSpec的affinity字段下的podAffinity子字段中。 Pod间的互斥性则被定义于同一层次的podAntiAffinity子字段中。
1 | # 参照pod |
Pod亲和性的操作符也包括In、 NotIn、 Exists、DoesNotExist、 Gt、 Lt。
出于性能和安全方面的考虑, 对topologyKey有如下限制:
- 在Pod亲和性和RequiredDuringScheduling的Pod互斥性的定义中, 不允许使用空的topologyKey。
- 如果Admission controller包含了LimitPodHardAntiAffinityTopology, 那么针对Required DuringScheduling的Pod互斥性定义就被限制为kubernetes.io/hostname, 要使用自定义的topologyKey, 就要改写或禁用该控制器。
- 在PreferredDuringScheduling类型的Pod互斥性定义中, 空的topologyKey会被解释为kubernetes.io/hostname、 failuredomain.beta.kubernetes.io/zone及failuredomain.beta.kubernetes.io/region的组合
PodAffinity规则设置的注意事项如下:
除了设置Label Selector和topologyKey, 用户还可以指定Namespace列表来进行限制, 同样, 使用Label Selector对Namespace进行选择。 Namespace的定义和Label Selector及topologyKey同级。
在所有关联requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全都满足之后, 系统才能将Pod调度到某个Node上
Taints和Tolerations( 污点和容忍)
Taint它让Node拒绝Pod的运行,Taint需要和Toleration配合使用, 让Pod避开那些不合适的Node。 在Node上设置一个或多个Taint之后, 除非Pod明确声明能够容忍这些污点, 否则无法在这些Node上运行。 Toleration是Pod的属性, 让Pod能够( 注意, 只是能够, 而非必须) 运行在标注了Taint的Node上。
1 | 用kubectl taint命令为Node设置Taint信息 |
1 | # 在Pod上声明Toleration(如果不指定operator, 则默认值为Equal) |
Kubernetes调度器处理多个Taint和Toleration的逻辑顺序为:首先列出节点中所有的Taint, 然后忽略Pod的Toleration能够匹配的部分, 剩下的没有忽略的Taint就是对Pod的效果 ,以下情况需要注意:
- 如果在剩余的Taint中存在effect=NoSchedule, 则调度器不会把该Pod调度到这一节点上
- 如果在剩余的Taint中没有NoSchedule效果, 但是有PreferNoSchedule效果, 则调度器会尝试不把这个Pod指派给这个节点
- 如果在剩余的Taint中有NoExecute效果, 并且这个Pod已经在该节点上运行, 则会被驱逐; 如果没有在该节点上运行, 则也不会再被调度到该节点上
应用场景:
- 独占节点
- 具有特殊硬件设备的节点
- 定义Pod驱逐行为, 以应对节点故障
Pod Priority Preemption: Pod优先级调度
Pod优先级调度(抢占式调度 )(1.14默认开启)
提高资源利用率的常规做法是采用优先级方案, 即不同类型的负载对应不同的优先级, 同时允许集群中的所有负载所需的资源总量超过集群可提供的资源, 在这种情况下, 当发生资源不足的情况时, 系统可以选择释放一些不重要的负载(优先级最低的) , 保障最重要的负载能够获取足够的资源稳定运行。
Eviction(驱逐)是kubelet进程的行为 ;Preemption(抢占)则是Scheduler执行的行为
1 | # 创建优先级 |
DaemonSet: 在每个Node上都调度一个Pod
1 | apiVersion: extensions/v1beta1 |
DaemonSet支持滚动升级
Job: 批处理调度
按照批处理任务实现方式的不同,批处理任务可以分为:
- Job Template Expansion模式: 一个Job对象对应一个待处理的Work item, 有几个Work item就产生几个独立的Job, 通常适合Work item数量少、 每个Work item要处理的数据量比较大的场景
- Queue with Pod Per Work Item模式: 采用一个任务队列存放Work item, 一个Job对象作为消费者去完成这些Work item, 在这种模式下, Job会启动N个Pod, 每个Pod都对应一个Work item
- Queue with Variable Pod Count模式: 也是采用一个任务队列存放Work item, 一个Job对象作为消费者去完成这些Work item, 但与上面的模式不同, Job启动的Pod数量是可变的
考虑到批处理的并行问题, Kubernetes将Job分以下三种类型 :
- Non-parallel Jobs: 通常一个Job只启动一个Pod, 除非Pod异常, 才会重启该Pod, 一旦
此Pod正常结束, Job将结束 - Parallel Jobs with a fixed completion count: 并行Job会启动多个Pod, 此时需要设定Jo的.spec.completions参数为一个正数, 当正常结束的Pod数量达至此参数设定的值后, Job结束。此外, Job的.spec.parallelism参数用来控制并行度, 即同时启动几个Job来处理Work Item
- Parallel Jobs with a work queue: 任务队列方式的并行Job需要一个独立的Queue, Work item都在一个Queue中存放, 不能设置Job的.spec.completions参数
Cronjob: 定时任务
1 | apiVersion: batch/v2alpha1 |