5-Pod调度方式
5.Pod调度方式
自定义调度器
通过spec.schedulername参数指定调度器的名字,可以为pod选择my-scheduler进行调度,而不是默认的default-scheduler:
apiVersion: v1
kind: Pod
metadata:
name: annotation-second-scheduler
labels:
name: multischeduler-example
spec:
schedulername: my-scheduler
containers:
- name: pod-with-second-annotation-container
image: gcr.io/google_containers/pause:2.0
调度方法
1.nodeName
在pod.spec.nodeName字段指定节点名,该方法优先级最高
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: my-nginx
image: nginx
nodeName: node1
使用 nodeName 来选择节点的一些限制:
1.指定的节点可能不存在
2.指定的节点没有足够的资源来容纳 pod
3.云环境中的节点名称不固定
2.nodeSelector
该方式由kube-scheduler进程负责实现Pod的调度
实现NodeSelector(定向调度)需要两步
1、使用kubectl label给node节点打标签
kubectl get nodes --show-labels # 查看所有节点标签
kubectl get node node1 --show-labels # 查看指定节点标签
kubectl label node node2 disktype=ssd # 添加
kubectl label node node2 disktype- # 删除标签
2、在pod.spec.nodeSelector字段指定节点标签名
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: my-nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
如果给多个Node都定义了相同的标签,则scheduler会根据调度算法从这组Node中挑选一个可用的Node进行Pod调度
如果指定了Pod的nodeSelector条件,但是集群中不存在包含相应标签的Node,即使集群中还有其他可供使用的Node,这个Pod也无法被成功调度
3.****NodeAffinity:Node亲和性调度
* 两种节点亲和性表达方式,由此项声明pod.spec.affinity.nodeAffinity
preferredDuringSchedulingIgnoreDuringExecution 倾向满足,多个优先级规则还可以设置权重(weight)值,以定义执行的先后顺序
requiredDuringSchedulingIgnoreDuringExecution 必须满足
* 实现NodeAffinity(Node亲和性调度)需要两步:
* (1)通过kubectl label命令给目标Node打上一些标签。
* kubectl label nodes <node-name> <label-key>=<label-value>
* (2)在Pod的定义中加上nodeAffinity的设置。
* 使用规则
1.如果同时定义了nodeSelector和nodeAffinity, 那么必须两个条件都得到满足, Pod才能最终运行在指定的Node上。
2.如果在nodeAffinity指定了多个nodeSelectorTerms(指的是nodeSelectorTerms下面有多个matchExpressions),那么其中一个能够匹配成功即可。
3.如果在nodeSelectorTerms中指定了多个matchExpressions(指的是一个matchExpressions下面有多个key=value),则一个节点必须满足所有matchExpressions才能运行该Pod
* 字段的解释:
* key:选择器应用于的标签键。
* operator:表示一个键与一组值的关系。有效的操作符有In、NotIn、Exists、DoesNotExist、Gt和Lt。
In:label的值在某个列表中
NotIn:label的值不在某个列表中
Gt:label的值大于某个值
Lt:label的值小于某个值
Exists:某个label存在
DoesNotExist:某个label不存在
* values:
* 如果操作符是In或NotIn,值数组必须是非空的。
* 如果操作符是Exists或DoesNotExist,则值数组必须为空。
* 如果运算符是Gt或Lt,则值数组必须有一个元素,该元素将被解释为整数。
* 虽然没有节点排斥功能,但是用NotIn和DoesNotExist就可以实现排斥的功能了。
* weight:与对应的nodeSelectorTerm相匹配的权重,范围为1-100。
* 示例
设置NodeAffinity调度规则如下:
* requiredDuringSchedulingIgnoredDuringExecution要求只运行在有label是node-name=node1的节点上。
* preferredDuringSchedulingIgnoredDuringExecution的要求是尽量运行在label是disk=ssd的节点上。
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-nginx-deployment3
namespace: default
spec:
selector:
matchLabels:
app: test-nginx-pod
replicas: 2
template:
metadata:
labels:
app: test-nginx-pod
spec:
containers:
- name: test-nginx-container
image: nginx:latest
imagePullPolicy: Never
command: ["/usr/sbin/nginx", "-g", "daemon off;"]
ports:
- containerPort: 80
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-name
operator: In
values:
- node1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disk
operator: In
values:
- ssd
4.****PodAffinity:Pod亲和互斥调度策略
* 根据在节点上正在运行的Pod的标签而不是节点的标签进行判断和调度,要求对节点和Pod两个条件进行匹配。
* Pod亲和与互斥的条件设置(和节点亲和相同)
由此项声明pod.spec.affinity.podAffinity或pod.spec.affinity.podAntiAffinity
preferredDuringSchedulingIgnoreDuringExecution 倾向满足,多个优先级规则还可以设置权重(weight)值,以定义执行的先后顺序
requiredDuringSchedulingIgnoreDuringExecution 必须满足
* 实现PodAffinity(Pod亲和与互斥调度)需要两步:
* (1)选定要亲和或互斥的pod的标签(该标签只能存在该pod中)。
* (2)在Pod的定义中加上podAffinity或podAntiAffinity的设置。
* 理解pod亲和与互斥
1.podAffinity 主要解决Pod可以和哪些Pod部署在同一个拓扑域中的问题
2.podAntiAffinity 主要解决Pod不能和哪些Pod部署在同一个拓扑域中的问题
3.这种规则可以描述为:如果在具有标签X的Node上运行了一个或者多个符合条件Y的Pod,那么Pod应该(如果是互斥的情况,那么就变成拒绝)运行在这个Node上。
4.这里X指的是一个集群中的节点、机架、区域等概念,通过Kubernetes内置节点标签中的key来进行声明。这个key的名字为topologyKey,意为表达节点所属的topology范围
* 与节点不同的是,Pod是属于某个命名空间的,所以条件Y指的是一个或者全部命名空间中的一个Label Selector。
* 在Pod亲和性和RequiredDuringScheduling的Pod互斥性的定义中,不允许使用空的topologyKey。
* 如果Admission controller包含了LimitPodHardAntiAffinityTopology,那么针对RequiredDuringScheduling的Pod互斥性定义就被限制为kubernetes.io/hostname,要使用自定义的topologyKey,就要改写或禁用该控制器。
* 在PreferredDuringScheduling类型的Pod互斥性定义中,空的topologyKey会被解释为kubernetes.io/hostname、failuredomain.beta.kubernetes.io/zone及failuredomain.beta.kubernetes.io/region的组合。
* 如果不是上述情况,就可以采用任意合法的topologyKey了。
* PodAffinity规则设置的注意事项如下:
* 除了设置Label Selector和topologyKey,用户还可以指定Namespace列表来进行限制,同样,使用Label Selector对Namespace进行选择。Namespace的定义和Label Selector及topologyKey同级。省略Namespace的设置,表示使用定义了affinity/anti-affinity的Pod所在的Namespace。如果Namespace被设置为空值(""),则表示所有Namespace。
* 在所有关联requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全都满足之后,系统才能将Pod调度到某个Node上。
* 与节点亲和性类似,Pod亲和性的操作符也包括In、NotIn、Exists、DoesNotExist、Gt、Lt。
* 示例
# 如下是新建立的pod,这里使用的亲和标签是app=nginx-pod,该pod会被尽量调度到有相同标签的pod所在的节点上,topologyKey的值被设置为“kubernetes.io/hostname”
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: mysql-pod
spec:
containers:
- name: mysql
image: mysql
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx-pod
topologyKey: kubernetes.io/hostname
namespace: xxxxxx
# 如下是新建立的pod,这里使用的亲和标签是app=nginx-pod,该pod一定要调度到有相同标签的pod所在的节点上,topologyKey的值被设置为“kubernetes.io/hostname”
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx-pod
topologyKey: kubernetes.io/hostname
namespace: xxxxxxx
# 如下是新建立的pod,这里使用的互斥标签是app=nginx-pod,该pod会被尽量调度到有相同标签的pod所在的节点上,topologyKey的值被设置为“kubernetes.io/hostname”
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoreDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- pod-2
topologyKey: kubernetes.io/hostname
namespace: xxxxxxx
# 如下是新建立的pod,这里使用的互斥标签是app=nginx-pod,该pod一定要调度到有相同标签的pod所在的节点上,topologyKey的值被设置为“kubernetes.io/hostname”
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx-pod
topologyKey: kubernetes.io/hostname
namespace: xxxxxxx
5.Taints和Tolerations:污点与容忍
Taint让Node拒绝Pod的在其上运行,除非Pod明确声明能够容忍这污点。
污点格式
key=value:effect
1.污点由一个key和value构成,value可以为空,effect描述污点的作用。
2.effect选项包括:
NoSchedule:k8s不会将pod调度到具有该污点的Node上
PreferNoSchedule:k8s尽量避免将pod调度到具有该污点的node上
NoExecute:k8s不会将pod调度到具有该污点的node上,如果pod已经在node上(且没有设置tolerations),pod将被驱逐出去
污点的设置、查看和去除
语法
kubectl taint node node名称 键名=键值:选项
# 在节点"k8s-node"添加污点,键为"dedicated",值为"special-user",效果为"NoSchedule"。
kubectl taint nodes k8s-node dedicated=special-user:NoSchedule
# 在标签有mylabel=X的节点上添加一个键为'dedicated'的污点
kubectl taint node -l myLabel=X dedicated=foo:PreferNoSchedule
查看污点,需要查看节点的说明,在其中查找taints字段
kubectl describe pod pod名称 | grep -A 5 Taints
kubectl get nodes k8s-node1 -o go-template={{.spec.taints}}
kubectl describe node k8s-node
for i in $(kubectl get nodes -o name | awk -F'/' '{print $2}');do echo "$i:";kubectl describe nodes $i | grep 'Taints:';done
去除污点
kubectl taint node node名称 键名:选项-(注意选项后的减号)(写上键值也行)
# 从节点'k8s-node'中删除键为'dedicated'并效果为'NoSchedule'的污点(如果存在的话)
kubectl taint nodes k8s-node dedicated:NoSchedule-
# 从节点"k8s-node"中删除键为'dedicated'的所有污点
kubectl taint nodes k8s-node dedicated-
容忍(Tolerations)
设置了容忍的pod将可以容忍污点的存在,可以被调度到存在污点的node上
* 实现pod要容忍Taints(污点)需要两步:
* (1)选定node,查看其上的Taints(污点)。
* (2)在Pod的定义中加tolerations,容忍node上的Taints。
tolerations的定义语法
* Toleration声明中的指令(kubectl explain pods.spec.tolerations):
* key:key是污点的键(taint key)(需要与Taint的设置保持一致)。
* 空的key配合Exists操作符能够匹配所有的键和值。
* effect:表示要匹配的污点效果(需要与Taint的设置保持一致)。
* 当指定时,允许的值是NoSchedule、PreferNoSchedule和NoExecute。
* 空的effect匹配所有的effect。
* operator:如果不指定operator,则默认值为Equal。
* operator的值是Equal,并且value的值需要与Taint设置的值相等。
* operator的值是Exists(无须指定value)。
* value:Value是污点的值(taint value)。
* tolerationSeconds:表示容忍(必须是NoExecute才生效,否则将忽略此字段)污点的时间段。
* 默认情况下,即没有设置,这意味着永远容忍污点(不要驱逐)。
* 0和负值将被系统视为0(立即驱逐)
* 效果是NoExecute的Taint(污点),对节点上正在运行的Pod有以下影响:
* 没有设置对应Toleration的Pod会被立刻驱逐。
* 配置了对应Toleration的Pod,如果没有为tolerationSeconds赋值,则会一直留在这一节点上。
* 配置了对应Toleration的Pod,且指定了tolerationSeconds值,则会在指定时间后驱逐。
示例
# pod可以在有污点key2=valuel:NoExecute的节点上运行3600s。如果超过这个时间就会被驱逐。
# 如果在此期间node的污点被移除,pod可以继续在node上运行
pod.spec.tolerations
tolerations:
- key: "key2"
value: "value1"
operator: "Equal"
effect: "NoExecute"
tolerationSeconds: 3600 # 貌似只有effect为NoExecute才能设置teolerationSeconds
# pod可以容忍节点上有键为key3,效果为NoSchedule的污点
tolerations:
- key: "key3"
operator: "Exists"
effect: "NoSchedule"
注意:
1.operator的值可以为Exists或Equal,都表示容忍
2.为Equal时要求key,value,effect的值与node上设置的taint保持一致
3.为Exists时要求key、effect要与node上设置的taint保持一致,value可以省略
4.tolerationSeconds用于指定当pod需要被驱逐时(effect为NoExecute)可以继续在pod上保留的时间
5.不指定operator的属性,默认值为Equal
6.不指定key,operator为Exists时,表示容忍所有污点
7.不指定effect时,表示匹配所有effect
8.tolerations中的所有键值,要有双引号
Master节点不参与调度是因为Master节点在创建时有污点 node-role.kubernetes.io/master:NoSchedule
有多个Master存在时,为防止资源浪费,可以如下设置
kubectl taint node node名称 node-role.kubernetes.io/master=:PreferNoSchedule
* 多个Taints和Tolerations的使用
* 在同一个Node上可以设置多个Taint,也可以在Pod上设置多个Toleration。Kubernetes调度器处理多个Taint和Toleration的逻辑顺序为:
* 首先列出节点中所有的Taint,然后忽略Pod的Toleration能够匹配的部分,剩下的没有忽略的Taint就是对Pod的效果了。
* 下面是几种特殊情况。
* 如果在剩余的Taint中存在effect=NoSchedule,则调度器不会把该Pod调度到这一节点上。
* 如果在剩余的Taint中没有NoSchedule效果,但是有PreferNoSchedule效果,则调度器会尝试不把这个Pod指派给这个节点。
* 如果在剩余的Taint中有NoExecute效果,并且这个Pod已经在该节点上运行,则会被驱逐;如果没有在该节点上运行,则也不会再被调度到该节点上。
6.deployment自动调度
详见其他笔记
cordon、drain、delete
cordon 暂停调度
作用:将node调为SchedulingDisabled状态,该状态下新创建的Pod不会被调度到该节点。节点中原有Pod不受影响,仍正常对外提供服务
kubectl cordon node2 # 暂停node2的调度
kubectl uncordon node2 # 恢复node2的调度
drain 驱逐节点
作用:首先驱逐node上的Pod,并在其他节点上重新创建,然后将节点调为SchedulingDisabled状态
kubectl drain node2 --ignore-daemonsets
kubectl uncordon node2 # 恢复node2的调度
delete 删除节点
作用:首先驱逐node上的pod,在其他节点重新创建,然后从master节点删除该node,master失去对其的控制,如要恢复调度,需进入node节点,重启kubelet服务
kubectl delete node node2
systemctl restart kubelet # 需要恢复的话,就需要重启kubelet
分类:
K8S
, K8S / K8S-03-Pod
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了