调度 是指将 Pod 放置到合适的 Node 上,然后对应 Node 上的 Kubelet 才能够运行这些 pod。
调度概览
调度器通过 kubernetes 的监测(Watch)机制来发现集群中新创建且尚未被调度到 Node 上的 Pod。 调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行。 调度器会依据下文的调度原则来做出调度选择。
kube-scheduler调度流程
kube-scheduler 给一个 pod 做调度选择包含两个步骤:
- 过滤
- 打分
过滤阶段会将所有满足 Pod 调度需求的 Node 选出来。
打分阶段,调度器会为 Pod 从所有可调度节点打分选取一个最合适的 Node。
NodeSelector定向调度
NodeSelector:是一个供用户将 Pod 与 Node 进行绑定的字段.
apiVersion: v1
kind: Pod
...
spec:
nodeSelector:
disktype: ssd
指明Pod永远只能运行在携带“disktype: ssd”标签的节点上;否则会调度失败
Kubernetes内置的节点标签
除了你给Node(节点)
添加标签外,Kubernetes也会给Node
预设义一些标签,包括:
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
edgenode=true
kubernetes.io/arch=amd64
kubernetes.io/hostname=ycloud
kubernetes.io/os=linux
node-role.kubernetes.io/control-plane=
node-role.kubernetes.io/master=
node.kubernetes.io/exclude-from-external-load-balancers=
注意:这些标签的值是特定于云提供商
的,不保证是可靠的。例如,kubernetes.io/hostname
的值可能与某些环境中的节点名称相同,而在其他环境中就不同了。
nodeName调度
nodeName是最简单的节点选择约束方式,我常常用它来将pod直接指定到某台节点上,进行测试。
<!--注意:如果它不为空,则调度程序不会在调度这个pod了,并且在命名节点上运行的kubelet尝试运行该pod。因此,如果在PodSpec中提供nodeName,则它将优先于其他的约束。-->
apiVersion: v1
kind: Pod
...
spec:
nodeName: ycloud
该pod将运行在名为ycloud的节点上了
Node Affinity
用节点亲和性把 Pods 分配到节点
依据强制的节点亲和性调度 Pod
下面清单描述了一个 Pod,它有一个节点亲和性配置 requiredDuringSchedulingIgnoredDuringExecution
,disktype=ssd
。 这意味着 pod 只会被调度到具有 disktype=ssd
标签的节点上。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
使用首选的节点亲和性调度 Pod
本清单描述了一个Pod,它有一个节点亲和性设置 preferredDuringSchedulingIgnoredDuringExecution
,disktype: ssd
。 这意味着 pod 将首选具有 disktype=ssd
标签的节点。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Taint和Toleration(污点和容忍)
节点亲和性是pod
的一种属性(优先选择或硬性要求),它使 pod 被优先分配到一类特定的节点上。而Taint
则相反,它使节点
能够排斥
一类特定的 pod。
使用kubectl taint给节点增加一个污点
[root@ycloud ~]# kubectl taint nodes ycloud app=test:NoSchedule
node/ycloud tainted
若要移除这个污点
[root@ycloud ~]# kubectl taint nodes ycloud app=test:NoSchedule-
node/ycloud untainted
你可以在 Pod 规约中为 Pod 设置容忍度。 下面两个容忍度均与上面例子中使用 kubectl taint
命令创建的污点相匹配, 因此如果一个 Pod 拥有其中的任何一个容忍度,都能够被调度到 node
:
tolerations:
- key: "app"
operator: "Equal"
value: "test"
effect: "NoSchedule"
tolerations:
- key: "app"
operator: "Exists"
effect: "NoSchedule"
例子:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: "app"
operator: "Exists"
effect: "NoSchedule"
operator
的默认值是 Equal
。
一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,并且:
- 如果
operator
是Exists
(此时容忍度不能指定value
),或者 - 如果
operator
是Equal
,则它们的value
应该相等
参考文献
https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/kube-scheduler/
https://kuboard.cn/learning/k8s-advanced/schedule/#filtering