初探认识Scheduler
一、调度简介
在开始之前,先来看看kubernetes的架构图,其中控制节点包含三大组件,kube-apiserver、kube-controller-manager、kube-scheduler。
kube-scheduler是kubernetes的核心组件之一,其主要负责Pod的调度、监听kube-apiserver,查询未分配Node的Pod,根据配置的调度策略,将Pod调度到最优的工作节点上,从而高效、合理的利用集群资源。
二、Scheduler解决了什么问题
==kube-scheduler==负责将Pod调度到集群内的最佳节点上,其监听kube-apiserver,查询还未分配Node的Pod,然后根据调度策略为这些Pod分配节点,执行绑定节点的操作。
在上述流程中,需要考虑到以下几点问题
- Node公平性
- 如何保证每个Node都会被分配到Pod资源
资源利用性
- 如何确保节点资源分配的高效性,使每个节点资源被合理利用
调度性能性
- 在短时间内对大量Pod进行分批调度
用户灵活性
- 允许用户根据自己或业务需求控制调度逻辑
三、调度方式
3.1 kubernetes默认调度
kubernetes调度分为几个流程:
首先是过滤掉不满足条件的节点,这个过程被称为Predicate,支持的算法有以下几种;
PodFitsResources
- 节点上剩余的资源是否大于Pod请求的资源。
PodFitsHost
- 如果Pod指定了NodeName,检查节点名称是否和NodeName一致。
PodFitsHostPorts
- 节点上已经使用的port是否和pod申请的port冲突
PodSelectorMatches
- 过滤掉和Pod指定label不匹配节点
NoDiskConflict
- 已经mount的volume和Pod指定的volume不冲突(排除只读的策略)
- 然后对通过的节点进行优先级排序,这个过程被称为Priority;
- 最后从中选择优先级最高的节点
如果中间任何一步有错误,就会直接返回异常。如果在Predicate过程中没有找到合适的节点,Pod会一直处于Pending状,不断重试调度,直到所节点满足条件。经过这个步骤。如果有多个节点满足条件,就继续priorities过程,按照优先级大小对节点排序。
3.2 亲和力调度
亲和力包括节点亲和力及Pod亲和力,表示我们部署的服务更加倾向于运行在哪些节点上,对服务的部署有一定的可控性。
3.2.1 节点亲和力
pod.spec.nodeAffinity
- 运算符关系
运算关系 | 说明 |
---|---|
In | label的值在某个列表中 |
NotIn | label的值不在某个列表中 |
Gt | label的值大于某个值 |
Lt | label的值小于某个值 |
Exists | 某个label存在 |
DoesNotExist | 某个label不存在 |
- 每个节点都有自己的标签
[root@node1 kube-state-metrics]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
10.22.33.104 Ready <none> 28d v1.21.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.22.33.104,kubernetes.io/os=linux
10.22.33.105 Ready <none> 28d v1.21.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.22.33.105,kubernetes.io/os=linux
10.22.33.106 Ready <none> 28d v1.21.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=10.22.33.106,kubernetes.io/os=linux
硬策略 requiredDuringSchedulingIgnoredDuringExecution
apiVersion: v1 kind: Pod metadata: name: affinity labels: app: node-affinity-pod spec: containers: - name: with-node-affinity image: devops.wangtianci/open/grafana:v8.45 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: NotIn values: - k8s-node01 //主机名不是k8s-node01即可
软策略 preferredDuringSchedulingIgnoredDuringExecution
apiVersion: v1 kind: Pod metadata: name: affinity labels: app: node-affinity-pod spec: containers: - name: with-node-affinity image: devops.wangtianci/open/grafana:v8.45 affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: source operator: In values: - k8s-node03 //主机名是k8s-node03即可
3.2.2 Pod亲和力
pod.spec.affinity.podAffinity/podAntiAffinity
- 软策略
spec: hostNetwork: false hostIPC: false affinity: podAffinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: kafka app.kubernetes.io/instance: wtc app.kubernetes.io/component: kafka namespaces: - "default" topologyKey: kubernetes.io/hostname weight: 1
3.2.3 亲和力与反亲和力对比
运算关系 | 匹配标签 | 操作符 | 调度目标 |
---|---|---|---|
nodeAffinity | 主机 | In、NotIn、Exists、DoesNotExist、Gt、Lt | 主机 |
podAffinity | pod | In、NotIn、Exists、DoesNotExist | Pod与指定Pod在同一域 |
podAntiAffinity | pod | In、NotIn、Exists、DoenNotExist | Pod与指定Pod在非同一域 |
3.3 污点调度
节点亲和力时间Pod的一种属性,它使Pod被吸引到一类特点的节点。污点(Taint)则相反,它是节点能排斥一类特有的Pod
3.3.1 污点
kubectl taint可以给某个Node节点设置污点,Node被设置上污点之后就和Pod之间存在了一种相斥的关系,可以让Node节点拒绝Pod的调度执行,升至将Node已经存在的Pod驱逐出去。污点的数据结构如下
key=value:effect
每一个污点有一个key和value作为污点的标签,其中value可以为空,effect描述污点的作用,总共有3个值
NoSchedule
- k8s将不会把Pod调度到具有该污点的Node上
PreferNoSchedule
- k8s将尽量避免把Pod调度到具有该污点的Node上
NoExecute
- k8s将不会把Pod调度到有该污点的Node上,同时会将Node上已经存在的Pod驱逐
污点的设置和驱逐
# 设置污点
$ kubectl taint nodes k8s-node1 key1=value1:NoSchedule
$ kubectl taint nodes k8s-node1 type=master:NoExecute
# 节点说明中查找Taints字段
$ kubectl describe pod pod-name
# 去除污点
$ kubectl taint nodes k8s-node1 key1:NoSchedule-
3.3.2 容忍
设置了污点的 Node 将根据 taint 的 effect:NoSchedule、PreferNoSchedule、NoExecute 和 Pod 之间产生互斥的关系,Pod 将在一定程度上不会被调度到 Node 上。但我们可以在 Pod 上设置容忍,意思是设置了容忍的 Pod 将可以容忍污点的存在,可以被调度到存在污点的 Node 上。
pod.spec.tolerations
3.4 指定节点调度
3.4.1 Pod.spec.nodeName
将 Pod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规则是强制匹配。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myweb
spec:
replicas: 7
template:
metadata:
labels:
app: myweb
spec:
nodeName: k8s-node1
containers:
- name: myweb
image: devops.wangtianci/open/grafana:v8.45
ports:
- containerPort: 80
3.4.1 Pod.spec.nodeSelector
通过 kubernetes 的 label-selector 机制选择节点,由调度器调度策略匹配 label,而后调度 Pod 到目标节点,该匹配规则属于强制约束。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myweb
spec:
replicas: 2
template:
metadata:
labels:
app: myweb
spec:
nodeSelector:
type: BackendNode
containers:
- name: myweb
image: devops.wangtianci/open/grafana:v8.45
ports: 3000