5-Pod调度方式
调度方式总结
- 指定nodeName调度pod
- 使用节点选择器(nodeSelector)调度pod
- NodeAffinity:Node亲和性调度
- Pod 亲和性/反亲和性(podAffinity/podAntiAffinity)调度策略
- Taints和Tolerations:污点与容忍
- 自定义调度器实现Pod调度
指定nodeName调度pod
- 在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.云环境中的节点名称不固定
使用节点选择器(nodeSelector)调度pod
该方式由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也无法被成功调度
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
Pod 亲和性/反亲和性(podAffinity/podAntiAffinity)调度策略
1. 核心概念
- Pod 亲和性(Affinity)与反亲和性(Anti-Affinity)用于控制 Pod 之间的调度关系,解决 Pod 应该或不应该与哪些 Pod 部署在同一个拓扑域中的问题。
- Pod 亲和性 (PodAffinity):让 Pod 倾向于与符合条件的其他 Pod 部署在一起(例如:将 Web 服务和缓存服务部署在同一节点)。
- Pod 反亲和性 (PodAntiAffinity):让 Pod 避免与符合条件的其他 Pod 部署在一起(例如:将同一个应用的多个副本分散在不同节点以实现高可用)。
2. 调度规则类型
- 规则分为“硬性要求”和“软性倾向”两种,通过 pod.spec.affinity 字段配置。
- 硬性要求 requiredDuringSchedulingIgnoredDuringExecution 必须满足。只有满足条件,Pod 才会被调度到该节点;否则 Pod 将处于 Pending 状态。
- 软性倾向 preferredDuringSchedulingIgnoredDuringExecution 尽量满足。调度器会尝试满足条件,但如果无法满足,Pod 仍然会被调度。可为多个规则设置 weight(权重)来定义优先级。
- IgnoredDuringExecution 的含义:无论是硬性还是软性规则,一旦 Pod 被成功调度并运行起来,即使后续集群状态发生变化导致规则不再满足,已运行的 Pod 也不会被驱逐或重新调度。
3. 实现原理与关键配置
- 实现 Pod 亲和/反亲和性需要同时匹配两个条件:
- 目标 Pod 的条件 (Y):通过 labelSelector 定义,用于找到集群中已经存在的、作为参照物的 Pod。
- 拓扑域的范围 (X):通过 topologyKey 定义,用于指定在哪个范围内进行亲和或反亲和。
- 调度逻辑: 如果在具有标签 X 的 Node 上,运行了一个或多个符合 labelSelector 条件 Y 的 Pod,那么新的 Pod 就应该(亲和)或拒绝(反亲和)被调度到这个 Node 上。
关键字段说明
- topologyKey:节点的标签键(Key),代表一个拓扑域,如节点、机架、区域等。
- kubernetes.io/hostname:表示单个节点。
- topology.kubernetes.io/zone:表示一个可用区。
- topology.kubernetes.io/region:表示一个地理区域。
- 注意:failuredomain.beta.kubernetes.io/zone 和 failuredomain.beta.kubernetes.io/region 是已被废弃的旧标签。
- labelSelector:一个标签选择器,用于匹配目标 Pod。
- namespaces:一个命名空间列表,用于限定 labelSelector 的搜索范围。
- 如果省略,则默认为定义亲和性规则的 Pod 所在的命名空间。
- 如果设置为空字符串 "",则表示在所有命名空间中搜索。
4. topologyKey 配置规则与限制
- topologyKey 是一个节点标签的键(Key)。Kubernetes 调度器会读取集群中所有节点的标签,根据这个键对应的值,把节点划分到不同的“拓扑域”中。有它指定的标签的节点,才有资格称为pod被调度的候选节点
- 对于硬性要求(requiredDuringScheduling):topologyKey 不允许为空。
- 如果集群启用了 LimitPodHardAntiAffinityTopology 准入控制器,那么 topologyKey 被强制限制为 kubernetes.io/hostname。若想使用自定义的 topologyKey,需要修改或禁用该控制器。
- 如果 topologyKey 为空,它会被解释为 kubernetes.io/hostname、topology.kubernetes.io/zone 和 topology.kubernetes.io/region 的组合。
5. 操作符
- 与节点亲和性类似,labelSelector 支持以下操作符:
- 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
Taints和Tolerations:污点与容忍
- Taint的作用是让Node拒绝Pod的在其上运行,除非Pod明确声明能够容忍这污点。
污点格式
key=value:effect
1.污点由一个key和value构成,value可以为空,effect描述污点的作用。
2.effect选项包括:
NoSchedule:新pod不会被调度到具有该污点的Node上,如果node上已经有pod不会驱逐
PreferNoSchedule:k8s尽量避免将pod调度到具有该污点的node上
NoExecute:新pod不会被调度到具有该污点的Node上,如果node上已经有pod不会驱逐。除非pod有设置tolerations
操作污点
设置污点
- Key 应表达"节点属性"而非"业务需求"
- GPU 专用节点 hardware-type=gpu
- 金融合规节点 compliance=pci-dss
- 高内存节点 resource-tier=high-mem
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字段
# 查看node01的污点
kubectl get nodes node01 -o go-template={{.spec.taints}}
# 或者
kubectl describe node node01 | grep -A 5 Taint
# 找到pod所在节点,再查找节点的污点
kubectl get node $(kubectl get pod <pod名称> -o jsonpath='{.spec.nodeName}') -o jsonpath='{.spec.taints}' | jq .
去除污点
kubectl taint node node名称 key:effect-(注意effect后的减号)(value可以省略)
# 从节点'k8s-node'中删除键为'dedicated'并效果为'NoSchedule'的污点(如果存在的话)
kubectl taint nodes k8s-node dedicated:NoSchedule-
# 从节点"k8s-node"中删除键为'dedicated'的所有污点
kubectl taint nodes k8s-node dedicated-
容忍(Tolerations)
- 设置了容忍的pod将可以容忍污点的存在,可以被调度到存在污点的node上
实现容忍
- tolerations的语法。kubectl explain pods.spec.tolerations可以查看结构
- key:匹配污点键。空值配合 operator: Exists 可匹配所有键
- value:匹配污点值
- effect:匹配污点效果。可选值:NoSchedule、PreferNoSchedule、NoExecute。空值表示匹配所有效果
- operator:可选值有Equal、Exists。如果不指定则默认值为Equal。此时需要key、value、effect完全相等。如果设置为Exists无需指定 value,key 和 effect 匹配即可。
- tolerationSeconds:仅对 NoExecute 有效,指定容忍时间(秒)。未设置或负值视为永久容忍。
# pod可以在有污点key2=value1:NoExecute的节点上运行3600s。超时间会被驱逐。如果在此期间node的污点被移除,pod可以继续在node上运行
pod.spec.tolerations
tolerations:
- key: "key2"
value: "value1"
operator: "Equal"
effect: "NoExecute"
tolerationSeconds: 3600
# pod可以容忍节点上有键为key3,效果为NoSchedule的污点
tolerations:
- key: "key3"
operator: "Exists"
effect: "NoSchedule"
- Master节点不参与调度是因为Master节点在创建时有以下污点:
node-role.kubernetes.io/control-plane: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的效果了。
自定义调度器实现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

浙公网安备 33010602011771号